Merge "Game Driver: process sphal libraries in GPU service"
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java b/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
index e417ca7..c1362dc 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
@@ -60,11 +60,13 @@
if (size == 0) {
return 0f;
}
- Collections.sort(mResults);
+
+ final ArrayList<Long> resultsCopy = new ArrayList<>(mResults);
+ Collections.sort(resultsCopy);
final int idx = size / 2;
return size % 2 == 0
- ? (double) (mResults.get(idx) + mResults.get(idx - 1)) / 2
- : mResults.get(idx);
+ ? (double) (resultsCopy.get(idx) + resultsCopy.get(idx - 1)) / 2
+ : resultsCopy.get(idx);
}
private double standardDeviation() {
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
index 2cdf54b..4d22d0b 100644
--- a/api/TEST_MAPPING
+++ b/api/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "CtsCurrentApiSignatureTestCases"
},
{
+ "name": "CtsSystemApiSignatureTestCases"
+ },
+ {
"name": "GtsUnofficialApisUsageTestCases"
}
]
diff --git a/api/current.txt b/api/current.txt
index f31dfff..343fbd9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5473,11 +5473,12 @@
public static final class Notification.BubbleMetadata implements android.os.Parcelable {
method public int describeContents();
method public boolean getAutoExpandBubble();
+ method public android.app.PendingIntent getDeleteIntent();
method public int getDesiredHeight();
method public android.graphics.drawable.Icon getIcon();
method public android.app.PendingIntent getIntent();
method public boolean getSuppressInitialNotification();
- method public CharSequence getTitle();
+ method @Deprecated public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR;
}
@@ -5486,11 +5487,12 @@
ctor public Notification.BubbleMetadata.Builder();
method public android.app.Notification.BubbleMetadata build();
method public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent);
method public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
method public android.app.Notification.BubbleMetadata.Builder setIcon(android.graphics.drawable.Icon);
method public android.app.Notification.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
method public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
- method public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
+ method @Deprecated public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
}
public static class Notification.Builder {
@@ -6662,7 +6664,7 @@
method public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName);
method public int getPasswordQuality(@Nullable android.content.ComponentName);
method @Nullable public android.app.admin.SystemUpdateInfo getPendingSystemUpdate(@NonNull android.content.ComponentName);
- method public int getPermissionGrantState(@Nullable android.content.ComponentName, String, String);
+ method public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
method public int getPermissionPolicy(android.content.ComponentName);
method @Nullable public java.util.List<java.lang.String> getPermittedAccessibilityServices(@NonNull android.content.ComponentName);
method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
@@ -6773,7 +6775,7 @@
method public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int);
method public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int);
method public void setPasswordQuality(@NonNull android.content.ComponentName, int);
- method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, String, String, int);
+ method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, @NonNull String, @NonNull String, int);
method public void setPermissionPolicy(@NonNull android.content.ComponentName, int);
method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
@@ -11473,7 +11475,6 @@
method public void setAppIcon(@Nullable android.graphics.Bitmap);
method public void setAppLabel(@Nullable CharSequence);
method public void setAppPackageName(@Nullable String);
- method public void setInstallAsApex();
method public void setInstallLocation(int);
method public void setInstallReason(int);
method public void setMultiPackage();
@@ -24012,8 +24013,8 @@
method public int getMaxImages();
method public android.view.Surface getSurface();
method public int getWidth();
- method public static android.media.ImageReader newInstance(int, int, int, int);
- method public static android.media.ImageReader newInstance(int, int, int, int, long);
+ method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int);
+ method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);
method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
}
@@ -24026,8 +24027,8 @@
method public android.media.Image dequeueInputImage();
method public int getFormat();
method public int getMaxImages();
- method public static android.media.ImageWriter newInstance(android.view.Surface, int);
- method public static android.media.ImageWriter newInstance(android.view.Surface, int, int);
+ method @NonNull public static android.media.ImageWriter newInstance(@NonNull android.view.Surface, @IntRange(from=1) int);
+ method @NonNull public static android.media.ImageWriter newInstance(@NonNull android.view.Surface, @IntRange(from=1) int, int);
method public void queueInputImage(android.media.Image);
method public void setOnImageReleasedListener(android.media.ImageWriter.OnImageReleasedListener, android.os.Handler);
}
@@ -27456,6 +27457,7 @@
method @Nullable public CharSequence getQueueTitle();
method public int getRatingType();
method @Nullable public android.app.PendingIntent getSessionActivity();
+ method @Nullable public android.os.Bundle getSessionInfo();
method @NonNull public android.media.session.MediaSession.Token getSessionToken();
method @NonNull public android.media.session.MediaController.TransportControls getTransportControls();
method public void registerCallback(@NonNull android.media.session.MediaController.Callback);
@@ -27515,6 +27517,7 @@
public final class MediaSession {
ctor public MediaSession(@NonNull android.content.Context, @NonNull String);
+ ctor public MediaSession(@NonNull android.content.Context, @NonNull String, @Nullable android.os.Bundle);
method @NonNull public android.media.session.MediaController getController();
method @NonNull public android.media.session.MediaSessionManager.RemoteUserInfo getCurrentControllerInfo();
method @NonNull public android.media.session.MediaSession.Token getSessionToken();
@@ -29985,7 +29988,7 @@
method @Deprecated public boolean reconnect();
method @Deprecated public boolean removeNetwork(int);
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
- method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public void removePasspointConfiguration(String);
+ method @Deprecated @RequiresPermission("android.permission.NETWORK_SETTINGS") public void removePasspointConfiguration(String);
method @Deprecated public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -43337,11 +43340,11 @@
public final class CallIdentification implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public String getCallScreeningAppName();
+ method @NonNull public CharSequence getCallScreeningAppName();
method @NonNull public String getCallScreeningPackageName();
- method @Nullable public String getDescription();
- method @Nullable public String getDetails();
- method @Nullable public String getName();
+ method @Nullable public CharSequence getDescription();
+ method @Nullable public CharSequence getDetails();
+ method @Nullable public CharSequence getName();
method public int getNuisanceConfidence();
method @Nullable public android.graphics.drawable.Icon getPhoto();
method public void writeToParcel(android.os.Parcel, int);
@@ -43356,9 +43359,9 @@
public static class CallIdentification.Builder {
ctor public CallIdentification.Builder();
method public android.telecom.CallIdentification build();
- method public android.telecom.CallIdentification.Builder setDescription(@Nullable String);
- method public android.telecom.CallIdentification.Builder setDetails(@Nullable String);
- method public android.telecom.CallIdentification.Builder setName(@Nullable String);
+ method public android.telecom.CallIdentification.Builder setDescription(@Nullable CharSequence);
+ method public android.telecom.CallIdentification.Builder setDetails(@Nullable CharSequence);
+ method public android.telecom.CallIdentification.Builder setName(@Nullable CharSequence);
method public android.telecom.CallIdentification.Builder setNuisanceConfidence(int);
method public android.telecom.CallIdentification.Builder setPhoto(@Nullable android.graphics.drawable.Icon);
}
@@ -45190,6 +45193,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
method public boolean isHearingAidCompatibilitySupported();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isMultisimSupported();
method public boolean isNetworkRoaming();
method public boolean isRttSupported();
method public boolean isSmsCapable();
@@ -47475,6 +47479,7 @@
method public int getVerticalAlignment();
field public static final int ALIGN_BASELINE = 1; // 0x1
field public static final int ALIGN_BOTTOM = 0; // 0x0
+ field public static final int ALIGN_CENTER = 2; // 0x2
field protected final int mVerticalAlignment;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index cf933dc..b7f435a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -15,6 +15,7 @@
field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
+ field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
@@ -1557,6 +1558,7 @@
method public void setDontKillApp(boolean);
method public void setEnableRollback();
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
@@ -1575,6 +1577,7 @@
method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(String);
+ method public boolean getAppDetailsActivityEnabled(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.dex.ArtManager getArtManager();
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
@@ -1601,6 +1604,7 @@
method @Deprecated public void replacePreferredActivity(@NonNull android.content.IntentFilter, int, @NonNull java.util.List<android.content.ComponentName>, @NonNull android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method public void sendDeviceCustomizationReadyBroadcast();
+ method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setAppDetailsActivityEnabled(@NonNull String, boolean);
method @RequiresPermission(allOf={android.Manifest.permission.SET_PREFERRED_APPLICATIONS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public abstract boolean setDefaultBrowserPackageNameAsUser(String, int);
method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setDistractingPackageRestrictions(@NonNull String[], int);
method @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public void setHarmfulAppWarning(@NonNull String, @Nullable CharSequence);
@@ -3036,21 +3040,21 @@
method public double getHorizontalPositionUncertaintyMeters();
method public double getLatitudeDegrees();
method public double getLongitudeDegrees();
- method @Nullable public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatCorrectionList();
+ method @Nullable public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
method public long getToaGpsNanosecondsOfWeek();
method public double getVerticalPositionUncertaintyMeters();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
}
- public static class GnssMeasurementCorrections.Builder {
+ public static final class GnssMeasurementCorrections.Builder {
ctor public GnssMeasurementCorrections.Builder();
method public android.location.GnssMeasurementCorrections build();
method public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(double);
method public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(double);
method public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(double);
method public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(double);
- method public android.location.GnssMeasurementCorrections.Builder setSingleSatCorrectionList(@Nullable java.util.List<android.location.GnssSingleSatCorrection>);
+ method public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@Nullable java.util.List<android.location.GnssSingleSatCorrection>);
method public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(long);
method public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(double);
}
@@ -3065,7 +3069,7 @@
field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
}
- public static class GnssReflectingPlane.Builder {
+ public static final class GnssReflectingPlane.Builder {
ctor public GnssReflectingPlane.Builder();
method public android.location.GnssReflectingPlane build();
method public android.location.GnssReflectingPlane.Builder setAltitudeMeters(double);
@@ -3080,14 +3084,14 @@
method public int getConstellationType();
method public float getExcessPathLengthMeters();
method public float getExcessPathLengthUncertaintyMeters();
- method @FloatRange(from=0.0f, to=1.0f) public float getProbSatIsLos();
+ method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
method @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
- method public int getSatId();
- method public int getSingleSatCorrectionFlags();
+ method public int getSatelliteId();
+ method public int getSingleSatelliteCorrectionFlags();
method public boolean hasExcessPathLength();
method public boolean hasExcessPathLengthUncertainty();
method public boolean hasReflectingPlane();
- method public boolean hasSatelliteLineOfSight();
+ method public boolean hasValidSatelliteLineOfSight();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
field public static final int HAS_EXCESS_PATH_LENGTH_MASK = 2; // 0x2
@@ -3096,17 +3100,17 @@
field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8
}
- public static class GnssSingleSatCorrection.Builder {
+ public static final class GnssSingleSatCorrection.Builder {
ctor public GnssSingleSatCorrection.Builder();
method public android.location.GnssSingleSatCorrection build();
method public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(float);
method public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(float);
method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(float);
- method public android.location.GnssSingleSatCorrection.Builder setProbSatIsLos(@FloatRange(from=0.0f, to=1.0f) float);
+ method public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
method public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(android.location.GnssReflectingPlane);
- method public android.location.GnssSingleSatCorrection.Builder setSatId(int);
- method public android.location.GnssSingleSatCorrection.Builder setSingleSatCorrectionFlags(int);
+ method public android.location.GnssSingleSatCorrection.Builder setSatelliteId(int);
+ method public android.location.GnssSingleSatCorrection.Builder setSingleSatelliteCorrectionFlags(int);
}
public class GpsClock implements android.os.Parcelable {
@@ -4664,7 +4668,10 @@
}
public class WifiInfo implements android.os.Parcelable {
+ method @Nullable public String getFqdn();
+ method @Nullable public String getProviderFriendlyName();
method public boolean isOsuAp();
+ method public boolean isPasspointAp();
}
public class WifiManager {
@@ -5537,6 +5544,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
method public boolean hasRestrictedProfiles();
@@ -5547,6 +5555,8 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(android.graphics.Bitmap);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(String);
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -5623,6 +5633,7 @@
method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream);
method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String);
method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String);
+ method public abstract boolean onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int);
field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
}
@@ -6385,20 +6396,12 @@
package android.service.contentcapture {
- @Deprecated public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
- }
-
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
- method @Deprecated public void onContentCaptureEventsRequest(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.ContentCaptureEventsRequest);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
@@ -7920,7 +7923,6 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCurrentPotentialEmergencyNumber(@NonNull String);
method public boolean isDataConnectivityPossible();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMultisimCarrierRestricted();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRebootRequiredForModemConfigChange();
diff --git a/api/test-current.txt b/api/test-current.txt
index 01f4a2f..ba497d4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17,6 +17,10 @@
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
}
+ public static final class R.bool {
+ field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004
+ }
+
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
@@ -48,6 +52,7 @@
method public long getTotalRam();
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
+ method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
}
@@ -94,6 +99,31 @@
field public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; // 0x0
}
+ public class ActivityView extends android.view.ViewGroup {
+ ctor public ActivityView(android.content.Context);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet, int);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet, int, boolean);
+ method public void onLayout(boolean, int, int, int, int);
+ method public void onLocationChanged();
+ method public void performBackPress();
+ method public void release();
+ method public void setCallback(android.app.ActivityView.StateCallback);
+ method public void setForwardedInsets(android.graphics.Insets);
+ method public void startActivity(@NonNull android.content.Intent);
+ method public void startActivity(@NonNull android.content.Intent, android.os.UserHandle);
+ method public void startActivity(@NonNull android.app.PendingIntent);
+ }
+
+ public abstract static class ActivityView.StateCallback {
+ ctor public ActivityView.StateCallback();
+ method public abstract void onActivityViewDestroyed(android.app.ActivityView);
+ method public abstract void onActivityViewReady(android.app.ActivityView);
+ method public void onTaskCreated(int, android.content.ComponentName);
+ method public void onTaskMovedToFront(int);
+ method public void onTaskRemovalStarted(int);
+ }
+
public class AppDetailsActivity extends android.app.Activity {
ctor public AppDetailsActivity();
}
@@ -483,6 +513,17 @@
package android.content {
+ public final class AutofillOptions implements android.os.Parcelable {
+ ctor public AutofillOptions(int, boolean);
+ method public int describeContents();
+ method public static android.content.AutofillOptions forWhitelistingItself();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
+ field public boolean augmentedEnabled;
+ field public final boolean compatModeEnabled;
+ field public final int loggingLevel;
+ }
+
public final class ContentCaptureOptions implements android.os.Parcelable {
ctor public ContentCaptureOptions(int, int, int, int, int, @Nullable android.util.ArraySet<android.content.ComponentName>);
method public int describeContents();
@@ -507,12 +548,17 @@
public abstract class Context {
method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.view.Display getDisplay();
method public android.os.UserHandle getUser();
method public int getUserId();
- method public void setAutofillCompatibilityEnabled(boolean);
+ method public void setAutofillOptions(@Nullable android.content.AutofillOptions);
method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
}
+ public class ContextWrapper extends android.content.Context {
+ method public android.view.Display getDisplay();
+ }
+
}
package android.content.pm {
@@ -958,6 +1004,50 @@
}
+package android.metrics {
+
+ public class LogMaker {
+ ctor public LogMaker(int);
+ ctor public LogMaker(Object[]);
+ method public android.metrics.LogMaker addTaggedData(int, Object);
+ method public android.metrics.LogMaker clearCategory();
+ method public android.metrics.LogMaker clearPackageName();
+ method public android.metrics.LogMaker clearSubtype();
+ method public android.metrics.LogMaker clearTaggedData(int);
+ method public android.metrics.LogMaker clearType();
+ method public void deserialize(Object[]);
+ method public int getCategory();
+ method public long getCounterBucket();
+ method public String getCounterName();
+ method public int getCounterValue();
+ method public String getPackageName();
+ method public int getProcessId();
+ method public int getSubtype();
+ method public Object getTaggedData(int);
+ method public long getTimestamp();
+ method public int getType();
+ method public int getUid();
+ method public boolean isLongCounterBucket();
+ method public boolean isSubsetOf(android.metrics.LogMaker);
+ method public boolean isValidValue(Object);
+ method public Object[] serialize();
+ method public android.metrics.LogMaker setCategory(int);
+ method public android.metrics.LogMaker setPackageName(String);
+ method public android.metrics.LogMaker setSubtype(int);
+ method public android.metrics.LogMaker setType(int);
+ }
+
+ public class MetricsReader {
+ ctor public MetricsReader();
+ method public void checkpoint();
+ method public boolean hasNext();
+ method public android.metrics.LogMaker next();
+ method public void read(long);
+ method public void reset();
+ }
+
+}
+
package android.net {
public class CaptivePortal implements android.os.Parcelable {
@@ -1302,6 +1392,7 @@
public class Build {
method public static boolean is64BitAbi(String);
+ field public static final boolean IS_EMULATOR;
}
public static class Build.VERSION {
@@ -1882,6 +1973,7 @@
field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
field public static final String LOW_POWER_MODE = "low_power";
field public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
+ field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SMS_ACCESS_RESTRICTION_ENABLED = "sms_access_restriction_enabled";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
@@ -1900,6 +1992,7 @@
field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled";
field public static final String DISABLED_PRINT_SERVICES = "disabled_print_services";
field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
+ field public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
field public static final String NOTIFICATION_BADGING = "notification_badging";
@@ -2126,20 +2219,12 @@
package android.service.contentcapture {
- @Deprecated public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
- }
-
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
- method @Deprecated public void onContentCaptureEventsRequest(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.ContentCaptureEventsRequest);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
@@ -2388,6 +2473,10 @@
method public E valueAtUnchecked(int);
}
+ public class TimeUtils {
+ method public static String formatDuration(long);
+ }
+
}
package android.util.proto {
@@ -2609,6 +2698,10 @@
field public static final int CALLBACK_ANIMATION = 1; // 0x1
}
+ public final class Display {
+ method public boolean supportsSystemDecorations();
+ }
+
public class FocusFinder {
method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 62926cb..78e994f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5455,7 +5455,7 @@
HEADER_GO_TO_SETTINGS = 9;
PERMISSION_OPT_IN = 10;
PERMISSION_OPT_OUT = 11;
- PERMISSION_IGNORED = 12;
+ PERMISSION_DIALOG_SHOWN = 12;
SWIPE_LEFT = 13;
SWIPE_RIGHT = 14;
STACK_EXPANDED = 15;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index d661ee8..71d39ff 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -493,6 +493,11 @@
getAtomMetricStats(metricId).invalidatedBucket++;
}
+void StatsdStats::noteBucketCount(int64_t metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).bucketCount++;
+}
+
void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs) {
lock_guard<std::mutex> lock(mLock);
AtomMetricStats& pullStats = getAtomMetricStats(metricId);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index e039be2..7c2d846 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -403,6 +403,11 @@
void noteInvalidatedBucket(int64_t metricId);
/**
+ * Tracks the total number of buckets (include skipped/invalid buckets).
+ */
+ void noteBucketCount(int64_t metricId);
+
+ /**
* For pulls at bucket boundaries, it represents the misalignment between the real timestamp and
* the end of the bucket.
*/
@@ -464,6 +469,7 @@
int64_t minBucketBoundaryDelayNs = 0;
int64_t maxBucketBoundaryDelayNs = 0;
long bucketUnknownCondition = 0;
+ long bucketCount = 0;
} AtomMetricStats;
private:
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 96d1447..254d7d5 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -371,6 +371,7 @@
}
}
+ StatsdStats::getInstance().noteBucketCount(mMetricId);
// Only resets the counters, but doesn't setup the times nor numbers.
// (Do not clear since the old one is still referenced in mAnomalyTrackers).
mCurrentSlicedCounter = std::make_shared<DimToValMap>();
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 5e4594b..7dc4e2d 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -601,6 +601,7 @@
whatIt++;
}
}
+ StatsdStats::getInstance().noteBucketCount(mMetricId);
}
void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 7b001b3..2b6cac8 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -576,6 +576,7 @@
}
}
+ StatsdStats::getInstance().noteBucketCount(mMetricId);
mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index e94b75c..8d1cf33 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -355,21 +355,25 @@
flushIfNeededLocked(eventTimeNs);
- // Pull on condition changes.
- bool conditionChanged = mCondition != condition;
- bool unknownToFalse = mCondition == ConditionState::kUnknown
- && condition == ConditionState::kFalse;
- // We do not need to pull when we go from unknown to false.
- if (mIsPulled && conditionChanged && !unknownToFalse) {
- pullAndMatchEventsLocked(eventTimeNs);
- }
+ if (mCondition != ConditionState::kUnknown) {
+ // Pull on condition changes.
+ bool conditionChanged = mCondition != condition;
+ // We do not need to pull when we go from unknown to false.
+ if (mIsPulled && conditionChanged) {
+ pullAndMatchEventsLocked(eventTimeNs);
+ }
- // when condition change from true to false, clear diff base but don't
- // reset other counters as we may accumulate more value in the bucket.
- if (mUseDiff && mCondition == ConditionState::kTrue && condition == ConditionState::kFalse) {
- resetBase();
+ // when condition change from true to false, clear diff base but don't
+ // reset other counters as we may accumulate more value in the bucket.
+ if (mUseDiff && mCondition == ConditionState::kTrue && condition == ConditionState::kFalse) {
+ resetBase();
+ }
+ } else {
+ // If the condition was unknown, we mark the bucket as invalid since the bucket will contain
+ // partial data. For instance, the condition change might happen close to the end of the
+ // bucket and we might miss lots of data.
+ invalidateCurrentBucket();
}
-
mCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
}
@@ -769,6 +773,7 @@
if (!mCurrentBucketIsInvalid) {
appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
}
+ StatsdStats::getInstance().noteBucketCount(mMetricId);
initCurrentSlicedBucket();
mCurrentBucketIsInvalid = false;
mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 696d4fa..24e14b1 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -255,6 +255,8 @@
FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged);
FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary);
FRIEND_TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid);
+ friend class ValueMetricProducerTestHelper;
};
} // namespace statsd
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 623d8bc..166e087 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -426,6 +426,7 @@
optional int64 min_bucket_boundary_delay_ns = 9;
optional int64 max_bucket_boundary_delay_ns = 10;
optional int64 bucket_unknown_condition = 11;
+ optional int64 bucket_count = 12;
}
repeated AtomMetricStats atom_metric_stats = 17;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index ca645e1..31f160d 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -85,6 +85,7 @@
const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
const int FIELD_ID_BUCKET_UNKNOWN_CONDITION = 11;
+const int FIELD_ID_BUCKET_COUNT = 12;
namespace {
@@ -515,6 +516,8 @@
(long long)pair.second.maxBucketBoundaryDelayNs);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_UNKNOWN_CONDITION,
(long long)pair.second.bucketUnknownCondition);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_COUNT,
+ (long long)pair.second.bucketCount);
protoOutput->end(token);
}
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index a9d2c88..28caede 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -52,15 +52,72 @@
const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
double epsilon = 0.001;
+
+class ValueMetricProducerTestHelper {
+
+ public:
+ static sp<ValueMetricProducer> createValueProducerNoConditions(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithCondition(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer =
+ new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+ valueProducer->mCondition = ConditionState::kFalse;
+ return valueProducer;
+ }
+
+ static ValueMetric createMetric() {
+ 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_max_pull_delay_sec(INT_MAX);
+ return metric;
+ }
+
+ static ValueMetric createMetricWithCondition() {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_condition(StringToId("SCREEN_ON"));
+ return metric;
+ }
+};
+
+
/*
* 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
int64_t startTimeBase = 11;
UidMap uidMap;
@@ -90,11 +147,7 @@
* Tests that the first bucket works correctly
*/
TEST(ValueMetricProducerTest, TestFirstBucket) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -120,23 +173,8 @@
* Tests pulled atoms with no conditions
*/
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
- 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_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -148,9 +186,8 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -160,17 +197,17 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -178,19 +215,19 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(23, curInterval.base.long_value);
EXPECT_EQ(false, 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(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -198,39 +235,24 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, 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(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
- EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second[2].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
- 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_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
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, _))
// Initialize bucket.
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -253,9 +275,8 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
// First bucket ends.
vector<shared_ptr<LogEvent>> allData;
@@ -265,14 +286,14 @@
event->write(2);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
// Partial buckets created in 2nd bucket.
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
// One full bucket and one partial bucket.
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- vector<ValueBucket> buckets = valueProducer.mPastBuckets.begin()->second;
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
EXPECT_EQ(2UL, buckets.size());
// Full bucket (2 - 1)
EXPECT_EQ(1, buckets[0].values[0].long_value);
@@ -284,12 +305,7 @@
* Tests pulled atoms with filtering
*/
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -315,9 +331,10 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -327,18 +344,18 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -346,16 +363,16 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// No new data seen, so data has been cleared.
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -363,46 +380,30 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// the base was reset
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(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
}
/*
* Tests pulled atoms with no conditions and take absolute value after reset
*/
TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_use_absolute_value_on_reset(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
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(true));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -412,15 +413,15 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -428,16 +429,16 @@
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -445,45 +446,28 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, 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(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
}
/*
* Tests pulled atoms with no conditions and take zero value after reset
*/
TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
- 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_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
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));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -493,15 +477,15 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -509,14 +493,14 @@
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -524,39 +508,24 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
}
/*
* Test pulled event with non sliced condition.
*/
TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -578,19 +547,19 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -599,34 +568,30 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(110, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(false, curInterval.hasBase);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -670,12 +635,7 @@
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -733,12 +693,7 @@
}
TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_split_bucket_for_app_upgrade(false);
UidMap uidMap;
@@ -773,24 +728,9 @@
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -810,29 +750,25 @@
data->push_back(event);
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
- EXPECT_FALSE(valueProducer.mCondition);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
+ EXPECT_FALSE(valueProducer->mCondition);
+
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
// Expect one full buckets already done and starting a partial bucket.
- 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].values[0].long_value);
- EXPECT_FALSE(valueProducer.mCondition);
+ 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].values[0].long_value);
+ EXPECT_FALSE(valueProducer->mCondition);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -876,11 +812,7 @@
}
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -894,6 +826,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.mCondition = ConditionState::kFalse;
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -955,11 +888,7 @@
const int32_t refPeriodSec = 3;
alert.set_refractory_period_secs(refPeriodSec);
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -1036,28 +965,11 @@
// Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
- 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_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
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(true));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
// pull 1
@@ -1068,16 +980,16 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:true sum:0 start:11
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull 2 at correct time
allData.clear();
@@ -1086,16 +998,16 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// tartUpdated:false sum:12
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(23, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
// pull 3 come late.
// The previous bucket gets closed with error. (Has start value 23, no ending)
@@ -1107,16 +1019,16 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:12
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().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
}
/*
@@ -1124,25 +1036,9 @@
* was delivered late.
*/
TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -1164,27 +1060,26 @@
data->push_back(event);
return true;
}));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ 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[0];
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Now the alarm is delivered.
// since the condition turned to off before this pull finish, it has no effect
@@ -1195,13 +1090,13 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
}
/*
@@ -1209,25 +1104,9 @@
* change to false, and then true again. This is due to alarm delivered late.
*/
TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -1260,36 +1139,36 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ 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[0];
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ 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[0];
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
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());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Now the alarm is delivered, but it is considered late, the bucket is invalidated.
vector<shared_ptr<LogEvent>> allData;
@@ -1299,22 +1178,18 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, 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());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
}
TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
UidMap uidMap;
@@ -1359,11 +1234,7 @@
}
TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MAX);
UidMap uidMap;
@@ -1408,11 +1279,7 @@
}
TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::AVG);
UidMap uidMap;
@@ -1460,11 +1327,7 @@
}
TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::SUM);
UidMap uidMap;
@@ -1509,11 +1372,7 @@
}
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(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
@@ -1584,11 +1443,7 @@
}
TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_value_field()->add_child()->set_field(3);
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
@@ -1694,26 +1549,12 @@
* Tests zero default base.
*/
TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_use_zero_default_base(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1725,19 +1566,18 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1752,15 +1592,15 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1773,8 +1613,8 @@
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
- auto iterator = valueProducer.mPastBuckets.begin();
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+ auto iterator = valueProducer->mPastBuckets.begin();
EXPECT_EQ(8, iterator->second[0].values[0].long_value);
iterator++;
EXPECT_EQ(4, iterator->second[0].values[0].long_value);
@@ -1784,26 +1624,12 @@
* Tests using zero default base with failed pull.
*/
TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_use_zero_default_base(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1815,19 +1641,18 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1842,15 +1667,15 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1862,7 +1687,7 @@
EXPECT_EQ(4, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
// next pull somehow did not happen, skip to end of bucket 3
allData.clear();
@@ -1871,16 +1696,16 @@
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(4, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
allData.clear();
event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
@@ -1893,9 +1718,9 @@
event2->write(5);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(5, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
@@ -1904,33 +1729,19 @@
EXPECT_EQ(13, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
}
/*
* Tests trim unused dimension key if no new data is seen in an entire bucket.
*/
TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1942,18 +1753,17 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1968,18 +1778,18 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
EXPECT_FALSE(interval1.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1991,7 +1801,7 @@
EXPECT_EQ(4, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
// next pull somehow did not happen, skip to end of bucket 3
allData.clear();
@@ -2000,17 +1810,17 @@
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
// Only one interval left. One was trimmed.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(5, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
allData.clear();
event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
@@ -2018,40 +1828,24 @@
event1->write(14);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
- interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(14, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
- auto iterator = valueProducer.mPastBuckets.begin();
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+ auto iterator = valueProducer->mPastBuckets.begin();
EXPECT_EQ(9, iterator->second[0].values[0].long_value);
iterator++;
EXPECT_EQ(8, iterator->second[0].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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());
-
// Used by onConditionChanged.
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2064,47 +1858,30 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2117,50 +1894,33 @@
}))
.WillOnce(Return(false));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 20);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2172,45 +1932,30 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 1);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_condition(StringToId("SCREEN_ON"));
metric.set_max_pull_delay_sec(0);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2222,25 +1967,18 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kFalse;
+ valueProducer->mCondition = ConditionState::kFalse;
// Max delay is set to 0 so pull will exceed max delay.
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2266,24 +2004,9 @@
}
TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2295,44 +2018,27 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kFalse;
- valueProducer.mHasGlobalBase = false;
+ valueProducer->mCondition = ConditionState::kFalse;
+ valueProducer->mHasGlobalBase = false;
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
- valueProducer.mHasGlobalBase = true;
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+ valueProducer->mHasGlobalBase = true;
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Return(false))
@@ -2347,11 +2053,10 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2361,12 +2066,12 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2375,43 +2080,28 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(140, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2425,36 +2115,19 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kFalse;
- valueProducer.onConditionChanged(true, bucket2StartTimeNs + 2);
- EXPECT_EQ(true, valueProducer.mCurrentBucketIsInvalid);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->mCondition = ConditionState::kFalse;
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 2);
+ EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2477,11 +2150,10 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2491,10 +2163,10 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2503,41 +2175,25 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(140, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2560,11 +2216,10 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2574,12 +2229,12 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2588,39 +2243,23 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Last pull failed so based has been reset.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
- 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_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
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, _))
// Start bucket.
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2633,9 +2272,8 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
// Bucket 2 start.
vector<shared_ptr<LogEvent>> allData;
@@ -2645,41 +2283,25 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
// Bucket 3 empty.
allData.clear();
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// Data has been trimmed.
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2696,47 +2318,30 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
// Empty pull.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
- 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"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2767,58 +2372,42 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 11);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 12);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
// End of bucket
vector<shared_ptr<LogEvent>> allData;
allData.clear();
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// Data is empty, base should be reset.
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(5, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
- 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);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- 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, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2832,12 +2421,11 @@
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// End of bucket
vector<shared_ptr<LogEvent>> allData;
@@ -2847,11 +2435,11 @@
event->write(2);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// Key 1 should be reset since in not present in the most pull.
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
- auto iterator = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iterator = valueProducer->mCurrentSlicedBucket.begin();
EXPECT_EQ(true, iterator->second[0].hasBase);
EXPECT_EQ(2, iterator->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
@@ -2860,7 +2448,49 @@
EXPECT_EQ(1, iterator->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+ metric.set_condition(StringToId("SCREEN_ON"));
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Second onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(2);
+ event->write(2);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kUnknown;
+
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(4);
+ event->write(4);
+ event->init();
+ allData.push_back(event);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket is incomplete so it is mark as invalid, however the base is fine since the last pull
+ // succeeded.
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
}
static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
@@ -2881,12 +2511,7 @@
}
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2918,7 +2543,7 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
true /* include recent buckets */, true,
FAST, &strSet, &output);
@@ -2928,12 +2553,7 @@
}
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2975,7 +2595,7 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucket4StartTimeNs,
+ valueProducer.onDumpReport(bucket4StartTimeNs,
false /* include recent buckets */, true,
FAST, &strSet, &output);
@@ -2986,12 +2606,7 @@
}
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
- 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_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -3033,7 +2648,7 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
true /* include recent buckets */, true,
NO_TIME_CONSTRAINTS, &strSet, &output);
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 62225df..68fb8e6 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -98,5 +98,6 @@
new UsbCommand(),
new NfcCommand(),
new BluetoothCommand(),
+ new SystemServerCommand(),
};
}
diff --git a/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java b/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java
new file mode 100644
index 0000000..b9104d1
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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.commands.svc;
+
+import android.app.ActivityManager;
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileInputStream;
+
+public class SystemServerCommand extends Svc.Command {
+ public SystemServerCommand() {
+ super("system-server");
+ }
+
+ @Override
+ public String shortHelp() {
+ return "System server process related command";
+ }
+
+ @Override
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: system-server wait-for-crash\n"
+ + " Wait until the system server process crashes.\n\n";
+ }
+
+ private void waitForCrash() throws Exception {
+ ParcelFileDescriptor fd = ActivityManager.getService().getLifeMonitor();
+ if (fd == null) {
+ System.err.println("Unable to get life monitor.");
+ return;
+ }
+ System.out.println("Waiting for the system server process to die...");
+ new FileInputStream(fd.getFileDescriptor()).read();
+ }
+
+ @Override
+ public void run(String[] args) {
+ try {
+ if (args.length > 1) {
+ switch (args[1]) {
+ case "wait-for-crash":
+ waitForCrash();
+ return;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ System.err.println(longHelp());
+ }
+}
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index a836e8e..2abb631 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -688,7 +688,6 @@
Landroid/os/Build;->getLong(Ljava/lang/String;)J
Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
Landroid/os/Build;->IS_DEBUGGABLE:Z
-Landroid/os/Build;->IS_EMULATOR:Z
Landroid/os/Bundle;->filterValues()Landroid/os/Bundle;
Landroid/os/Bundle;->forPair(Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;
Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
@@ -3107,10 +3106,6 @@
Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ISub$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISub;
-Lcom/android/internal/telephony/ISub;->getActiveSubIdList()[I
-Lcom/android/internal/telephony/ISub;->getDefaultDataSubId()I
-Lcom/android/internal/telephony/ISub;->getDefaultSubId()I
-Lcom/android/internal/telephony/ISub;->setDefaultDataSubId(I)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->isRadioOn(Ljava/lang/String;)Z
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 89e848b..a63350c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7608,7 +7608,7 @@
mWindow.setColorMode(info.colorMode);
- setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
+ setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d4f988..ee7288f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3925,6 +3925,14 @@
/**
* @hide
*/
+ @TestApi
+ public static void resumeAppSwitches() throws RemoteException {
+ getService().resumeAppSwitches();
+ }
+
+ /**
+ * @hide
+ */
public static void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid,
String sourcePkg, String tag) {
try {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 001cd69..92302c5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -43,6 +43,7 @@
import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -745,7 +746,7 @@
/** Initial values for {@link Profiler}. */
ProfilerInfo initProfilerInfo;
- boolean autofillCompatibilityEnabled;
+ AutofillOptions autofillOptions;
/**
* Content capture options for the application - when null, it means ContentCapture is not
@@ -975,9 +976,8 @@
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
- String buildSerial, boolean autofillCompatibilityEnabled,
+ String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions) {
-
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
@@ -1023,7 +1023,7 @@
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
- data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
+ data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
sendMessage(H.BIND_APPLICATION, data);
}
@@ -6164,7 +6164,7 @@
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state
- app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
+ app.setAutofillOptions(data.autofillOptions);
// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index e0ae4e3..2ef0856 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -21,7 +21,7 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.TestApi;
import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -59,6 +59,7 @@
* on VirtualDisplays.
* @hide
*/
+@TestApi
public class ActivityView extends ViewGroup {
private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay";
@@ -92,7 +93,6 @@
private Insets mForwardedInsets;
- @UnsupportedAppUsage
public ActivityView(Context context) {
this(context, null /* attrs */);
}
@@ -151,7 +151,7 @@
* Called when a task is moved to the front of the stack inside the container.
* This is a filtered version of {@link TaskStackListener}
*/
- public void onTaskMovedToFront(ActivityManager.StackInfo stackInfo) { }
+ public void onTaskMovedToFront(int taskId) { }
/**
* Called when a task is about to be removed from the stack inside the container.
@@ -195,7 +195,6 @@
* @see StateCallback
* @see #startActivity(PendingIntent)
*/
- @UnsupportedAppUsage
public void startActivity(@NonNull Intent intent) {
final ActivityOptions options = prepareActivityOptions();
getContext().startActivity(intent, options.toBundle());
@@ -238,7 +237,6 @@
* @see StateCallback
* @see #startActivity(Intent)
*/
- @UnsupportedAppUsage
public void startActivity(@NonNull PendingIntent pendingIntent) {
final ActivityOptions options = prepareActivityOptions();
try {
@@ -272,7 +270,6 @@
*
* @see StateCallback
*/
- @UnsupportedAppUsage
public void release() {
if (mVirtualDisplay == null) {
throw new IllegalStateException(
@@ -400,7 +397,7 @@
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
- .setContainerLayer(true)
+ .setContainerLayer()
.setParent(mSurfaceView.getSurfaceControl())
.setName(DISPLAY_NAME)
.build();
@@ -524,9 +521,10 @@
private class TaskStackListenerImpl extends TaskStackListener {
@Override
- public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
- if (mVirtualDisplay == null) {
+ if (mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
@@ -536,14 +534,17 @@
}
// Found the topmost stack on target display. Now check if the topmost task's
// description changed.
- if (taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mSurfaceView.setResizeBackgroundColor(td.getBackgroundColor());
+ if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mSurfaceView.setResizeBackgroundColor(
+ taskInfo.taskDescription.getBackgroundColor());
}
}
@Override
- public void onTaskMovedToFront(int taskId) throws RemoteException {
- if (mActivityViewCallback == null) {
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (mActivityViewCallback == null || mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
@@ -551,14 +552,14 @@
// if StackInfo was null or unrelated to the "move to front" then there's no use
// notifying the callback
if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskMovedToFront(stackInfo);
+ && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mActivityViewCallback.onTaskMovedToFront(taskInfo.taskId);
}
}
@Override
public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
- if (mActivityViewCallback == null) {
+ if (mActivityViewCallback == null || mVirtualDisplay == null) {
return;
}
@@ -572,17 +573,13 @@
}
@Override
- public void onTaskRemovalStarted(int taskId) throws RemoteException {
- if (mActivityViewCallback == null) {
+ public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (mActivityViewCallback == null || mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
- StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or task is on a different display then there's no use
- // notifying the callback
- if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskRemovalStarted(taskId);
- }
+ mActivityViewCallback.onTaskRemovalStarted(taskInfo.taskId);
}
private StackInfo getTopMostStackInfo() throws RemoteException {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 98032dc..d3e3507 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -696,7 +696,9 @@
int flagMask, int flagValues, UserHandle user) {
try {
mPM.updatePermissionFlags(permissionName, packageName, flagMask,
- flagValues, user.getIdentifier());
+ flagValues,
+ mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q,
+ user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2467,6 +2469,33 @@
}
@Override
+ public void setAppDetailsActivityEnabled(String packageName, boolean enabled) {
+ try {
+ ComponentName componentName = new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ mPM.setComponentEnabledSetting(componentName, enabled
+ ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP, getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean getAppDetailsActivityEnabled(String packageName) {
+ try {
+ ComponentName componentName = new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ int state = mPM.getComponentEnabledSetting(componentName, getUserId());
+ return state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags) {
try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3a1e80d..b607f9a 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
@@ -215,8 +216,8 @@
// The name of the split this Context is representing. May be null.
private @Nullable String mSplitName = null;
- private AutofillClient mAutofillClient = null;
- private boolean mIsAutofillCompatEnabled;
+ private @Nullable AutofillClient mAutofillClient = null;
+ private @Nullable AutofillOptions mAutofillOptions;
private ContentCaptureOptions mContentCaptureOptions = null;
@@ -2283,8 +2284,8 @@
return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0;
}
+ @TestApi
@Override
- @UnsupportedAppUsage
public Display getDisplay() {
if (mDisplay == null) {
return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
@@ -2376,15 +2377,14 @@
/** @hide */
@Override
- public boolean isAutofillCompatibilityEnabled() {
- return mIsAutofillCompatEnabled;
+ public AutofillOptions getAutofillOptions() {
+ return mAutofillOptions;
}
/** @hide */
- @TestApi
@Override
- public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
- mIsAutofillCompatEnabled = autofillCompatEnabled;
+ public void setAutofillOptions(AutofillOptions options) {
+ mAutofillOptions = options;
}
/** @hide */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3aa9fa7..dcef9d2 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -486,4 +486,7 @@
* started from the shell.
*/
void stopDelegateShellPermissionIdentity();
+
+ /** Returns a file descriptor that'll be closed when the system server process dies. */
+ ParcelFileDescriptor getLifeMonitor();
}
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index b73092a..b8af898 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -21,6 +21,7 @@
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.servertransaction.ClientTransaction;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
@@ -69,7 +70,7 @@
int debugMode, boolean enableBinderTracking, boolean trackAllocation,
boolean restrictedBackupMode, boolean persistent, in Configuration config,
in CompatibilityInfo compatInfo, in Map services,
- in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled,
+ in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions,
in ContentCaptureOptions contentCaptureOptions);
void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
void scheduleExit();
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 2e1e988..8615f00 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -73,8 +73,12 @@
/**
* Called when an activity was requested to be launched on a secondary display but was not
* allowed there.
+ *
+ * @param taskInfo info about the Activity's task
+ * @param requestedDisplayId the id of the requested launch display
*/
- void onActivityLaunchOnSecondaryDisplayFailed();
+ void onActivityLaunchOnSecondaryDisplayFailed(in ActivityManager.RunningTaskInfo taskInfo,
+ int requestedDisplayId);
/**
* Called when a task is added.
@@ -94,18 +98,17 @@
/**
* Called when a task is moved to the front of its stack.
*
- * @param taskId id of the task.
+ * @param taskInfo info about the task which moved
*/
- void onTaskMovedToFront(int taskId);
+ void onTaskMovedToFront(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when a task’s description is changed due to an activity calling
* ActivityManagerService.setTaskDescription
*
- * @param taskId id of the task.
- * @param td the new TaskDescription.
+ * @param taskInfo info about the task which changed, with {@link TaskInfo#taskDescription}
*/
- void onTaskDescriptionChanged(int taskId, in ActivityManager.TaskDescription td);
+ void onTaskDescriptionChanged(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when a activity’s orientation is changed due to it calling
@@ -120,8 +123,10 @@
* Called when the task is about to be finished but before its surfaces are
* removed from the window manager. This allows interested parties to
* perform relevant animations before the window disappears.
+ *
+ * @param taskInfo info about the task being removed
*/
- void onTaskRemovalStarted(int taskId);
+ void onTaskRemovalStarted(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when the task has been put in a locked state because one or more of the
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index dc4f343..2e7093d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8408,7 +8408,7 @@
public static final class BubbleMetadata implements Parcelable {
private PendingIntent mPendingIntent;
- private CharSequence mTitle;
+ private PendingIntent mDeleteIntent;
private Icon mIcon;
private int mDesiredHeight;
private int mFlags;
@@ -8436,19 +8436,22 @@
*/
private static final int FLAG_SUPPRESS_INITIAL_NOTIFICATION = 0x00000002;
- private BubbleMetadata(PendingIntent intent, CharSequence title, Icon icon, int height) {
- mPendingIntent = intent;
- mTitle = title;
+ private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent,
+ Icon icon, int height) {
+ mPendingIntent = expandIntent;
mIcon = icon;
mDesiredHeight = height;
+ mDeleteIntent = deleteIntent;
}
private BubbleMetadata(Parcel in) {
mPendingIntent = PendingIntent.CREATOR.createFromParcel(in);
- mTitle = in.readCharSequence();
mIcon = Icon.CREATOR.createFromParcel(in);
mDesiredHeight = in.readInt();
mFlags = in.readInt();
+ if (in.readInt() != 0) {
+ mDeleteIntent = PendingIntent.CREATOR.createFromParcel(in);
+ }
}
/**
@@ -8459,14 +8462,23 @@
}
/**
- * @return the title that will appear along with the app content defined by
- * {@link #getIntent()} for this bubble.
+ * @return the pending intent to send when the bubble is dismissed by a user, if one exists.
*/
- public CharSequence getTitle() {
- return mTitle;
+ public PendingIntent getDeleteIntent() {
+ return mDeleteIntent;
}
/**
+ * @return the title that will appear along with the app content defined by
+ * {@link #getIntent()} for this bubble.
+ *
+ * @deprecated titles are no longer required or shown.
+ */
+ @Deprecated
+ public CharSequence getTitle() {
+ return "";
+ }
+ /**
* @return the icon that will be displayed for this bubble when it is collapsed.
*/
public Icon getIcon() {
@@ -8521,10 +8533,13 @@
@Override
public void writeToParcel(Parcel out, int flags) {
mPendingIntent.writeToParcel(out, 0);
- out.writeCharSequence(mTitle);
mIcon.writeToParcel(out, 0);
out.writeInt(mDesiredHeight);
out.writeInt(mFlags);
+ out.writeInt(mDeleteIntent != null ? 1 : 0);
+ if (mDeleteIntent != null) {
+ mDeleteIntent.writeToParcel(out, 0);
+ }
}
private void setFlags(int flags) {
@@ -8537,10 +8552,10 @@
public static class Builder {
private PendingIntent mPendingIntent;
- private CharSequence mTitle;
private Icon mIcon;
private int mDesiredHeight;
private int mFlags;
+ private PendingIntent mDeleteIntent;
/**
* Constructs a new builder object.
@@ -8565,12 +8580,11 @@
*
* <p>A title is required and should expect to fit on a single line and make sense when
* shown with the content defined by {@link #setIntent(PendingIntent)}.</p>
+ *
+ * @deprecated titles are no longer required or shown.
*/
+ @Deprecated
public BubbleMetadata.Builder setTitle(CharSequence title) {
- if (TextUtils.isEmpty(title)) {
- throw new IllegalArgumentException("Bubbles require non-null or empty title");
- }
- mTitle = title;
return this;
}
@@ -8633,6 +8647,14 @@
}
/**
+ * Sets an optional intent to send when this bubble is explicitly removed by the user.
+ */
+ public BubbleMetadata.Builder setDeleteIntent(PendingIntent deleteIntent) {
+ mDeleteIntent = deleteIntent;
+ return this;
+ }
+
+ /**
* Creates the {@link BubbleMetadata} defined by this builder.
* <p>Will throw {@link IllegalStateException} if required fields have not been set
* on this builder.</p>
@@ -8641,14 +8663,11 @@
if (mPendingIntent == null) {
throw new IllegalStateException("Must supply pending intent to bubble");
}
- if (TextUtils.isEmpty(mTitle)) {
- throw new IllegalStateException("Must supply a title for the bubble");
- }
if (mIcon == null) {
throw new IllegalStateException("Must supply an icon for the bubble");
}
- BubbleMetadata data = new BubbleMetadata(mPendingIntent, mTitle, mIcon,
- mDesiredHeight);
+ BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent,
+ mIcon, mDesiredHeight);
data.setFlags(mFlags);
return data;
}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index e23352a..fcc76ac 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -70,6 +70,16 @@
}
@Override
+ public void onActivityLaunchOnSecondaryDisplayFailed(ActivityManager.RunningTaskInfo taskInfo,
+ int requestedDisplayId) throws RemoteException {
+ onActivityLaunchOnSecondaryDisplayFailed();
+ }
+
+ /**
+ * @deprecated see {@link
+ * #onActivityLaunchOnSecondaryDisplayFailed(ActivityManager.RunningTaskInfo, int)}
+ */
+ @Deprecated
@UnsupportedAppUsage
public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
}
@@ -84,15 +94,42 @@
}
@Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskMovedToFront(taskInfo.taskId);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskMovedToFront(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
@UnsupportedAppUsage
public void onTaskMovedToFront(int taskId) throws RemoteException {
}
@Override
+ public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskRemovalStarted(taskInfo.taskId);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskRemovalStarted(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
public void onTaskRemovalStarted(int taskId) throws RemoteException {
}
@Override
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskDescriptionChanged(taskInfo.taskId, taskInfo.taskDescription);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskDescriptionChanged(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
throws RemoteException {
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 31521a3..7e07446 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -128,7 +128,13 @@
: InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
final long identity = Binder.clearCallingIdentity();
try {
- return InputManager.getInstance().injectInputEvent(event, mode);
+ IWindowManager manager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ try {
+ return manager.injectInputAfterTransactionsApplied(event, mode);
+ } catch (RemoteException e) {
+ }
+ return false;
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3587c68..a32e01f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -59,6 +59,7 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
@@ -115,6 +116,8 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
/**
@@ -1576,6 +1579,19 @@
public static final int PERMISSION_POLICY_AUTO_DENY = 2;
/**
+ * Possible policy values for permissions.
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "PERMISSION_GRANT_STATE_" }, value = {
+ PERMISSION_GRANT_STATE_DEFAULT,
+ PERMISSION_GRANT_STATE_GRANTED,
+ PERMISSION_GRANT_STATE_DENIED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionGrantState {}
+
+ /**
* Runtime permission state: The user can manage the permission
* through the UI.
*/
@@ -8667,8 +8683,15 @@
* Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke
* the permission. It retains the previous grant, if any.
* <p/>
- * Permissions can be granted or revoked only for applications built with a
- * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
+ * Device admins with a {@code targetSdkVersion} < {@link android.os.Build.VERSION_CODES#Q}
+ * cannot grant and revoke permissions for applications built with a {@code targetSdkVersion}
+ * < {@link android.os.Build.VERSION_CODES#M}.
+ * <p/>
+ * Admins with a {@code targetSdkVersion} ≥ {@link android.os.Build.VERSION_CODES#Q} can
+ * grant and revoke permissions of all apps. Similar to the user revoking a permission from a
+ * application built with a {@code targetSdkVersion} <
+ * {@link android.os.Build.VERSION_CODES#M} the app-op matching the permission is set to
+ * {@link android.app.AppOpsManager#MODE_IGNORED}, but the permission stays granted.
*
* @param admin Which profile or device owner this request is associated with.
* @param packageName The application to grant or revoke a permission to.
@@ -8684,14 +8707,21 @@
* @see #setDelegatedScopes
* @see #DELEGATION_PERMISSION_GRANT
*/
- public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
- String permission, int grantState) {
+ public boolean setPermissionGrantState(@NonNull ComponentName admin,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState) {
throwIfParentInstance("setPermissionGrantState");
try {
- return mService.setPermissionGrantState(admin, mContext.getPackageName(), packageName,
- permission, grantState);
+ CompletableFuture<Boolean> result = new CompletableFuture<>();
+
+ mService.setPermissionGrantState(admin, mContext.getPackageName(), packageName,
+ permission, grantState, new RemoteCallback((b) -> result.complete(b != null)));
+
+ return result.get();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
}
}
@@ -8719,8 +8749,8 @@
* @see #setDelegatedScopes
* @see #DELEGATION_PERMISSION_GRANT
*/
- public int getPermissionGrantState(@Nullable ComponentName admin, String packageName,
- String permission) {
+ public @PermissionGrantState int getPermissionGrantState(@Nullable ComponentName admin,
+ @NonNull String packageName, @NonNull String permission) {
throwIfParentInstance("getPermissionGrantState");
try {
return mService.getPermissionGrantState(admin, mContext.getPackageName(), packageName,
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5790fda..9478a3c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -311,8 +311,8 @@
void setPermissionPolicy(in ComponentName admin, in String callerPackage, int policy);
int getPermissionPolicy(in ComponentName admin);
- boolean setPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName,
- String permission, int grantState);
+ void setPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName,
+ String permission, int grantState, in RemoteCallback resultReceiver);
int getPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName, String permission);
boolean isProvisioningAllowed(String action, String packageName);
int checkProvisioningPreCondition(String action, String packageName);
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 868fbfe..bcc4974 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -762,6 +762,7 @@
*/
@Nullable
public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.getUserForAncestralSerialNumber(ancestralSerialNumber);
@@ -782,6 +783,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public void setAncestralSerialNumber(long ancestralSerialNumber) {
+ checkServiceBinder();
if (sService != null) {
try {
sService.setAncestralSerialNumber(ancestralSerialNumber);
@@ -802,6 +804,7 @@
@TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public Intent getConfigurationIntent(String transportName) {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.getConfigurationIntentForUser(mContext.getUserId(), transportName);
@@ -823,6 +826,7 @@
@TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public String getDestinationString(String transportName) {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.getDestinationStringForUser(mContext.getUserId(), transportName);
@@ -844,6 +848,7 @@
@TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public Intent getDataManagementIntent(String transportName) {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.getDataManagementIntentForUser(mContext.getUserId(), transportName);
@@ -867,6 +872,7 @@
@TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public String getDataManagementLabel(String transportName) {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.getDataManagementLabelForUser(mContext.getUserId(), transportName);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 3e9dd28..85f0e23 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -30,7 +30,6 @@
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcelable;
@@ -178,40 +177,29 @@
*/
public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
Rect padding) {
- ApplicationInfo appInfo = null;
- try {
- appInfo = context.getPackageManager().getApplicationInfo(component.getPackageName(), 0);
- } catch (NameNotFoundException e) {
- // if we can't find the package, ignore
- }
- return getDefaultPaddingForWidget(context, appInfo, padding);
+ return getDefaultPaddingForWidget(context, padding);
}
- @UnsupportedAppUsage
- private static Rect getDefaultPaddingForWidget(Context context, ApplicationInfo appInfo,
- Rect padding) {
+ private static Rect getDefaultPaddingForWidget(Context context, Rect padding) {
if (padding == null) {
padding = new Rect(0, 0, 0, 0);
} else {
padding.set(0, 0, 0, 0);
}
- if (appInfo != null && appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- Resources r = context.getResources();
- padding.left = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_left);
- padding.right = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_right);
- padding.top = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_top);
- padding.bottom = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_bottom);
- }
+ Resources r = context.getResources();
+ padding.left = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_left);
+ padding.right = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_right);
+ padding.top = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_top);
+ padding.bottom = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_bottom);
return padding;
}
private Rect getDefaultPadding() {
- return getDefaultPaddingForWidget(mContext,
- mInfo == null ? null : mInfo.providerInfo.applicationInfo, null);
+ return getDefaultPaddingForWidget(mContext, null);
}
public int getAppWidgetId() {
diff --git a/core/java/android/content/AutofillOptions.aidl b/core/java/android/content/AutofillOptions.aidl
new file mode 100644
index 0000000..7e4fed2
--- /dev/null
+++ b/core/java/android/content/AutofillOptions.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content;
+
+parcelable AutofillOptions;
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
new file mode 100644
index 0000000..fd7e52a
--- /dev/null
+++ b/core/java/android/content/AutofillOptions.java
@@ -0,0 +1,130 @@
+/*
+ * 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.content;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.app.ActivityThread;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.autofill.AutofillManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Autofill options for a given package.
+ *
+ * <p>This object is created by the Autofill System Service and passed back to the app when the
+ * application is created.
+ *
+ * @hide
+ */
+@TestApi
+public final class AutofillOptions implements Parcelable {
+
+ private static final String TAG = AutofillOptions.class.getSimpleName();
+
+ /**
+ * Logging level for {@code logcat} statements.
+ */
+ public final int loggingLevel;
+
+ /**
+ * Whether compatibility mode is enabled for the package.
+ */
+ public final boolean compatModeEnabled;
+
+ /**
+ * Whether package is whitelisted for augmented autofill.
+ */
+ public boolean augmentedEnabled;
+ // TODO(b/123100824): add (optional) list of activities
+
+ public AutofillOptions(int loggingLevel, boolean compatModeEnabled) {
+ this.loggingLevel = loggingLevel;
+ this.compatModeEnabled = compatModeEnabled;
+ }
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public static AutofillOptions forWhitelistingItself() {
+ final ActivityThread at = ActivityThread.currentActivityThread();
+ if (at == null) {
+ throw new IllegalStateException("No ActivityThread");
+ }
+
+ final String packageName = at.getApplication().getPackageName();
+
+ if (!"android.autofillservice.cts".equals(packageName)) {
+ Log.e(TAG, "forWhitelistingItself(): called by " + packageName);
+ throw new SecurityException("Thou shall not pass!");
+ }
+
+ final AutofillOptions options = new AutofillOptions(
+ AutofillManager.FLAG_ADD_CLIENT_VERBOSE, /* compatModeAllowed= */ true);
+ options.augmentedEnabled = true;
+ // Always log, as it's used by test only
+ Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
+
+ return options;
+ }
+
+ @Override
+ public String toString() {
+ return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode="
+ + compatModeEnabled + ", augmentedEnabled=" + augmentedEnabled + "]";
+ }
+
+ /** @hide */
+ public void dumpShort(@NonNull PrintWriter pw) {
+ pw.print("logLvl="); pw.print(loggingLevel);
+ pw.print(", compatMode="); pw.print(compatModeEnabled);
+ pw.print(", augmented="); pw.print(augmentedEnabled);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(loggingLevel);
+ parcel.writeBoolean(compatModeEnabled);
+ parcel.writeBoolean(augmentedEnabled);
+ }
+
+ public static final Parcelable.Creator<AutofillOptions> CREATOR =
+ new Parcelable.Creator<AutofillOptions>() {
+
+ @Override
+ public AutofillOptions createFromParcel(Parcel parcel) {
+ final int loggingLevel = parcel.readInt();
+ final boolean compatMode = parcel.readBoolean();
+ final AutofillOptions options = new AutofillOptions(loggingLevel, compatMode);
+ options.augmentedEnabled = parcel.readBoolean();
+ return options;
+ }
+
+ @Override
+ public AutofillOptions[] newArray(int size) {
+ return new AutofillOptions[size];
+ }
+ };
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fdb0041..29added 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5241,9 +5241,10 @@
public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
/**
+ * @return Returns the {@link Display} object this context is associated with.
* @hide
*/
- @UnsupportedAppUsage
+ @TestApi
public abstract Display getDisplay();
/**
@@ -5340,16 +5341,24 @@
/**
* @hide
*/
- public boolean isAutofillCompatibilityEnabled() {
- return false;
+ public final boolean isAutofillCompatibilityEnabled() {
+ final AutofillOptions options = getAutofillOptions();
+ return options != null && options.compatModeEnabled;
+ }
+
+ /**
+ * @hide
+ */
+ @Nullable
+ public AutofillOptions getAutofillOptions() {
+ return null;
}
/**
* @hide
*/
@TestApi
- public void setAutofillCompatibilityEnabled(
- @SuppressWarnings("unused") boolean autofillCompatEnabled) {
+ public void setAutofillOptions(@SuppressWarnings("unused") @Nullable AutofillOptions options) {
}
/**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 68b4320..40559d3 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -919,11 +919,9 @@
return mBase.getDisplayAdjustments(displayId);
}
- /**
- * @hide
- */
+ /** @hide */
+ @TestApi
@Override
- @UnsupportedAppUsage
public Display getDisplay() {
return mBase.getDisplay();
}
@@ -1031,22 +1029,17 @@
mBase.setAutofillClient(client);
}
- /**
- * @hide
- */
+ /** @hide */
@Override
- public boolean isAutofillCompatibilityEnabled() {
- return mBase != null && mBase.isAutofillCompatibilityEnabled();
+ public AutofillOptions getAutofillOptions() {
+ return mBase == null ? null : mBase.getAutofillOptions();
}
- /**
- * @hide
- */
- @TestApi
+ /** @hide */
@Override
- public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
+ public void setAutofillOptions(AutofillOptions options) {
if (mBase != null) {
- mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+ mBase.setAutofillOptions(options);
}
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 14e7725..dcbb4ac 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -111,7 +111,7 @@
int getPermissionFlags(String permissionName, String packageName, int userId);
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
- int flagValues, int userId);
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 8095473..badd48f 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1545,7 +1545,11 @@
/**
* Set this session to be installing an APEX package.
+ *
+ * {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setInstallAsApex() {
installFlags |= PackageManager.INSTALL_APEX;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0041921..6b2442f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -33,6 +33,7 @@
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
import android.app.ActivityManager;
+import android.app.AppDetailsActivity;
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
@@ -3030,6 +3031,13 @@
public static final int MASK_PERMISSION_FLAGS = 0xFF;
/**
+ * Injected activity in app that forwards user to setting activity of that app.
+ *
+ * @hide
+ */
+ public static final String APP_DETAILS_ACTIVITY_CLASS_NAME = AppDetailsActivity.class.getName();
+
+ /**
* This is a library that contains components apps can invoke. For
* example, a services for apps to bind to, or standard chooser UI,
* etc. This library is versioned and backwards compatible. Clients
@@ -5792,6 +5800,37 @@
@NonNull ComponentName componentName);
/**
+ * Set the enabled setting for a package app settings activity.
+ *
+ * @param packageName The package name of the app
+ * @param enabled The new enabled state for app details activity
+ *
+ * @hide
+ */
+ @RequiresPermission(value = android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE,
+ conditional = true)
+ @SystemApi
+ public void setAppDetailsActivityEnabled(@NonNull String packageName, boolean enabled) {
+ throw new UnsupportedOperationException(
+ "setAppDetailsActivityEnabled not implemented");
+ }
+
+
+ /**
+ * Return the enabled setting for a package app settings activity.
+ *
+ * @param packageName The package name of the app
+ * @return Returns the current enabled state for app settings activity.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getAppDetailsActivityEnabled(@NonNull String packageName) {
+ throw new UnsupportedOperationException(
+ "getAppDetailsActivityEnabled not implemented");
+ }
+
+ /**
* Set the enabled setting for an application
* This setting will override any enabled state which may have been set by the application in
* its manifest. It also overrides the enabled state set in the manifest for any of the
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0f67262..d7ca757 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -48,7 +48,6 @@
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
-import android.app.AppDetailsActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -4311,7 +4310,7 @@
} else {
String outInfoName
= buildClassName(owner.applicationInfo.packageName, name, outError);
- if (AppDetailsActivity.class.getName().equals(outInfoName)) {
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
outError[0] = tag + " invalid android:name";
return false;
}
@@ -4364,13 +4363,14 @@
boolean hardwareAccelerated) {
// Build custom App Details activity info instead of parsing it from xml
- Activity a = new Activity(owner, AppDetailsActivity.class.getName(), new ActivityInfo());
+ Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
+ new ActivityInfo());
a.owner = owner;
a.setPackageName(owner.packageName);
a.info.theme = android.R.style.Theme_NoDisplay;
a.info.exported = true;
- a.info.name = AppDetailsActivity.class.getName();
+ a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
a.info.processName = owner.applicationInfo.processName;
a.info.uiOptions = a.info.applicationInfo.uiOptions;
a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 1d0ab5a..7e5532c 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -108,6 +108,11 @@
}
/** @hide */
+ public void addPendingBackup(int userId) {
+ mPendingBackups.add(userId);
+ }
+
+ /** @hide */
public IntArray getPendingBackups() {
return mPendingBackups;
}
@@ -154,6 +159,19 @@
}
/** @hide */
+ public void removePendingBackup(int userId) {
+ int idx = mPendingBackups.indexOf(userId);
+ if (idx != -1) {
+ mPendingBackups.remove(idx);
+ }
+ }
+
+ /** @hide */
+ public void removePendingRestoreInfo(int userId) {
+ removeRestoreInfo(getRestoreInfo(userId));
+ }
+
+ /** @hide */
public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
VersionedPackage packageRolledBackTo,
@NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
diff --git a/core/java/android/hardware/display/Curve.java b/core/java/android/hardware/display/Curve.java
index ac28fdd..41f66f5 100644
--- a/core/java/android/hardware/display/Curve.java
+++ b/core/java/android/hardware/display/Curve.java
@@ -59,4 +59,18 @@
public int describeContents() {
return 0;
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[");
+ final int size = mX.length;
+ for (int i = 0; i < size; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append("(").append(mX[i]).append(", ").append(mY[i]).append(")");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
}
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 19848ee..5496e17 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -16,6 +16,7 @@
package android.metrics;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.ComponentName;
import android.util.Log;
import android.util.SparseArray;
@@ -31,6 +32,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class LogMaker {
private static final String TAG = "LogBuilder";
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 5f356ca..27f9a5d 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -16,6 +16,7 @@
package android.metrics;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.util.EventLog;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,6 +36,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class MetricsReader {
private Queue<LogMaker> mPendingQueue = new LinkedList<>();
private Queue<LogMaker> mSeenQueue = new LinkedList<>();
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 6d195ae..c1bce5e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3147,9 +3147,9 @@
/**
* Called if no network is found in the timeout time specified in
- * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call. This callback is not
- * called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
- * without timeout. When this callback is invoked the associated
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the
+ * requested network request cannot be fulfilled (whether or not a timeout was
+ * specified). When this callback is invoked the associated
* {@link NetworkRequest} will have already been removed and released, as if
* {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
*/
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 0dfe7a4..5b1d12c 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -27,11 +27,13 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -113,7 +115,16 @@
*/
private static final int CMD_SET_FILTER = BASE + 3;
+ /**
+ * Sent by NetworkFactory to ConnectivityService to indicate that a request is
+ * unfulfillable.
+ * @see #releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest).
+ */
+ public static final int EVENT_UNFULFILLABLE_REQUEST = BASE + 4;
+
private final Context mContext;
+ private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
+ private AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private final SparseArray<NetworkRequestInfo> mNetworkRequests =
@@ -155,6 +166,36 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAsyncChannel != null) {
+ log("Received new connection while already connected!");
+ break;
+ }
+ if (VDBG) log("NetworkFactory fully connected");
+ AsyncChannel ac = new AsyncChannel();
+ ac.connected(null, this, msg.replyTo);
+ ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL);
+ mAsyncChannel = ac;
+ for (Message m : mPreConnectedQueue) {
+ ac.sendMessage(m);
+ }
+ mPreConnectedQueue.clear();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+ if (mAsyncChannel != null) {
+ mAsyncChannel.disconnect();
+ mAsyncChannel = null;
+ }
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (DBG) log("NetworkFactory channel lost");
+ mAsyncChannel = null;
+ break;
+ }
case CMD_REQUEST_NETWORK: {
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
@@ -355,6 +396,27 @@
});
}
+ /**
+ * Can be called by a factory to release a request as unfulfillable: the request will be
+ * removed, and the caller will get a
+ * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
+ * returns.
+ *
+ * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
+ * is able to fulfill this request!
+ */
+ protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
+ post(() -> {
+ if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
+ Message msg = obtainMessage(EVENT_UNFULFILLABLE_REQUEST, r);
+ if (mAsyncChannel != null) {
+ mAsyncChannel.sendMessage(msg);
+ } else {
+ mPreConnectedQueue.add(msg);
+ }
+ });
+ }
+
// override to do simple mode (request independent)
protected void startNetwork() { }
protected void stopNetwork() { }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 83a7654..0425c62 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -107,6 +107,7 @@
* Whether this build was for an emulator device.
* @hide
*/
+ @TestApi
public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1");
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e2b5730..0673755 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2697,6 +2697,19 @@
}
/**
+ * Updates the calling user's name.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param name the new name for the user
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public void setUserName(String name) {
+ setUserName(getUserHandle(), name);
+ }
+
+ /**
* Sets the user's photo.
* @param userHandle the user for whom to change the photo.
* @param icon the bitmap to set as the photo.
@@ -2711,6 +2724,19 @@
}
/**
+ * Sets the calling user's photo.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param icon the bitmap to set as the photo.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public void setUserIcon(Bitmap icon) {
+ setUserIcon(getUserHandle(), icon);
+ }
+
+ /**
* Returns a file descriptor for the user's photo. PNG data can be read from this file.
* @param userHandle the user whose photo we want to read.
* @return a {@link Bitmap} of the user's photo, or null if there's no photo.
@@ -2737,6 +2763,20 @@
}
/**
+ * Returns a Bitmap for the calling user's photo.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
+ * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public Bitmap getUserIcon() {
+ return getUserIcon(getUserHandle());
+ }
+
+ /**
* Returns the maximum number of users that can be created on this device. A return value
* of 1 means that it is a single user device.
* @hide
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 7e9ba5d..cb2517e 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -40,4 +40,6 @@
void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
void isApplicationQualifiedForRole(String roleName, String packageName,
in RemoteCallback callback);
+ void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
+ String permission, int grantState, in RemoteCallback callback);
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index d62bc6c5..cd7bbfd 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -16,8 +16,12 @@
package android.permission;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerService.SERVICE_INTERFACE;
+import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkFlagsArgument;
@@ -35,6 +39,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -268,6 +273,40 @@
}
/**
+ * Set the runtime permission state from a device admin.
+ *
+ * @param callerPackageName The package name of the admin requesting the change
+ * @param packageName Package the permission belongs to
+ * @param permission Permission to change
+ * @param grantState State to set the permission into
+ * @param executor Executor to run the {@code callback} on
+ * @param callback The callback
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY},
+ conditional = true)
+ public void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState, @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) {
+ checkStringNotEmpty(callerPackageName);
+ checkStringNotEmpty(packageName);
+ checkStringNotEmpty(permission);
+ checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
+ || grantState == PERMISSION_GRANT_STATE_DENIED
+ || grantState == PERMISSION_GRANT_STATE_DEFAULT);
+ checkNotNull(executor);
+ checkNotNull(callback);
+
+ mRemoteService.scheduleRequest(new PendingSetRuntimePermissionGrantStateByDeviceAdmin(
+ mRemoteService, callerPackageName, packageName, permission, grantState, executor,
+ callback));
+ }
+
+ /**
* Create a backup of the runtime permissions.
*
* @param user The user to be backed up
@@ -797,6 +836,67 @@
}
/**
+ * Request for {@link #getRuntimePermissionBackup}
+ */
+ private static final class PendingSetRuntimePermissionGrantStateByDeviceAdmin extends
+ AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
+ private final @NonNull String mCallerPackageName;
+ private final @NonNull String mPackageName;
+ private final @NonNull String mPermission;
+ private final @PermissionGrantState int mGrantState;
+
+ private final @NonNull Executor mExecutor;
+ private final @NonNull Consumer<Boolean> mCallback;
+ private final @NonNull RemoteCallback mRemoteCallback;
+
+ private PendingSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull RemoteService service,
+ @NonNull String callerPackageName, @NonNull String packageName,
+ @NonNull String permission, @PermissionGrantState int grantState,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ super(service);
+
+ mCallerPackageName = callerPackageName;
+ mPackageName = packageName;
+ mPermission = permission;
+ mGrantState = grantState;
+ mExecutor = executor;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ callback.accept(result.getBoolean(KEY_RESULT, false));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+
+ finish();
+ }
+ }), null);
+ }
+
+ @Override
+ protected void onTimeout(RemoteService remoteService) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.accept(false));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().setRuntimePermissionGrantStateByDeviceAdmin(
+ mCallerPackageName, mPackageName, mPermission, mGrantState, mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error setting permissions state for device admin " + mPackageName,
+ e);
+ }
+ }
+ }
+
+ /**
* Request for {@link #restoreRuntimePermissionBackup}
*/
private static final class PendingRestoreRuntimePermissionBackup implements
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index fb6c061..e883d25 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -16,6 +16,9 @@
package android.permission;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM;
@@ -32,6 +35,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Service;
+import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -180,6 +184,18 @@
public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
@NonNull String packageName);
+ /**
+ * Set the runtime permission state from a device admin.
+ *
+ * @param callerPackageName The package name of the admin requesting the change
+ * @param packageName Package the permission belongs to
+ * @param permission Permission to change
+ * @param grantState State to set the permission into
+ */
+ public abstract boolean onSetRuntimePermissionGrantStateByDeviceAdmin(
+ @NonNull String callerPackageName, @NonNull String packageName,
+ @NonNull String permission, @PermissionGrantState int grantState);
+
@Override
public final IBinder onBind(Intent intent) {
return new IPermissionController.Stub() {
@@ -326,6 +342,35 @@
PermissionControllerService::isApplicationQualifiedForRole,
PermissionControllerService.this, roleName, packageName, callback));
}
+
+ @Override
+ public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
+ String packageName, String permission, int grantState,
+ RemoteCallback callback) {
+ checkStringNotEmpty(callerPackageName);
+ checkStringNotEmpty(packageName);
+ checkStringNotEmpty(permission);
+ checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
+ || grantState == PERMISSION_GRANT_STATE_DENIED
+ || grantState == PERMISSION_GRANT_STATE_DEFAULT);
+ checkNotNull(callback);
+
+ if (grantState == PERMISSION_GRANT_STATE_DENIED) {
+ enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
+ }
+
+ if (grantState == PERMISSION_GRANT_STATE_DENIED) {
+ enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null);
+ }
+
+ enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
+ null);
+
+ mHandler.sendMessage(obtainMessage(
+ PermissionControllerService::setRuntimePermissionGrantStateByDeviceAdmin,
+ PermissionControllerService.this, callerPackageName, packageName,
+ permission, grantState, callback));
+ }
};
}
@@ -399,4 +444,15 @@
result.putBoolean(PermissionControllerManager.KEY_RESULT, qualified);
callback.sendResult(result);
}
+
+ private void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState, @NonNull RemoteCallback callback) {
+ boolean wasSet = onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
+ packageName, permission, grantState);
+
+ Bundle result = new Bundle();
+ result.putBoolean(PermissionControllerManager.KEY_RESULT, wasSet);
+ callback.sendResult(result);
+ }
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f63c0adb..44adc1c 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -783,7 +783,7 @@
String postDialDigits, String viaNumber, int presentation, int callType,
int features, PhoneAccountHandle accountHandle, long start, int duration,
Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
- boolean isRead, int callBlockReason, String callScreeningAppName,
+ boolean isRead, int callBlockReason, CharSequence callScreeningAppName,
String callScreeningComponentName, CallIdentification callIdentification) {
if (VERBOSE_LOG) {
Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
@@ -836,15 +836,19 @@
}
values.put(BLOCK_REASON, callBlockReason);
- values.put(CALL_SCREENING_APP_NAME, callScreeningAppName);
+ values.put(CALL_SCREENING_APP_NAME, charSequenceToString(callScreeningAppName));
values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName);
if (callIdentification != null) {
values.put(CALL_ID_PACKAGE_NAME, callIdentification.getCallScreeningPackageName());
- values.put(CALL_ID_APP_NAME, callIdentification.getCallScreeningAppName());
- values.put(CALL_ID_NAME, callIdentification.getName());
- values.put(CALL_ID_DESCRIPTION, callIdentification.getDescription());
- values.put(CALL_ID_DETAILS, callIdentification.getDetails());
+ values.put(CALL_ID_APP_NAME,
+ charSequenceToString(callIdentification.getCallScreeningAppName()));
+ values.put(CALL_ID_NAME,
+ charSequenceToString(callIdentification.getName()));
+ values.put(CALL_ID_DESCRIPTION,
+ charSequenceToString(callIdentification.getDescription()));
+ values.put(CALL_ID_DETAILS,
+ charSequenceToString(callIdentification.getDetails()));
values.put(CALL_ID_NUISANCE_CONFIDENCE, callIdentification.getNuisanceConfidence());
} else {
values.putNull(CALL_ID_PACKAGE_NAME);
@@ -987,6 +991,10 @@
return result;
}
+ private static String charSequenceToString(CharSequence sequence) {
+ return sequence == null ? null : sequence.toString();
+ }
+
/** @hide */
public static boolean shouldHaveSharedCallLogEntries(Context context,
UserManager userManager, int userId) {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index f6a8388..868a36b 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -169,7 +169,7 @@
*
* @hide for internal use only
*/
- String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_max";
+ String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_min";
/**
* The threshold used to determine if the pool should be refilled.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a465b32..1530626 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8131,6 +8131,7 @@
*
* @hide
*/
+ @TestApi
public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
private static final Validator ENABLED_VR_LISTENERS_VALIDATOR =
@@ -10780,6 +10781,7 @@
*
* @hide
*/
+ @TestApi
public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
/**
@@ -14096,18 +14098,17 @@
public static final String SHOW_TEMPERATURE_WARNING = "show_temperature_warning";
/**
+ * Whether to show the usb high temperature alarm notification.
+ * @hide
+ */
+ public static final String SHOW_USB_TEMPERATURE_ALARM = "show_usb_temperature_alarm";
+
+ /**
* Temperature at which the high temperature warning notification should be shown.
* @hide
*/
public static final String WARNING_TEMPERATURE = "warning_temperature";
-
- /**
- * USB Temperature at which the high temperature alarm notification should be shown.
- * @hide
- */
- public static final String USB_ALARM_TEMPERATURE = "usb_alarm_temperature";
-
/**
* Whether the diskstats logging task is enabled/disabled.
* @hide
diff --git a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
deleted file mode 100644
index bbcf7a9..0000000
--- a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
+++ /dev/null
@@ -1,80 +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 android.service.contentcapture;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.contentcapture.ContentCaptureEvent;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Not needed anymore...
- *
- * @deprecated ContentCaptureService should use
- * {@code #onContentCaptureEvent(ContentCaptureSessionId, ContentCaptureEvent)} instead.
- *
- * @hide
- */
-@SystemApi
-@TestApi
-@Deprecated
-public final class ContentCaptureEventsRequest implements Parcelable {
-// TODO(b/121051220): remove .java and .aidl once service implementation doesn't use it anymore
-
- private final ContentCaptureEvent mEvent;
-
- /** @hide */
- public ContentCaptureEventsRequest(@NonNull ContentCaptureEvent event) {
- mEvent = event;
- }
-
- /**
- * Gets the events.
- */
- @NonNull
- public List<ContentCaptureEvent> getEvents() {
- return Arrays.asList(mEvent);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mEvent, flags);
- }
-
- public static final Parcelable.Creator<ContentCaptureEventsRequest> CREATOR =
- new Parcelable.Creator<ContentCaptureEventsRequest>() {
-
- @Override
- public ContentCaptureEventsRequest createFromParcel(Parcel parcel) {
- return new ContentCaptureEventsRequest(parcel.readParcelable(null));
- }
-
- @Override
- public ContentCaptureEventsRequest[] newArray(int size) {
- return new ContentCaptureEventsRequest[size];
- }
- };
-}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index d032e56..9c4669f 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -234,17 +234,6 @@
}
/**
- *
- * @deprecated use {@link #onContentCaptureEvent(ContentCaptureSessionId, ContentCaptureEvent)}
- * instead.
- */
- @Deprecated
- public void onContentCaptureEventsRequest(@NonNull ContentCaptureSessionId sessionId,
- @NonNull ContentCaptureEventsRequest request) {
- if (sVerbose) Log.v(TAG, "onContentCaptureEventsRequest(id=" + sessionId + ")");
- }
-
- /**
* Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
* session.
*
@@ -254,7 +243,6 @@
public void onContentCaptureEvent(@NonNull ContentCaptureSessionId sessionId,
@NonNull ContentCaptureEvent event) {
if (sVerbose) Log.v(TAG, "onContentCaptureEventsRequest(id=" + sessionId + ")");
- onContentCaptureEventsRequest(sessionId, new ContentCaptureEventsRequest(event));
}
/**
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 5754014..1a508a1 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -16,6 +16,9 @@
package android.text.style;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -25,6 +28,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
/**
@@ -80,10 +84,21 @@
/**
* A constant indicating that this span should be vertically centered between
* the top and the lowest descender.
- * @hide
*/
public static final int ALIGN_CENTER = 2;
+ /**
+ * Defines acceptable alignment types.
+ * @hide
+ */
+ @Retention(SOURCE)
+ @IntDef(prefix = { "ALIGN_" }, value = {
+ ALIGN_BOTTOM,
+ ALIGN_BASELINE,
+ ALIGN_CENTER
+ })
+ public @interface AlignmentType {}
+
protected final int mVerticalAlignment;
@UnsupportedAppUsage
@@ -100,17 +115,18 @@
/**
* Creates a {@link DynamicDrawableSpan} based on a vertical alignment.\
*
- * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}
+ * @param verticalAlignment one of {@link #ALIGN_BOTTOM}, {@link #ALIGN_BASELINE} or
+ * {@link #ALIGN_CENTER}
*/
- protected DynamicDrawableSpan(int verticalAlignment) {
+ protected DynamicDrawableSpan(@AlignmentType int verticalAlignment) {
mVerticalAlignment = verticalAlignment;
}
/**
- * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or
- * {@link #ALIGN_BASELINE}.
+ * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM},
+ * {@link #ALIGN_BASELINE} or {@link #ALIGN_CENTER}.
*/
- public int getVerticalAlignment() {
+ public @AlignmentType int getVerticalAlignment() {
return mVerticalAlignment;
}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index e4c8eeb..f8b38e9 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemClock;
@@ -302,6 +303,7 @@
}
/** @hide Just for debugging; not internationalized. */
+ @TestApi
public static String formatDuration(long duration) {
synchronized (sFormatSync) {
int len = formatDurationLocked(duration, 0);
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index cb5100a..94a9a1c 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
import android.content.res.CompatibilityInfo;
@@ -911,6 +912,7 @@
* @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
* @hide
*/
+ @TestApi
// TODO (b/114338689): Remove the method and use IWindowManager#shouldShowSystemDecors
public boolean supportsSystemDecorations() {
return (mDisplayInfo.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 2ef7c4b..5dc54a5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -582,4 +582,13 @@
* display should be re-parented to.
*/
void reparentDisplayContent(int displayId, in SurfaceControl sc);
+
+ /**
+ * Waits for transactions to get applied before injecting input.
+ * This includes waiting for the input windows to get sent to InputManager.
+ *
+ * This is needed for testing since the system add windows and injects input
+ * quick enough that the windows don't have time to get sent to InputManager.
+ */
+ boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1212df0..aaf85af 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -189,6 +189,7 @@
IBinder toToken);
private static native boolean nativeGetProtectedContentSupport();
private static native void nativeSetMetadata(long transactionObj, int key, Parcel data);
+ private static native void nativeSyncInputWindows(long transactionObj);
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
@@ -489,7 +490,16 @@
}
mWidth = width;
mHeight = height;
- return this;
+ // set this as a buffer layer since we are specifying a buffer size.
+ return setFlags(FX_SURFACE_NORMAL, FX_SURFACE_MASK);
+ }
+
+ /**
+ * Set the initial size of the controlled surface's buffers in pixels.
+ */
+ private void unsetBufferSize() {
+ mWidth = 0;
+ mHeight = 0;
}
/**
@@ -607,16 +617,11 @@
* Color layers will not have an associated BufferQueue and will instead always render a
* solid color (that is, solid before plane alpha). Currently that color is black.
*
- * @param isColorLayer Whether to create a color layer.
* @hide
*/
- public Builder setColorLayer(boolean isColorLayer) {
- if (isColorLayer) {
- mFlags |= FX_SURFACE_DIM;
- } else {
- mFlags &= ~FX_SURFACE_DIM;
- }
- return this;
+ public Builder setColorLayer() {
+ unsetBufferSize();
+ return setFlags(FX_SURFACE_DIM, FX_SURFACE_MASK);
}
private boolean isColorLayerSet() {
@@ -629,16 +634,11 @@
* Container layers will not be rendered in any fashion and instead are used
* as a parent of renderable layers.
*
- * @param isContainerLayer Whether to create a container layer.
* @hide
*/
- public Builder setContainerLayer(boolean isContainerLayer) {
- if (isContainerLayer) {
- mFlags |= FX_SURFACE_CONTAINER;
- } else {
- mFlags &= ~FX_SURFACE_CONTAINER;
- }
- return this;
+ public Builder setContainerLayer() {
+ unsetBufferSize();
+ return setFlags(FX_SURFACE_CONTAINER, FX_SURFACE_MASK);
}
private boolean isContainerLayerSet() {
@@ -646,7 +646,7 @@
}
/**
- * Set 'Surface creation flags' such as {@link HIDDEN}, {@link SECURE}.
+ * Set 'Surface creation flags' such as {@link #HIDDEN}, {@link #SECURE}.
*
* TODO: Finish conversion to individual builder methods?
* @param flags The combined flags
@@ -656,6 +656,11 @@
mFlags = flags;
return this;
}
+
+ private Builder setFlags(int flags, int mask) {
+ mFlags = (mFlags & ~mask) | flags;
+ return this;
+ }
}
/**
@@ -2105,6 +2110,17 @@
}
/**
+ * Waits until any changes to input windows have been sent from SurfaceFlinger to
+ * InputFlinger before returning.
+ *
+ * @hide
+ */
+ public Transaction syncInputWindows() {
+ nativeSyncInputWindows(mNativeObject);
+ return this;
+ }
+
+ /**
* Specify how the buffer assosciated with this Surface is mapped in to the
* parent coordinate space. The source frame will be scaled to fit the destination
* frame, after being rotated according to the orientation parameter.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9f0800f..fe9aa23 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,7 +33,6 @@
import android.graphics.RenderNode;
import android.os.Build;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -588,7 +587,7 @@
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
.setName("Background for -" + name)
.setOpaque(true)
- .setColorLayer(true)
+ .setColorLayer()
.setParent(mSurfaceControl)
.build();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ab4847d..89c6703 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -29,6 +29,7 @@
import android.Manifest;
import android.animation.LayoutTransition;
+import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -1041,10 +1042,22 @@
return mHeight;
}
+ /**
+ * Destroys hardware rendering resources for this ViewRootImpl
+ *
+ * May be called on any thread
+ */
+ @AnyThread
void destroyHardwareResources() {
- if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.destroyHardwareResources(mView);
- mAttachInfo.mThreadedRenderer.destroy();
+ final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer;
+ if (renderer != null) {
+ // This is called by WindowManagerGlobal which may or may not be on the right thread
+ if (Looper.myLooper() != mAttachInfo.mHandler.getLooper()) {
+ mAttachInfo.mHandler.postAtFrontOfQueue(this::destroyHardwareResources);
+ return;
+ }
+ renderer.destroyHardwareResources(mView);
+ renderer.destroy();
}
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e9b1683..9dcbe05 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -28,6 +28,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -482,6 +483,9 @@
@GuardedBy("mLock")
private CompatibilityBridge mCompatibilityBridge;
+ @Nullable
+ private final AutofillOptions mOptions;
+
/** @hide */
public interface AutofillClient {
/**
@@ -618,6 +622,12 @@
public AutofillManager(Context context, IAutoFillManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
mService = service;
+ mOptions = context.getAutofillOptions();
+
+ if (mOptions != null) {
+ sDebug = (mOptions.loggingLevel & FLAG_ADD_CLIENT_DEBUG) != 0;
+ sVerbose = (mOptions.loggingLevel & FLAG_ADD_CLIENT_VERBOSE) != 0;
+ }
}
/**
@@ -2352,6 +2362,9 @@
pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds);
pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
+ if (mOptions != null) {
+ pw.print(pfx); pw.print("options: "); mOptions.dumpShort(pw); pw.println();
+ }
pw.print(pfx); pw.print("compat mode enabled: ");
synchronized (mLock) {
if (mCompatibilityBridge != null) {
diff --git a/core/java/android/view/autofill/AutofillManagerInternal.java b/core/java/android/view/autofill/AutofillManagerInternal.java
index 155fe72..d5862bd 100644
--- a/core/java/android/view/autofill/AutofillManagerInternal.java
+++ b/core/java/android/view/autofill/AutofillManagerInternal.java
@@ -16,7 +16,9 @@
package android.view.autofill;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.content.AutofillOptions;
/**
* Autofill Manager local system service interface.
@@ -31,12 +33,13 @@
public abstract void onBackKeyPressed();
/**
- * Gets whether compatibility mode is enabled for a package
+ * Gets autofill options for a package
*
* @param packageName The package for which to query.
* @param versionCode The package version code.
* @param userId The user id for which to query.
*/
- public abstract boolean isCompatibilityModeRequested(@NonNull String packageName,
+ @Nullable
+ public abstract AutofillOptions getAutofillOptions(@NonNull String packageName,
long versionCode, @UserIdInt int userId);
}
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index b0e7ad5..2ad17a8 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -94,7 +94,8 @@
if (actionIntents != null) {
final int size = actionIntents.size();
for (int i = 0; i < size; i++) {
- if (intentAction.equals(actionIntents.get(i).getAction())) {
+ final Intent intent = actionIntents.get(i);
+ if (intent != null && intentAction.equals(intent.getAction())) {
return classification.getActions().get(i);
}
}
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index a059209..052ee95 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -54,6 +54,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
* Information for generating a widget to handle classified text.
@@ -276,8 +277,8 @@
@Override
public String toString() {
return String.format(Locale.US,
- "TextClassification {text=%s, entities=%s, actions=%s, id=%s}",
- mText, mEntityConfidence, mActions, mId);
+ "TextClassification {text=%s, entities=%s, actions=%s, id=%s, extras=%s}",
+ mText, mEntityConfidence, mActions, mId, mExtras);
}
/**
@@ -532,7 +533,7 @@
private Bundle buildExtras() {
final Bundle extras = mExtras == null ? new Bundle() : mExtras.deepCopy();
- if (!mActionIntents.isEmpty()) {
+ if (mActionIntents.stream().anyMatch(Objects::nonNull)) {
ExtrasUtils.putActionsIntents(extras, mActionIntents);
}
if (mForeignLanguageExtra != null) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 295c8b7..e628f19 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -240,9 +240,7 @@
refTime.getZone().getId(),
localesString),
mContext,
- // TODO: Pass the locale list once it is supported in
- // native side.
- LocaleList.getDefault().get(0).toLanguageTag()
+ getResourceLocaleString()
);
if (results.length > 0) {
return createClassificationResult(
@@ -403,8 +401,7 @@
nativeConversation,
null,
mContext,
- // TODO: Pass the locale list once it is supported in native side.
- LocaleList.getDefault().get(0).toLanguageTag());
+ getResourceLocaleString());
return createConversationActionResult(request, nativeSuggestions);
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
@@ -456,10 +453,9 @@
TextLanguage textLanguage = detectLanguage(request);
int localeHypothesisCount = textLanguage.getLocaleHypothesisCount();
List<String> languageTags = new ArrayList<>();
- // TODO: Reconsider this and probably make the score threshold configurable.
for (int i = 0; i < localeHypothesisCount; i++) {
ULocale locale = textLanguage.getLocale(i);
- if (textLanguage.getConfidenceScore(locale) < 0.5) {
+ if (textLanguage.getConfidenceScore(locale) < getForeignLanguageThreshold()) {
break;
}
languageTags.add(locale.toLanguageTag());
@@ -587,15 +583,10 @@
}
}
- final float foreignTextThreshold = mSettings.getLangIdThresholdOverride() >= 0
- ? mSettings.getLangIdThresholdOverride()
- : 0.5f /* TODO: Load this from the langId model. */;
- final Bundle foreignLanguageBundle =
- detectForeignLanguage(classifiedText, foreignTextThreshold);
+ final Bundle foreignLanguageBundle = detectForeignLanguage(classifiedText);
builder.setForeignLanguageExtra(foreignLanguageBundle);
boolean isPrimaryAction = true;
- final ArrayList<Intent> sourceIntents = new ArrayList<>();
List<LabeledIntent> labeledIntents = mIntentFactory.create(
mContext,
classifiedText,
@@ -626,16 +617,20 @@
/**
* Returns a bundle with the language and confidence score if it finds the text to be
- * in a foreign language. Otherwise returns null.
+ * in a foreign language. Otherwise returns null. This algorithm defines what the system thinks
+ * is a foreign language.
*/
+ // TODO: Revisit this algorithm.
+ // TODO: Consider making this public API.
@Nullable
- private Bundle detectForeignLanguage(String text, float threshold) {
- if (threshold > 1) {
- return null;
- }
-
- // TODO: Revisit this algorithm.
+ private Bundle detectForeignLanguage(String text) {
try {
+ final float threshold = getForeignLanguageThreshold();
+ if (threshold > 1) {
+ Log.v(LOG_TAG, "Foreign language detection disabled.");
+ return null;
+ }
+
final LangIdModel langId = getLangIdImpl();
final LangIdModel.LanguageResult[] langResults = langId.detectLanguages(text);
if (langResults.length <= 0) {
@@ -651,8 +646,8 @@
if (highestScoringResult.getScore() < threshold) {
return null;
}
- // TODO: Remove
- Log.d(LOG_TAG, String.format("Language detected: <%s:%s>",
+
+ Log.v(LOG_TAG, String.format("Language detected: <%s:%s>",
highestScoringResult.getLanguage(), highestScoringResult.getScore()));
final Locale detected = new Locale(highestScoringResult.getLanguage());
@@ -671,6 +666,18 @@
return null;
}
+ private float getForeignLanguageThreshold() {
+ try {
+ return mSettings.getLangIdThresholdOverride() >= 0
+ ? mSettings.getLangIdThresholdOverride()
+ : getLangIdImpl().getTranslateThreshold();
+ } catch (FileNotFoundException e) {
+ final float defaultThreshold = 0.5f;
+ Log.v(LOG_TAG, "Using default foreign language threshold: " + defaultThreshold);
+ return defaultThreshold;
+ }
+ }
+
@Override
public void dump(@NonNull IndentingPrintWriter printWriter) {
synchronized (mLock) {
@@ -719,6 +726,19 @@
}
/**
+ * Returns the locale string for the current resources configuration.
+ */
+ private String getResourceLocaleString() {
+ // TODO: Pass the locale list once it is supported in native side.
+ try {
+ return mContext.getResources().getConfiguration().getLocales().get(0).toLanguageTag();
+ } catch (NullPointerException e) {
+ // NPE is unexpected. Erring on the side of caution.
+ return LocaleList.getDefault().get(0).toLanguageTag();
+ }
+ }
+
+ /**
* Helper class to store the information from which RemoteActions are built.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 0fbd4dc..89e3d6b 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -381,6 +381,8 @@
final long systemCost = mChooserShownTime - intentReceivedTime;
getMetricsLogger().write(new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN)
+ .setSubtype(isWorkProfile() ? MetricsEvent.MANAGED_PROFILE :
+ MetricsEvent.PARENT_PROFILE)
.addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
.addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
@@ -418,6 +420,16 @@
}
/**
+ * Check if the profile currently used is a work profile.
+ * @return true if it is work profile, false if it is parent profile (or no work profile is
+ * set up)
+ */
+ protected boolean isWorkProfile() {
+ return ((UserManager) getSystemService(Context.USER_SERVICE))
+ .getUserInfo(UserHandle.myUserId()).isManagedProfile();
+ }
+
+ /**
* Override method to add content preview area, specific to the chooser activity.
*/
@Override
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index d13bcf2..64f0010 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.metrics.LogMaker;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -39,6 +40,8 @@
import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.util.Arrays;
import java.util.HashSet;
@@ -66,6 +69,8 @@
private Injector mInjector;
+ private MetricsLogger mMetricsLogger;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -78,9 +83,17 @@
if (className.equals(FORWARD_INTENT_TO_PARENT)) {
userMessageId = com.android.internal.R.string.forward_intent_to_owner;
targetUserId = getProfileParent();
+
+ getMetricsLogger().write(
+ new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
+ .setSubtype(MetricsEvent.PARENT_PROFILE));
} else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
userMessageId = com.android.internal.R.string.forward_intent_to_work;
targetUserId = getManagedProfile();
+
+ getMetricsLogger().write(
+ new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
+ .setSubtype(MetricsEvent.MANAGED_PROFILE));
} else {
Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
userMessageId = -1;
@@ -257,6 +270,13 @@
intent.setComponent(null);
}
+ protected MetricsLogger getMetricsLogger() {
+ if (mMetricsLogger == null) {
+ mMetricsLogger = new MetricsLogger();
+ }
+ return mMetricsLogger;
+ }
+
@VisibleForTesting
protected Injector createInjector() {
return new InjectorImpl();
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 7f4d8a2..2c78be7 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -51,7 +51,7 @@
public class BinderCallsStats implements BinderInternal.Observer {
public static final boolean ENABLED_DEFAULT = true;
public static final boolean DETAILED_TRACKING_DEFAULT = true;
- public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
+ public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 1000;
public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true;
public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 6b8d8b1..003ee37 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -406,6 +406,11 @@
transaction->transferTouchFocus(fromToken, toToken);
}
+static void nativeSyncInputWindows(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->syncInputWindows();
+}
+
static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint id, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
@@ -1246,7 +1251,9 @@
"(Landroid/os/IBinder;JJ)Landroid/hardware/display/DisplayedContentSample;",
(void*)nativeGetDisplayedContentSample },
{"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
- (void*)nativeSetGeometry }
+ (void*)nativeSetGeometry },
+ {"nativeSyncInputWindows", "(J)V",
+ (void*)nativeSyncInputWindows }
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 15ceca9..4c5b284 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -613,17 +613,13 @@
}
}
-static void CreatePkgSandboxTarget(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
- // Create /mnt/user/0/package/<package-name>
- userid_t user_id = multiuser_get_user_id(uid);
- std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
+static void CreatePkgSandboxTarget(userid_t userId, fail_fn_t fail_fn) {
+ // Create /mnt/user/0/package
+ std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", userId);
CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
StringAppendF(&pkg_sandbox_dir, "/package");
- CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
-
- StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
- CreateDir(pkg_sandbox_dir, 0755, uid, uid, fail_fn);
+ CreateDir(pkg_sandbox_dir, 0755, AID_ROOT, AID_ROOT, fail_fn);
}
static void BindMount(const std::string& sourceDir, const std::string& targetDir,
@@ -650,25 +646,25 @@
BindMount(mntSourceDir, mntTargetDir, fail_fn);
}
-static void CreateSubDirs(int dirfd, const std::string& parentDirPath,
+static void CreateSubDirs(int parentFd, const std::string& parentPath,
const std::vector<std::string>& subDirs,
fail_fn_t fail_fn) {
for (auto& dirName : subDirs) {
struct stat sb;
- if (TEMP_FAILURE_RETRY(fstatat(dirfd, dirName.c_str(), &sb, 0)) == 0) {
+ if (TEMP_FAILURE_RETRY(fstatat(parentFd, dirName.c_str(), &sb, 0)) == 0) {
if (S_ISDIR(sb.st_mode)) {
continue;
- } else if (TEMP_FAILURE_RETRY(unlinkat(dirfd, dirName.c_str(), 0)) == -1) {
+ } else if (TEMP_FAILURE_RETRY(unlinkat(parentFd, dirName.c_str(), 0)) == -1) {
fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ parentPath.c_str(), dirName.c_str(), strerror(errno)));
}
} else if (errno != ENOENT) {
fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ parentPath.c_str(), dirName.c_str(), strerror(errno)));
}
- if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1 && errno != EEXIST) {
+ if (TEMP_FAILURE_RETRY(mkdirat(parentFd, dirName.c_str(), 0700)) == -1 && errno != EEXIST) {
fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ parentPath.c_str(), dirName.c_str(), strerror(errno)));
}
}
}
@@ -754,6 +750,9 @@
if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) == -1) {
ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno));
continue;
+ } else if (TEMP_FAILURE_RETRY(access(mntTarget.c_str(), F_OK)) == -1) {
+ ALOGE("Can't access %s: %s", mntTarget.c_str(), strerror(errno));
+ continue;
}
// Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb}
@@ -782,6 +781,39 @@
}
}
+static void handleMountModeInstaller(int mountMode,
+ userid_t userId,
+ const std::string& sandboxId,
+ fail_fn_t fail_fn) {
+ std::string obbMountDir = StringPrintf("/mnt/user/%d/obb_mount", userId);
+ std::string obbMountFile = StringPrintf("%s/%s", obbMountDir.c_str(), sandboxId.c_str());
+ if (mountMode == MOUNT_EXTERNAL_INSTALLER) {
+ if (TEMP_FAILURE_RETRY(access(obbMountFile.c_str(), F_OK)) != -1) {
+ return;
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to access %s: %s", obbMountFile.c_str(), strerror(errno)));
+ }
+ if (fs_prepare_dir(obbMountDir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
+ fail_fn(CREATE_ERROR("Failed to fs_prepare_dir %s: %s",
+ obbMountDir.c_str(), strerror(errno)));
+ }
+ const android::base::unique_fd fd(TEMP_FAILURE_RETRY(
+ open(obbMountFile.c_str(), O_RDWR | O_CREAT, 0600)));
+ if (fd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to create %s: %s", obbMountFile.c_str(), strerror(errno)));
+ }
+ } else {
+ if (TEMP_FAILURE_RETRY(access(obbMountFile.c_str(), F_OK)) != -1) {
+ if (TEMP_FAILURE_RETRY(unlink(obbMountFile.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ obbMountDir.c_str(), strerror(errno)));
+ }
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to access %s: %s", obbMountFile.c_str(), strerror(errno)));
+ }
+ }
+}
+
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -844,48 +876,19 @@
}
userid_t user_id = multiuser_get_user_id(uid);
- std::string pkgSandboxDir =
- StringPrintf("/mnt/user/%d/package/%s", user_id, package_name.c_str());
- bool sandboxAlreadyCreated = true;
- if (TEMP_FAILURE_RETRY(access(pkgSandboxDir.c_str(), F_OK)) == -1) {
- if (errno == ENOENT) {
- ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str());
- sandboxAlreadyCreated = false;
- CreatePkgSandboxTarget(uid, package_name, fail_fn);
- } else {
- fail_fn(CREATE_ERROR("Failed to access %s: %s",
- pkgSandboxDir.c_str(), strerror(errno)));
- }
- }
+ CreatePkgSandboxTarget(user_id, fail_fn);
+ std::string pkgSandboxDir = StringPrintf("/mnt/user/%d/package", user_id);
if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
pkgSandboxDir.c_str(), strerror(errno)));
}
- if (TEMP_FAILURE_RETRY(access("/storage/obb_mount", F_OK)) == 0) {
- if (mount_mode != MOUNT_EXTERNAL_INSTALLER) {
- remove("/storage/obb_mount");
- }
- } else {
- if (mount_mode == MOUNT_EXTERNAL_INSTALLER) {
- int fd =
- TEMP_FAILURE_RETRY(open("/storage/obb_mount", O_RDWR | O_CREAT, 0660));
- if (fd == -1) {
- fail_fn(CREATE_ERROR("Couldn't create /storage/obb_mount: %s",
- strerror(errno)));
- }
- close(fd);
- }
- }
- // If the sandbox was already created by vold, only then set up the bind mounts for
- // pkg specific directories. Otherwise, leave as is and bind mounts will be taken
- // care of by vold later.
- if (sandboxAlreadyCreated) {
- PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
- mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
- }
+ handleMountModeInstaller(mount_mode, user_id, sandbox_id, fail_fn);
+
+ PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
+ mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
}
} else {
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", nullptr,
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index cccb40d..c1cbd52 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -920,8 +920,7 @@
// Temperature at which the high temperature warning notification should
// be shown.
optional SettingProto warning_temperature_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // USB temperature at which the high temperature alarm notification should be shown.
- optional SettingProto usb_alarm_temperature_level = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_usb_temperature_alarm = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional TemperatureWarning temperature_warning = 119;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5b74d90..0149365 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1167,8 +1167,7 @@
<!-- ====================================================================== -->
<eat-comment />
- <!-- Used for permissions that are associated with activity recognition.
- TODO(zezeozue). STOPSHIP: Add icon -->
+ <!-- Used for permissions that are associated with activity recognition. -->
<permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
android:icon="@drawable/perm_group_activity_recognition"
android:label="@string/permgrouplab_activityRecognition"
@@ -3419,6 +3418,11 @@
<permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to change policy_fixed permissions.
+ @hide -->
+ <permission android:name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"
+ android:protectionLevel="signature|installer" />
+
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6571cd2..eb69535 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2673,11 +2673,6 @@
</string-array>
- <!-- Flag indicating that this device does not rotate and will always remain in its default
- orientation. Activities that desire to run in a non-compatible orientation will be run
- from an emulated display within the physical display. -->
- <bool name="config_forceDefaultOrientation">false</bool>
-
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e1ce2f6..5a3c536 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2998,6 +2998,8 @@
<public name="config_showDefaultEmergency" />
<!-- @hide @SystemApi -->
<public name="config_showDefaultHome" />
+ <!-- @hide @TestApi -->
+ <public name="config_perDisplayFocusEnabled" />
</public-group>
<public-group type="dimen" first-id="0x01050007">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ae239e..8df0e19 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -347,7 +347,6 @@
<java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
<java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
<java-symbol type="bool" name="config_useFixedVolume" />
- <java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_wifi_softap_acs_supported" />
<java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 9fabe44..d73c174 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -28,6 +28,7 @@
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
@@ -407,7 +408,7 @@
IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
boolean b2, boolean b3, Configuration configuration,
CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
- boolean autofillCompatEnabled, ContentCaptureOptions o) throws RemoteException {
+ AutofillOptions ao, ContentCaptureOptions co) throws RemoteException {
}
@Override
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 46cac7a..3a1a4fc 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -429,6 +429,7 @@
Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
Settings.Global.SHOW_TEMPERATURE_WARNING,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
Settings.Global.SIGNED_CONFIG_VERSION,
Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
@@ -504,7 +505,6 @@
Settings.Global.USER_SWITCHER_ENABLED,
Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
Settings.Global.WARNING_TEMPERATURE,
- Settings.Global.USB_ALARM_TEMPERATURE,
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
Settings.Global.WEBVIEW_MULTIPROCESS,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index 99c959e..d544029 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -93,8 +93,8 @@
final String id = "id";
final TextClassification reference = new TextClassification.Builder()
.setText(text)
- .addAction(remoteAction0)
- .addAction(remoteAction1)
+ .addAction(remoteAction0) // Action intent not included.
+ .addAction(remoteAction1) // Action intent not included.
.setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
.setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
.setId(id)
@@ -132,6 +132,7 @@
// Extras
assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
+ assertNull(ExtrasUtils.getActionsIntents(result));
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index f27f3f9..9fbc166 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -57,7 +57,7 @@
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import org.junit.Before;
import org.junit.Rule;
@@ -524,15 +524,45 @@
waitForIdle();
verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
assertThat(logMakerCaptor
.getAllValues().get(0)
- .getTaggedData(MetricsProto.MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
+ .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
is(notNullValue()));
assertThat(logMakerCaptor
.getAllValues().get(0)
- .getTaggedData(MetricsProto.MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
+ .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
is("TestType"));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getSubtype(),
+ is(MetricsEvent.PARENT_PROFILE));
+ }
+
+ @Test
+ public void testOnCreateLoggingFromWorkProfile() {
+ Intent sendIntent = createSendTextIntent();
+ sendIntent.setType("TestType");
+ sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE;
+ MetricsLogger mockLogger = sOverrides.metricsLogger;
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
+ waitForIdle();
+ verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
+ assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
+ is(notNullValue()));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
+ is("TestType"));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getSubtype(),
+ is(MetricsEvent.MANAGED_PROFILE));
}
@Test
@@ -547,7 +577,7 @@
verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
}
@Test
@@ -569,7 +599,7 @@
verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
is(CONTENT_PREVIEW_TEXT));
}
@@ -599,11 +629,11 @@
verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
is(CONTENT_PREVIEW_IMAGE));
assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
is(CONTENT_PREVIEW_IMAGE));
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 57c84ff..a8dd69a 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -28,6 +28,7 @@
import android.util.Size;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.util.function.Function;
@@ -112,6 +113,14 @@
return super.queryResolver(resolver, uri);
}
+ @Override
+ protected boolean isWorkProfile() {
+ if (sOverrides.alternateProfileSetting != 0) {
+ return sOverrides.alternateProfileSetting == MetricsEvent.MANAGED_PROFILE;
+ }
+ return super.isWorkProfile();
+ }
+
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -128,6 +137,7 @@
public boolean resolverForceException;
public Bitmap previewThumbnail;
public MetricsLogger metricsLogger;
+ public int alternateProfileSetting;
public void reset() {
onSafelyStartCallback = null;
@@ -139,6 +149,7 @@
resolverForceException = false;
resolverListController = mock(ResolverListController.class);
metricsLogger = mock(MetricsLogger.class);
+ alternateProfileSetting = 0;
}
}
}
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index 9b13af2..abfb4fb 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +41,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -51,6 +53,9 @@
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -70,6 +75,11 @@
"android",
IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE
);
+ private static final ComponentName FORWARD_TO_PARENT_COMPONENT_NAME =
+ new ComponentName(
+ "android",
+ IntentForwarderActivity.FORWARD_INTENT_TO_PARENT
+ );
private static final String TYPE_PLAIN_TEXT = "text/plain";
private static UserInfo MANAGED_PROFILE_INFO = new UserInfo();
@@ -522,6 +532,60 @@
verify(sInjector).showToast(anyInt(), anyInt());
}
+ @Test
+ public void forwardToManagedProfile_LoggingTest() throws Exception {
+ sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+
+ // Intent can be forwarded.
+ when(mIPm.canForwardTo(
+ any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+
+ // Managed profile exists.
+ List<UserInfo> profiles = new ArrayList<>();
+ profiles.add(CURRENT_USER_INFO);
+ profiles.add(MANAGED_PROFILE_INFO);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+
+ Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class);
+ intent.setAction(Intent.ACTION_SEND);
+ intent.setType(TYPE_PLAIN_TEXT);
+ IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent);
+
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ verify(activity.getMetricsLogger()).write(logMakerCaptor.capture());
+ assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE,
+ logMakerCaptor.getValue().getCategory());
+ assertEquals(MetricsEvent.MANAGED_PROFILE,
+ logMakerCaptor.getValue().getSubtype());
+ }
+
+ @Test
+ public void forwardToParent_LoggingTest() throws Exception {
+ sComponentName = FORWARD_TO_PARENT_COMPONENT_NAME;
+
+ // Intent can be forwarded.
+ when(mIPm.canForwardTo(
+ any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+
+ // Managed profile exists.
+ List<UserInfo> profiles = new ArrayList<>();
+ profiles.add(CURRENT_USER_INFO);
+ profiles.add(MANAGED_PROFILE_INFO);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+
+ Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class);
+ intent.setAction(Intent.ACTION_SEND);
+ intent.setType(TYPE_PLAIN_TEXT);
+ IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent);
+
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ verify(activity.getMetricsLogger()).write(logMakerCaptor.capture());
+ assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE,
+ logMakerCaptor.getValue().getCategory());
+ assertEquals(MetricsEvent.PARENT_PROFILE,
+ logMakerCaptor.getValue().getSubtype());
+ }
+
private void setupShouldSkipDisclosureTest() throws RemoteException {
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
sActivityName = "MyTestActivity";
@@ -541,6 +605,7 @@
private Intent mStartActivityIntent;
private int mUserIdActivityLaunchedIn;
+ private MetricsLogger mMetricsLogger = mock(MetricsLogger.class);
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -559,6 +624,11 @@
mStartActivityIntent = intent;
mUserIdActivityLaunchedIn = userId;
}
+
+ @Override
+ protected MetricsLogger getMetricsLogger() {
+ return mMetricsLogger;
+ }
}
public class TestInjector implements IntentForwarderActivity.Injector {
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 6264774..15d855e 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,7 +16,43 @@
package android.graphics;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class ImageFormat {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ UNKNOWN,
+ RGB_565,
+ YV12,
+ Y8,
+ Y16,
+ NV16,
+ NV21,
+ YUY2,
+ JPEG,
+ DEPTH_JPEG,
+ YUV_420_888,
+ YUV_422_888,
+ YUV_444_888,
+ FLEX_RGB_888,
+ FLEX_RGBA_8888,
+ RAW_SENSOR,
+ RAW_PRIVATE,
+ RAW10,
+ RAW12,
+ DEPTH16,
+ DEPTH_POINT_CLOUD,
+ RAW_DEPTH,
+ PRIVATE,
+ HEIC
+ })
+ public @interface Format {
+ }
+
/*
* these constants are chosen to be binary compatible with their previous
* location in PixelFormat.java
@@ -731,7 +767,7 @@
* @return the number of bits per pixel of the given format or -1 if the
* format doesn't exist or is not supported.
*/
- public static int getBitsPerPixel(int format) {
+ public static int getBitsPerPixel(@Format int format) {
switch (format) {
case RGB_565:
return 16;
@@ -781,7 +817,7 @@
*
* @hide
*/
- public static boolean isPublicFormat(int format) {
+ public static boolean isPublicFormat(@Format int format) {
switch (format) {
case RGB_565:
case NV16:
diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java
index 3ce48b4..9d3211d 100644
--- a/location/java/android/location/GnssMeasurementCorrections.java
+++ b/location/java/android/location/GnssMeasurementCorrections.java
@@ -124,7 +124,7 @@
* Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
* satellite in view
*/
- public @Nullable List<GnssSingleSatCorrection> getSingleSatCorrectionList() {
+ public @Nullable List<GnssSingleSatCorrection> getSingleSatelliteCorrectionList() {
return mSingleSatCorrectionList;
}
@@ -137,7 +137,7 @@
new Creator<GnssMeasurementCorrections>() {
@Override
public GnssMeasurementCorrections createFromParcel(Parcel parcel) {
- GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
+ final GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
new Builder()
.setLatitudeDegrees(parcel.readDouble())
.setLongitudeDegrees(parcel.readDouble())
@@ -147,7 +147,7 @@
.setToaGpsNanosecondsOfWeek(parcel.readLong());
List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
- gnssMeasurementCorrectons.setSingleSatCorrectionList(
+ gnssMeasurementCorrectons.setSingleSatelliteCorrectionList(
singleSatCorrectionList.isEmpty() ? null : singleSatCorrectionList);
return gnssMeasurementCorrectons.build();
}
@@ -188,7 +188,7 @@
}
/** Builder for {@link GnssMeasurementCorrections} */
- public static class Builder {
+ public static final class Builder {
/**
* For documentation of below fields, see corresponding fields in {@link
* GnssMeasurementCorrections}.
@@ -253,7 +253,7 @@
* Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for
* a satellite in view
*/
- public Builder setSingleSatCorrectionList(
+ public Builder setSingleSatelliteCorrectionList(
@Nullable List<GnssSingleSatCorrection> singleSatCorrectionList) {
if (singleSatCorrectionList == null) {
mSingleSatCorrectionList = null;
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
index 64b3752..9a106a7 100644
--- a/location/java/android/location/GnssReflectingPlane.java
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -116,7 +116,7 @@
}
/** Builder for {@link GnssReflectingPlane} */
- public static class Builder {
+ public static final class Builder {
/** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
private double mLatitudeDegrees;
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
index 4d5303f..f719e1a 100644
--- a/location/java/android/location/GnssSingleSatCorrection.java
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -60,6 +60,7 @@
private int mSingleSatCorrectionFlags;
/** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
+ @GnssStatus.ConstellationType
private int mConstellationType;
/**
@@ -115,7 +116,7 @@
}
/** Gets a bitmask of fields present in this object */
- public int getSingleSatCorrectionFlags() {
+ public int getSingleSatelliteCorrectionFlags() {
return mSingleSatCorrectionFlags;
}
@@ -136,7 +137,7 @@
* <p>Interpretation depends on {@link #getConstellationType()}. See {@link
* GnssStatus#getSvid(int)}.
*/
- public int getSatId() {
+ public int getSatelliteId() {
return mSatId;
}
@@ -162,7 +163,7 @@
* location.
*/
@FloatRange(from = 0f, to = 1f)
- public float getProbSatIsLos() {
+ public float getProbabilityLineOfSight() {
return mProbSatIsLos;
}
@@ -189,8 +190,8 @@
return mReflectingPlane;
}
- /** Returns {@code true} if {@link #getProbSatIsLos()} is valid. */
- public boolean hasSatelliteLineOfSight() {
+ /** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */
+ public boolean hasValidSatelliteLineOfSight() {
return (mSingleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0;
}
@@ -220,11 +221,11 @@
public GnssSingleSatCorrection createFromParcel(Parcel parcel) {
GnssSingleSatCorrection singleSatCorrection =
new Builder()
- .setSingleSatCorrectionFlags(parcel.readInt())
+ .setSingleSatelliteCorrectionFlags(parcel.readInt())
.setConstellationType(parcel.readInt())
- .setSatId(parcel.readInt())
+ .setSatelliteId(parcel.readInt())
.setCarrierFrequencyHz(parcel.readFloat())
- .setProbSatIsLos(parcel.readFloat())
+ .setProbabilityLineOfSight(parcel.readFloat())
.setExcessPathLengthMeters(parcel.readFloat())
.setExcessPathLengthUncertaintyMeters(parcel.readFloat())
.setReflectingPlane(
@@ -272,7 +273,7 @@
}
/** Builder for {@link GnssSingleSatCorrection} */
- public static class Builder {
+ public static final class Builder {
/**
* For documentation of below fields, see corresponding fields in {@link
@@ -289,19 +290,19 @@
private GnssReflectingPlane mReflectingPlane;
/** Sets a bitmask of fields present in this object */
- public Builder setSingleSatCorrectionFlags(int singleSatCorrectionFlags) {
+ public Builder setSingleSatelliteCorrectionFlags(int singleSatCorrectionFlags) {
mSingleSatCorrectionFlags = singleSatCorrectionFlags;
return this;
}
/** Sets the constellation type. */
- public Builder setConstellationType(int constellationType) {
+ public Builder setConstellationType(@GnssStatus.ConstellationType int constellationType) {
mConstellationType = constellationType;
return this;
}
- /** Sets the Satellite ID. */
- public Builder setSatId(int satId) {
+ /** Sets the Satellite ID defined in the ICD of the given constellation. */
+ public Builder setSatelliteId(int satId) {
mSatId = satId;
return this;
}
@@ -316,7 +317,8 @@
* Sets the line-of-sight probability of the satellite at the given location in the range
* between 0 and 1.
*/
- public Builder setProbSatIsLos(@FloatRange(from = 0f, to = 1f) float probSatIsLos) {
+ public Builder setProbabilityLineOfSight(
+ @FloatRange(from = 0f, to = 1f) float probSatIsLos) {
Preconditions.checkArgumentInRange(
probSatIsLos, 0, 1, "probSatIsLos should be between 0 and 1.");
mProbSatIsLos = probSatIsLos;
diff --git a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
index 8f46e84..ae5ca40 100644
--- a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
+++ b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
@@ -53,15 +53,15 @@
assertEquals(604000000000000L, measurementCorrections.getToaGpsNanosecondsOfWeek());
GnssSingleSatCorrection singleSatCorrection =
- measurementCorrections.getSingleSatCorrectionList().get(0);
+ measurementCorrections.getSingleSatelliteCorrectionList().get(0);
GnssSingleSatCorrectionsTest.verifyTestValues(singleSatCorrection);
- singleSatCorrection = measurementCorrections.getSingleSatCorrectionList().get(1);
- assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags());
+ singleSatCorrection = measurementCorrections.getSingleSatelliteCorrectionList().get(1);
+ assertEquals(15, singleSatCorrection.getSingleSatelliteCorrectionFlags());
assertEquals(GnssStatus.CONSTELLATION_GPS, singleSatCorrection.getConstellationType());
- assertEquals(11, singleSatCorrection.getSatId());
+ assertEquals(11, singleSatCorrection.getSatelliteId());
assertEquals(1575430000f, singleSatCorrection.getCarrierFrequencyHz());
- assertEquals(0.9f, singleSatCorrection.getProbSatIsLos());
+ assertEquals(0.9f, singleSatCorrection.getProbabilityLineOfSight());
assertEquals(50.0f, singleSatCorrection.getExcessPathLengthMeters());
assertEquals(55.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters());
GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane();
@@ -82,17 +82,17 @@
List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
singleSatCorrectionList.add(GnssSingleSatCorrectionsTest.generateTestSingleSatCorrection());
singleSatCorrectionList.add(generateTestSingleSatCorrection());
- measurementCorrections.setSingleSatCorrectionList(singleSatCorrectionList);
+ measurementCorrections.setSingleSatelliteCorrectionList(singleSatCorrectionList);
}
private static GnssSingleSatCorrection generateTestSingleSatCorrection() {
GnssSingleSatCorrection.Builder singleSatCorrection = new GnssSingleSatCorrection.Builder();
singleSatCorrection
- .setSingleSatCorrectionFlags(8)
+ .setSingleSatelliteCorrectionFlags(8)
.setConstellationType(GnssStatus.CONSTELLATION_GPS)
- .setSatId(11)
+ .setSatelliteId(11)
.setCarrierFrequencyHz(1575430000f)
- .setProbSatIsLos(0.9f)
+ .setProbabilityLineOfSight(0.9f)
.setExcessPathLengthMeters(50.0f)
.setExcessPathLengthUncertaintyMeters(55.0f)
.setReflectingPlane(generateTestReflectingPlane());
diff --git a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
index f358806..60f33f0 100644
--- a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
+++ b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
@@ -40,11 +40,11 @@
}
public static void verifyTestValues(GnssSingleSatCorrection singleSatCorrection) {
- assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags());
+ assertEquals(15, singleSatCorrection.getSingleSatelliteCorrectionFlags());
assertEquals(GnssStatus.CONSTELLATION_GALILEO, singleSatCorrection.getConstellationType());
- assertEquals(12, singleSatCorrection.getSatId());
+ assertEquals(12, singleSatCorrection.getSatelliteId());
assertEquals(1575420000f, singleSatCorrection.getCarrierFrequencyHz());
- assertEquals(0.1f, singleSatCorrection.getProbSatIsLos());
+ assertEquals(0.1f, singleSatCorrection.getProbabilityLineOfSight());
assertEquals(10.0f, singleSatCorrection.getExcessPathLengthMeters());
assertEquals(5.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters());
GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane();
@@ -52,27 +52,27 @@
}
private static void setTestValues(GnssSingleSatCorrection.Builder singleSatCorrection) {
- GnssSingleSatCorrection singleSatCorr = generateTestSingleSatCorrection();
+ GnssSingleSatCorrection singleSatCor = generateTestSingleSatCorrection();
singleSatCorrection
- .setSingleSatCorrectionFlags(singleSatCorr.getSingleSatCorrectionFlags())
- .setConstellationType(singleSatCorr.getConstellationType())
- .setSatId(singleSatCorr.getSatId())
- .setCarrierFrequencyHz(singleSatCorr.getCarrierFrequencyHz())
- .setProbSatIsLos(singleSatCorr.getProbSatIsLos())
- .setExcessPathLengthMeters(singleSatCorr.getExcessPathLengthMeters())
+ .setSingleSatelliteCorrectionFlags(singleSatCor.getSingleSatelliteCorrectionFlags())
+ .setConstellationType(singleSatCor.getConstellationType())
+ .setSatelliteId(singleSatCor.getSatelliteId())
+ .setCarrierFrequencyHz(singleSatCor.getCarrierFrequencyHz())
+ .setProbabilityLineOfSight(singleSatCor.getProbabilityLineOfSight())
+ .setExcessPathLengthMeters(singleSatCor.getExcessPathLengthMeters())
.setExcessPathLengthUncertaintyMeters(
- singleSatCorr.getExcessPathLengthUncertaintyMeters())
- .setReflectingPlane(singleSatCorr.getReflectingPlane());
+ singleSatCor.getExcessPathLengthUncertaintyMeters())
+ .setReflectingPlane(singleSatCor.getReflectingPlane());
}
public static GnssSingleSatCorrection generateTestSingleSatCorrection() {
GnssSingleSatCorrection.Builder singleSatCorrection =
new GnssSingleSatCorrection.Builder()
- .setSingleSatCorrectionFlags(15)
+ .setSingleSatelliteCorrectionFlags(15)
.setConstellationType(GnssStatus.CONSTELLATION_GALILEO)
- .setSatId(12)
+ .setSatelliteId(12)
.setCarrierFrequencyHz(1575420000f)
- .setProbSatIsLos(0.1f)
+ .setProbabilityLineOfSight(0.1f)
.setExcessPathLengthMeters(10.0f)
.setExcessPathLengthUncertaintyMeters(5.0f)
.setReflectingPlane(GnssReflectingPlaneTest.generateTestReflectingPlane());
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 10accf2..4f2de23 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -401,7 +401,7 @@
int initResult = native_setup( new WeakReference<AudioRecord>(this),
mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
mAudioFormat, mNativeBufferSizeInBytes,
- session, ActivityThread.currentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
+ session, getCurrentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
return; // with mState == STATE_UNINITIALIZED
@@ -413,6 +413,15 @@
mState = STATE_INITIALIZED;
}
+ private String getCurrentOpPackageName() {
+ String opPackageName = ActivityThread.currentOpPackageName();
+ if (opPackageName != null) {
+ return opPackageName;
+ }
+ // Command line utility
+ return "uid:" + Binder.getCallingUid();
+ }
+
/**
* A constructor which explicitly connects a Native (C++) AudioRecord. For use by
* the AudioRecordRoutingProxy subclass.
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 6116429..ba87f2b 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -16,8 +16,12 @@
package android.media;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.graphics.ImageFormat;
+import android.graphics.ImageFormat.Format;
import android.hardware.HardwareBuffer;
+import android.hardware.HardwareBuffer.Usage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -120,7 +124,11 @@
* Must be greater than 0.
* @see Image
*/
- public static ImageReader newInstance(int width, int height, int format, int maxImages) {
+ public static @NonNull ImageReader newInstance(
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @Format int format,
+ @IntRange(from = 1) int maxImages) {
// If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
// work, and is inscrutable anyway
return new ImageReader(width, height, format, maxImages,
@@ -210,8 +218,12 @@
* @see Image
* @see HardwareBuffer
*/
- public static ImageReader newInstance(int width, int height, int format, int maxImages,
- long usage) {
+ public static @NonNull ImageReader newInstance(
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @Format int format,
+ @IntRange(from = 1) int maxImages,
+ @Usage long usage) {
// TODO: Check this - can't do it just yet because format support is different
// Unify formats! The only reliable way to validate usage is to just try it and see.
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index dd09afc..f813d1b 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -16,7 +16,10 @@
package android.media;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.graphics.ImageFormat;
+import android.graphics.ImageFormat.Format;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.camera2.utils.SurfaceUtils;
@@ -124,7 +127,8 @@
* {@link #dequeueInputImage()}.
* @return a new ImageWriter instance.
*/
- public static ImageWriter newInstance(Surface surface, int maxImages) {
+ public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
+ @IntRange(from = 1) int maxImages) {
return new ImageWriter(surface, maxImages, ImageFormat.UNKNOWN);
}
@@ -169,7 +173,8 @@
*
* @return a new ImageWriter instance.
*/
- public static ImageWriter newInstance(Surface surface, int maxImages, int format) {
+ public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
+ @IntRange(from = 1) int maxImages, @Format int format) {
if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
throw new IllegalArgumentException("Invalid format is specified: " + format);
}
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index cf5711d..a9e33fd 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -19,9 +19,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
-import android.hardware.cas.V1_1.ICas;
+import android.hardware.cas.V1_0.ICas;
+import android.hardware.cas.V1_0.IMediaCasService;
import android.hardware.cas.V1_1.ICasListener;
-import android.hardware.cas.V1_1.IMediaCasService;
import android.media.MediaCasException.*;
import android.os.Bundle;
import android.os.Handler;
@@ -99,23 +99,35 @@
public final class MediaCas implements AutoCloseable {
private static final String TAG = "MediaCas";
private ICas mICas;
+ private android.hardware.cas.V1_1.ICas mICasV11;
private EventListener mListener;
private HandlerThread mHandlerThread;
private EventHandler mEventHandler;
- private static final Singleton<IMediaCasService> gDefault =
- new Singleton<IMediaCasService>() {
+ private static final Singleton<IMediaCasService> sService = new Singleton<IMediaCasService>() {
@Override
protected IMediaCasService create() {
try {
- return IMediaCasService.getService(true /*wait*/);
- } catch (RemoteException e) {}
+ Log.d(TAG, "Tried to get cas@1.1 service");
+ android.hardware.cas.V1_1.IMediaCasService serviceV11 =
+ android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/);
+ if (serviceV11 != null) {
+ return serviceV11;
+ }
+ } catch (Exception eV1_1) {
+ try {
+ Log.d(TAG, "Tried to get cas@1.0 service");
+ return IMediaCasService.getService(true /*wait*/);
+ } catch (Exception eV1_0) {
+ Log.d(TAG, "Failed to get cas@1.0 service");
+ }
+ }
return null;
}
};
static IMediaCasService getService() {
- return gDefault.get();
+ return sService.get();
}
private void validateInternalStates() {
@@ -126,11 +138,12 @@
private void cleanupAndRethrowIllegalState() {
mICas = null;
+ mICasV11 = null;
throw new IllegalStateException();
}
- private class EventHandler extends Handler
- {
+ private class EventHandler extends Handler {
+
private static final int MSG_CAS_EVENT = 0;
private static final int MSG_CAS_SESSION_EVENT = 1;
private static final String SESSION_KEY = "sessionId";
@@ -164,7 +177,7 @@
}
@Override
public void onSessionEvent(@NonNull ArrayList<Byte> sessionId,
- int event, int arg, @Nullable ArrayList<Byte> data)
+ int event, int arg, @Nullable ArrayList<Byte> data)
throws RemoteException {
Message msg = mEventHandler.obtainMessage();
msg.what = EventHandler.MSG_CAS_SESSION_EVENT;
@@ -177,7 +190,6 @@
mEventHandler.sendMessage(msg);
}
};
-
/**
* Describe a CAS plugin with its CA_system_ID and string name.
*
@@ -338,9 +350,14 @@
throws MediaCasException {
validateInternalStates();
+ if (mICasV11 == null) {
+ Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
+ throw new UnsupportedCasException("Send Session Event is not supported");
+ }
+
try {
MediaCasException.throwExceptionIfNeeded(
- mICas.sendSessionEvent(mSessionId, event, arg, toByteArray(data)));
+ mICasV11.sendSessionEvent(mSessionId, event, arg, toByteArray(data)));
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
}
@@ -427,7 +444,16 @@
*/
public MediaCas(int CA_system_id) throws UnsupportedCasException {
try {
- mICas = getService().createPluginExt(CA_system_id, mBinder);
+ IMediaCasService service = getService();
+ android.hardware.cas.V1_1.IMediaCasService serviceV11 =
+ android.hardware.cas.V1_1.IMediaCasService.castFrom(service);
+ if (serviceV11 == null) {
+ Log.d(TAG, "Used cas@1_0 interface to create plugin");
+ mICas = service.createPlugin(CA_system_id, mBinder);
+ } else {
+ Log.d(TAG, "Used cas@1.1 interface to create plugin");
+ mICas = mICasV11 = serviceV11.createPluginExt(CA_system_id, mBinder);
+ }
} catch(Exception e) {
Log.e(TAG, "Failed to create plugin: " + e);
mICas = null;
@@ -528,7 +554,7 @@
}
}
- private class OpenSessionCallback implements ICas.openSessionCallback {
+ private class OpenSessionCallback implements android.hardware.cas.V1_1.ICas.openSessionCallback{
public Session mSession;
public int mStatus;
@Override
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 65f3294..49867ab 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
@@ -417,16 +418,12 @@
Log.e(TAG, "Cannot use unregistered AudioPolicy");
return false;
}
- if (mContext == null) {
- Log.e(TAG, "Cannot use AudioPolicy without context");
- return false;
- }
if (mRegistrationId == null) {
Log.e(TAG, "Cannot use unregistered AudioPolicy");
return false;
}
}
- if (!(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
+ if (!(PackageManager.PERMISSION_GRANTED == checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid "
+ Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING");
@@ -435,6 +432,23 @@
return true;
}
+ /**
+ * Returns {@link PackageManager#PERMISSION_GRANTED} if the caller has the given permission.
+ */
+ private @PackageManager.PermissionResult int checkCallingOrSelfPermission(String permission) {
+ if (mContext != null) {
+ return mContext.checkCallingOrSelfPermission(permission);
+ }
+ Slog.v(TAG, "Null context, checking permission via ActivityManager");
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
+ try {
+ return ActivityManager.getService().checkPermission(permission, pid, uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private void checkMixReadyToUse(AudioMix mix, boolean forTrack)
throws IllegalArgumentException{
if (mix == null) {
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index f725cac..a56fd31 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -18,8 +18,6 @@
import android.annotation.NonNull;
import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioPatch;
import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
index 40c7166..5828fbd 100644
--- a/media/java/android/media/session/ControllerLink.java
+++ b/media/java/android/media/session/ControllerLink.java
@@ -158,6 +158,18 @@
}
/**
+ * Gets the session info of the connected session.
+ */
+ @Nullable
+ Bundle getSessionInfo() {
+ try {
+ return mISessionController.getSessionInfo();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Gets the {@link PendingIntent} for launching UI of the connected session.
*/
@Nullable
@@ -666,6 +678,12 @@
return null;
}
+ /** Stub method for ISessionController.getSessionInfo */
+ @Nullable
+ public Bundle getSessionInfo() {
+ return null;
+ }
+
/** Stub method for ISessionController.getLaunchPendingIntent */
@Nullable
public PendingIntent getLaunchPendingIntent() {
@@ -856,6 +874,11 @@
}
@Override
+ public Bundle getSessionInfo() {
+ return mControllerStub.getSessionInfo();
+ }
+
+ @Override
public PendingIntent getLaunchPendingIntent() {
return mControllerStub.getLaunchPendingIntent();
}
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 3e7b4fb..298085f 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -44,6 +44,7 @@
void unregisterCallback(in ControllerCallbackLink cb);
String getPackageName();
String getTag();
+ Bundle getSessionInfo();
PendingIntent getLaunchPendingIntent();
long getFlags();
MediaController.PlaybackInfo getVolumeAttributes();
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 8143bfa..e85461f 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -35,7 +35,7 @@
*/
interface ISessionManager {
SessionLink createSession(String packageName, in SessionCallbackLink sessionCb, String tag,
- int userId);
+ in Bundle sessionInfo, int userId);
void notifySession2Created(in Session2Token sessionToken);
List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
List<Session2Token> getSession2Tokens(int userId);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 9e4199c..fb21f69 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -79,6 +79,7 @@
private boolean mCbRegistered = false;
private String mPackageName;
private String mTag;
+ private Bundle mSessionInfo;
private final TransportControls mTransportControls;
@@ -410,6 +411,23 @@
}
/**
+ * Gets the additional session information which was set when the session was created.
+ *
+ * @return The additional session information
+ */
+ @Nullable
+ public Bundle getSessionInfo() {
+ if (mSessionInfo == null) {
+ try {
+ mSessionInfo = mSessionBinder.getSessionInfo();
+ } catch (RuntimeException e) {
+ Log.d(TAG, "Dead object in getSessionInfo.", e);
+ }
+ }
+ return mSessionInfo;
+ }
+
+ /**
* Get the session's tag for debugging purposes.
*
* @return The session's tag.
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 8ab893b..9fdefa6 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -132,6 +132,27 @@
* @param tag A short name for debugging purposes.
*/
public MediaSession(@NonNull Context context, @NonNull String tag) {
+ this(context, tag, null);
+ }
+
+ /**
+ * Creates a new session. The session will automatically be registered with
+ * the system but will not be published until {@link #setActive(boolean)
+ * setActive(true)} is called. You must call {@link #release()} when
+ * finished with the session.
+ * <p>
+ * The {@code sessionInfo} can include additional unchanging information about this session.
+ * For example, it can include the version of the application, or the list of the custom
+ * commands that this session supports.
+ *
+ * @param context The context to use to create the session.
+ * @param tag A short name for debugging purposes.
+ * @param sessionInfo A bundle for additional information about this session.
+ * Controllers can get this information by calling
+ * {@link MediaController#getSessionInfo()}.
+ */
+ public MediaSession(@NonNull Context context, @NonNull String tag,
+ @Nullable Bundle sessionInfo) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null.");
}
@@ -142,7 +163,7 @@
.getSystemService(Context.MEDIA_SESSION_SERVICE);
try {
SessionCallbackLink cbLink = new SessionCallbackLink(context);
- SessionLink sessionLink = manager.createSession(cbLink, tag);
+ SessionLink sessionLink = manager.createSession(cbLink, tag, sessionInfo);
mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
mMaxBitmapSize = context.getResources().getDimensionPixelSize(
android.R.dimen.config_mediaMetadataBitmapMaxSize);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 46f6c71..fde4f88 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -28,6 +28,7 @@
import android.media.IRemoteVolumeController;
import android.media.MediaSession2;
import android.media.Session2Token;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -101,13 +102,15 @@
* Create a new session in the system and get the binder for it.
*
* @param tag A short name for debugging purposes.
+ * @param sessionInfo A bundle for additional information about this session.
* @return The binder object from the system
* @hide
*/
@NonNull
- public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag) {
+ public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag,
+ @Nullable Bundle sessionInfo) {
try {
- return mService.createSession(mContext.getPackageName(), cbStub, tag,
+ return mService.createSession(mContext.getPackageName(), cbStub, tag, sessionInfo,
UserHandle.myUserId());
} catch (RemoteException e) {
throw new RuntimeException(e);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index e8f188c..d22a298 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -109,7 +109,7 @@
public @interface VideoUnavailableReason {}
static final int VIDEO_UNAVAILABLE_REASON_START = 0;
- static final int VIDEO_UNAVAILABLE_REASON_END = 4;
+ static final int VIDEO_UNAVAILABLE_REASON_END = 5;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
@@ -140,7 +140,14 @@
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the current TV program is audio-only.
*/
- public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = VIDEO_UNAVAILABLE_REASON_END;
+ public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 4;
+ /**
+ * Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
+ * {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
+ * the source is not physically connected, for example the HDMI cable is not connected.
+ * @hide
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = VIDEO_UNAVAILABLE_REASON_END;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f865563..68f1e6f 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"আঁতৰোৱা এপ্সমূহ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"আঁতৰোৱা এপ্ আৰু ব্যৱহাৰকাৰীসমূহ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ছিষ্টেম আপডে’ট"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ইউএছবি টেডাৰিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টেডাৰিং"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index ef8dd3d..4f29131 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"সরানো অ্যাপ্লিকেশানগুলি"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"সরানো অ্যাপ্লিকেশানগুলি এবং ব্যবহারকারীগণ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"সিস্টেম আপডেট"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB টিথারিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"পোর্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টিথারিং"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 97b9036..36e04bb 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"દૂર કરેલી ઍપ્લિકેશનો"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"દૂર કરેલી ઍપ્લિકેશનો અને વપરાશકર્તાઓ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"સિસ્ટમ અપડેટ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ટિથરિંગ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હૉટસ્પૉટ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"બ્લૂટૂથ ટિથરિંગ"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6e37c9a..89d6361 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"אפליקציות שהוסרו"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"אפליקציות ומשתמשים שהוסרו"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"עדכוני מערכת"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"שיתוף אינטרנט דרך USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"נקודה לשיתוף אינטרנט"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"שיתוף אינטרנט דרך Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 41b0fbd..1e9a0d5 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ತೆಗೆದುಹಾಕಲಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ಸಿಸ್ಟಂ ಅಪ್ಡೇಟ್ಗಳು"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ಟೆಥರಿಂಗ್"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ಪೋರ್ಟಬಲ್ ಹಾಟ್ಸ್ಪಾಟ್"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ಬ್ಲೂಟೂತ್ ಟೆಥರಿಂಗ್"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0292cab..ae97fb2 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"നീക്കംചെയ്ത അപ്ലിക്കേഷനുകൾ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"നീക്കംചെയ്ത അപ്ലിക്കേഷനുകളും ഉപയോക്താക്കളും"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"സിസ്റ്റം അപ്ഡേറ്റുകൾ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ടെതറിംഗ്"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"പോർട്ടബിൾ ഹോട്ട്സ്പോട്ട്"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ബ്ലൂടൂത്ത് ടെതറിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0c2f0ee..88de8f4 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"काढलेले अॅप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"काढलेले अॅप्स आणि वापरकर्ते"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"सिस्टम अपडेट"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 7daf956..ac15f1b 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"एन्ड्रोइड OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"हटाइएका अनुप्रयोगहरू"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"अनुप्रयोगहरू र प्रयोगकर्ताहरू हटाइयो।"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"प्रणालीसम्बन्धी अद्यावधिकहरू"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेथर गर्दै"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हटस्पट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लुटुथ टेथर गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 54ddf84..847586e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"କଢ଼ାଯାଇଥିବା ଆପ୍ଗୁଡ଼ିକ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ଆପ୍ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ସିଷ୍ଟମ୍ ଅପ୍ଡେଟ୍"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ଟିଥରିଙ୍ଗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ପୋର୍ଟବଲ୍ ହଟସ୍ପଟ୍"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ବ୍ଲୁଟୂଥ ଟିଥରିଙ୍ଗ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index dcf3e3c..0675b6b 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ਹਟਾਏ ਗਏ ਐਪਸ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ਹਟਾਏ ਗਏ ਐਪਸ ਅਤੇ ਉਪਭੋਗਤਾ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ਸਿਸਟਮ ਅੱਪਡੇਟ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ਟੈਦਰਿੰਗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ਪੋਰਟੇਬਲ ਹੌਟਸਪੌਟ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 71716ce..3cf43c8 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட பயன்பாடுகள்"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட பயன்பாடுகள் மற்றும் பயனர்கள்"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"சிஸ்டம் புதுப்பிப்புகள்"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB டெதெரிங்"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"போர்ட்டபிள் ஹாட்ஸ்பாட்"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"புளூடூத் டெதெரிங்"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 65ed110..c223629 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ہٹائی گئی ایپس"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ہٹائی گئی ایپس اور صارفین"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"سسٹم اپ ڈیٹس"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ٹیدرنگ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"پورٹیبل ہاٹ اسپاٹ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"بلوٹوتھ ٹیدرنگ"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4f18d45..402ce90 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -420,14 +420,20 @@
private class ClassChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
- mDeviceManager.onBtClassChanged(device);
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.refresh();
+ }
}
}
private class UuidChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
- mDeviceManager.onUuidChanged(device);
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.onUuidChanged();
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 5b4a8b4f..33e7540 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -206,20 +206,6 @@
}
}
- public synchronized void onBtClassChanged(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
- cachedDevice.dispatchAttributesChanged();
- }
- }
-
- public synchronized void onUuidChanged(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
- cachedDevice.onUuidChanged();
- }
- }
-
public synchronized void onBluetoothStateChanged(int bluetoothState) {
// When Bluetooth is turning off, we need to clear the non-bonded devices
// Otherwise, they end up showing up on the next BT enable
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 43b2894..dc47de8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -369,21 +369,6 @@
}
/**
- * Test to verify onBtClassChanged().
- */
- @Test
- public void onBtClassChanged_validBtClass_classChanged() {
- CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
- assertThat(cachedDevice1).isNotNull();
- assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
-
- final BluetoothClass newBluetoothClass = DEVICE_CLASS_2;
- when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass);
- mCachedDeviceManager.onBtClassChanged(mDevice1);
- assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass);
- }
-
- /**
* Test to verify onDeviceDisappeared().
*/
@Test
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 81b304d..0f8fd92 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1353,11 +1353,11 @@
Settings.Global.SHOW_TEMPERATURE_WARNING,
GlobalSettingsProto.TemperatureWarning.SHOW_TEMPERATURE_WARNING);
dumpSetting(s, p,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ GlobalSettingsProto.TemperatureWarning.SHOW_USB_TEMPERATURE_ALARM);
+ dumpSetting(s, p,
Settings.Global.WARNING_TEMPERATURE,
GlobalSettingsProto.TemperatureWarning.WARNING_TEMPERATURE_LEVEL);
- dumpSetting(s, p,
- Settings.Global.USB_ALARM_TEMPERATURE,
- GlobalSettingsProto.TemperatureWarning.USB_ALARM_TEMPERATURE_LEVEL);
p.end(tempWarningToken);
final long tetherToken = p.start(GlobalSettingsProto.TETHER);
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
deleted file mode 100644
index 78304fd..0000000
--- a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <FrameLayout
- android:id="@+id/nav_buttons"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/ends_group"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:clipChildren="false" />
-
- <LinearLayout
- android:id="@+id/center_group"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="horizontal"
- android:clipChildren="false" />
-
- </FrameLayout>
-
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/bubble_expanded_view.xml b/packages/SystemUI/res/layout/bubble_expanded_view.xml
index f664c05..a8b1b2e 100644
--- a/packages/SystemUI/res/layout/bubble_expanded_view.xml
+++ b/packages/SystemUI/res/layout/bubble_expanded_view.xml
@@ -39,26 +39,13 @@
android:layout_height="@dimen/bubble_expanded_header_height"
android:layout_width="match_parent"
android:animateLayoutChanges="true"
+ android:gravity="end|center_vertical"
android:orientation="horizontal">
- <TextView
- android:id="@+id/header_text"
- android:textAppearance="@*android:style/TextAppearance.Material.Title"
- android:textSize="18sp"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="start|center_vertical"
- android:singleLine="true"
- android:paddingLeft="@dimen/bubble_expanded_header_horizontal_padding"
- android:paddingRight="@dimen/bubble_expanded_header_horizontal_padding"
- />
-
<ImageButton
android:id="@+id/deep_link_button"
android:layout_width="@dimen/bubble_header_icon_size"
android:layout_height="@dimen/bubble_header_icon_size"
- android:gravity="end|center_vertical"
android:src="@drawable/ic_open_in_new"
android:scaleType="center"
android:tint="?android:attr/colorForeground"
@@ -70,7 +57,6 @@
android:layout_width="@dimen/bubble_header_icon_size"
android:layout_height="@dimen/bubble_header_icon_size"
android:src="@drawable/ic_settings"
- android:gravity="end|center_vertical"
android:scaleType="center"
android:tint="?android:attr/colorForeground"
android:background="?android:attr/selectableItemBackground"
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
index b237633..133b215 100644
--- a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
+++ b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
@@ -20,8 +20,8 @@
android:layout_width="match_parent"
android:layout_height="@dimen/navigation_bar_size">
- <include android:id="@+id/rot0" layout="@layout/navigation_layout" />
+ <include android:id="@+id/horizontal" layout="@layout/navigation_layout" />
- <include android:id="@+id/rot90" layout="@layout/navigation_layout_rot90" />
+ <include android:id="@+id/vertical" layout="@layout/navigation_layout_vertical" />
</com.android.systemui.tuner.PreviewNavInflater>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index d72021e..db1c79d 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -22,7 +22,8 @@
android:layout_marginStart="@dimen/rounded_corner_content_padding"
android:layout_marginEnd="@dimen/rounded_corner_content_padding"
android:paddingStart="@dimen/nav_content_padding"
- android:paddingEnd="@dimen/nav_content_padding">
+ android:paddingEnd="@dimen/nav_content_padding"
+ android:id="@+id/horizontal">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
similarity index 95%
rename from packages/SystemUI/res/layout/navigation_layout_rot90.xml
rename to packages/SystemUI/res/layout/navigation_layout_vertical.xml
index 24a0c71..285c5c4 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
@@ -22,7 +22,8 @@
android:layout_marginTop="@dimen/rounded_corner_content_padding"
android:layout_marginBottom="@dimen/rounded_corner_content_padding"
android:paddingTop="@dimen/nav_content_padding"
- android:paddingBottom="@dimen/nav_content_padding">
+ android:paddingBottom="@dimen/nav_content_padding"
+ android:id="@+id/vertical">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4396a42..b4dc0eff 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -329,16 +329,11 @@
<bool name="quick_settings_show_full_alarm">false</bool>
- <!-- Whether to show a warning notification when the device reaches a certain temperature. -->
+ <!-- Whether to show a warning notification when device's skin temperature is high. -->
<integer name="config_showTemperatureWarning">0</integer>
- <!-- Temp at which to show a warning notification if config_showTemperatureWarning is true.
- If < 0, uses the skin temperature sensor shutdown value from
- HardwarePropertiesManager#getDeviceTemperatures - config_warningTemperatureTolerance. -->
- <integer name="config_warningTemperature">-1</integer>
-
- <!-- Fudge factor for how much below the shutdown temp to show the warning. -->
- <integer name="config_warningTemperatureTolerance">2</integer>
+ <!-- Whether to show a alarm dialog when device's usb port is overheating. -->
+ <integer name="config_showUsbPortAlarm">0</integer>
<!-- Accessibility actions -->
<item type="id" name="action_split_task_to_left" />
@@ -485,4 +480,5 @@
</string-array>
<integer name="ongoing_appops_dialog_max_apps">5</integer>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 371a060..1f6e3c2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1012,7 +1012,7 @@
<!-- How much to inset the icon in the circle -->
<dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
- <dimen name="bubble_expanded_view_padding">8dp</dimen>
+ <dimen name="bubble_expanded_view_padding">4dp</dimen>
<!-- Default (and minimum) height of the expanded view shown when the bubble is expanded -->
<dimen name="bubble_expanded_default_height">180dp</dimen>
<!-- Height of the triangle that points to the expanded bubble -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0fde2de..4905e57 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2118,6 +2118,14 @@
<string name="high_temp_notif_message">Some features limited while phone cools down</string>
<!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
<string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
+ <!-- Title for alarm dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=30] -->
+ <string name="high_temp_alarm_title">Unplug charger</string>
+ <!-- Text body for dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_notify_message">There\u2019s an issue charging this device. Unplug the power adapter, and take care as the cable may be warm.</string>
+ <!-- Text for See care steps button [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_help_care_steps">See care steps</string>
+ <!-- Text link directs to usb overheat help page. -->
+ <string name="high_temp_alarm_help_url" translatable="false">help_uri_usb_warm</string>
<!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_shortcut_left">Left shortcut</string>
@@ -2378,5 +2386,4 @@
<string name="no_bubbles">Block</string>
<!-- Text used for button allowing user to approve / enable bubbles [CHAR LIMIT=20] -->
<string name="yes_bubbles">Allow</string>
-
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java
new file mode 100644
index 0000000..3ae2df5b
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 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.shared.system;
+
+import android.content.pm.ParceledListSlice;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * PinnedStackListener that simply forwards all calls to each listener added via
+ * {@link #addListener}. This is necessary since calling
+ * {@link com.android.server.wm.WindowManagerService#registerPinnedStackListener} replaces any
+ * previously set listener.
+ */
+public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub {
+ private List<IPinnedStackListener> mListeners = new ArrayList<>();
+
+ /** Adds a listener to receive updates from the WindowManagerService. */
+ public void addListener(IPinnedStackListener listener) {
+ mListeners.add(listener);
+ }
+
+ /** Removes a listener so it will no longer receive updates from the WindowManagerService. */
+ public void removeListener(IPinnedStackListener listener) {
+ mListeners.remove(listener);
+ }
+
+ @Override
+ public void onListenerRegistered(IPinnedStackController controller) throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onListenerRegistered(controller);
+ }
+ }
+
+ @Override
+ public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
+ boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation)
+ throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onMovementBoundsChanged(
+ insetBounds, normalBounds, animatingBounds,
+ fromImeAdjustment, fromShelfAdjustment, displayRotation);
+ }
+ }
+
+ @Override
+ public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onImeVisibilityChanged(imeVisible, imeHeight);
+ }
+ }
+
+ @Override
+ public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight)
+ throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onShelfVisibilityChanged(shelfVisible, shelfHeight);
+ }
+ }
+
+ @Override
+ public void onMinimizedStateChanged(boolean isMinimized) throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onMinimizedStateChanged(isMinimized);
+ }
+ }
+
+ @Override
+ public void onActionsChanged(ParceledListSlice actions) throws RemoteException {
+ for (IPinnedStackListener listener : mListeners) {
+ listener.onActionsChanged(actions);
+ }
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index f9aa8da..3d2f61e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.shared.system;
-import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.os.UserHandle;
import android.util.Log;
@@ -43,10 +43,20 @@
public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
public void onActivityDismissingDockedStack() { }
public void onActivityLaunchOnSecondaryDisplayFailed() { }
+
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
+ onActivityLaunchOnSecondaryDisplayFailed();
+ }
+
public void onTaskProfileLocked(int taskId, int userId) { }
public void onTaskCreated(int taskId, ComponentName componentName) { }
public void onTaskRemoved(int taskId) { }
public void onTaskMovedToFront(int taskId) { }
+
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ onTaskMovedToFront(taskInfo.taskId);
+ }
+
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 628b3c6..a9ac42f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -16,8 +16,9 @@
package com.android.systemui.shared.system;
-import android.app.ActivityTaskManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.app.TaskStackListener;
import android.content.ComponentName;
@@ -132,8 +133,11 @@
}
@Override
- public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
- mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo,
+ int requestedDisplayId) throws RemoteException {
+ mHandler.obtainMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED, requestedDisplayId,
+ 0 /* unused */,
+ taskInfo).sendToTarget();
}
@Override
@@ -157,8 +161,9 @@
}
@Override
- public void onTaskMovedToFront(int taskId) throws RemoteException {
- mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskId, 0).sendToTarget();
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo)
+ throws RemoteException {
+ mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget();
}
@Override
@@ -258,8 +263,10 @@
break;
}
case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
+ final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
+ mTaskStackListeners.get(i)
+ .onActivityLaunchOnSecondaryDisplayFailed(info);
}
break;
}
@@ -283,15 +290,16 @@
break;
}
case ON_TASK_MOVED_TO_FRONT: {
+ final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskMovedToFront(msg.arg1);
+ mTaskStackListeners.get(i).onTaskMovedToFront(info);
}
break;
}
case ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityRequestedOrientationChanged(
- msg.arg1, msg.arg2);
+ mTaskStackListeners.get(i)
+ .onActivityRequestedOrientationChanged(msg.arg1, msg.arg2);
}
break;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 8a251ae..10996e88 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -27,6 +27,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
+import android.view.IPinnedStackListener;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -81,6 +82,13 @@
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
+ /**
+ * Forwarder to which we can add multiple pinned stack listeners. Each listener will receive
+ * updates from the window manager service.
+ */
+ private PinnedStackListenerForwarder mPinnedStackListenerForwarder =
+ new PinnedStackListenerForwarder();
+
public static WindowManagerWrapper getInstance() {
return sInstance;
}
@@ -199,4 +207,14 @@
Log.w(TAG, "Failed to register docked stack listener");
}
}
+
+ /**
+ * Adds a pinned stack listener, which will receive updates from the window manager service
+ * along with any other pinned stack listeners that were added via this method.
+ */
+ public void addPinnedStackListener(IPinnedStackListener listener) throws RemoteException {
+ mPinnedStackListenerForwarder.addListener(listener);
+ WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
+ DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index c5dc324..3827e44 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -34,6 +34,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
@@ -241,6 +242,7 @@
// Draw clock view hierarchy to canvas.
Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
+ dispatchVisibilityAggregated(clockView, true);
clockView.measure(MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY));
clockView.layout(0, 0, mWidth, mHeight);
@@ -250,6 +252,24 @@
return bitmap;
}
+ private void dispatchVisibilityAggregated(View view, boolean isVisible) {
+ // Similar to View.dispatchVisibilityAggregated implementation.
+ final boolean thisVisible = view.getVisibility() == View.VISIBLE;
+ if (thisVisible || !isVisible) {
+ view.onVisibilityAggregated(isVisible);
+ }
+
+ if (view instanceof ViewGroup) {
+ isVisible = thisVisible && isVisible;
+ ViewGroup vg = (ViewGroup) view;
+ int count = vg.getChildCount();
+
+ for (int i = 0; i < count; i++) {
+ dispatchVisibilityAggregated(vg.getChildAt(i), isVisible);
+ }
+ }
+ }
+
private void notifyClockChanged(ClockPlugin plugin) {
for (int i = 0; i < mListeners.size(); i++) {
// It probably doesn't make sense to supply the same plugin instances to multiple
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 9efa656..60e6083 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -474,8 +474,6 @@
if (anim == null) {
return;
}
- int duration = SNAP_ANIM_LEN;
- anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
boolean wasCancelled = false;
@@ -495,6 +493,9 @@
});
prepareSnapBackAnimation(animView, anim);
mSnappingChild = true;
+ float maxDistance = Math.abs(targetLeft - getTranslation(animView));
+ mFlingAnimationUtils.apply(anim, getTranslation(animView), targetLeft, velocity,
+ maxDistance);
anim.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 0832296..4eea9f8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -25,17 +25,21 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.INotificationManager;
import android.app.Notification;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.view.Display;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -48,6 +52,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -172,6 +177,12 @@
mTaskStackListener = new BubbleTaskStackListener();
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+ try {
+ WindowManagerWrapper.getInstance().addPinnedStackListener(new BubblesImeListener());
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+
mBubbleData = data;
}
@@ -491,15 +502,8 @@
}
@Override
- public void onTaskMovedToFront(int taskId) {
- ActivityManager.StackInfo stackInfo = null;
- try {
- stackInfo = findStackInfo(taskId);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- if (stackInfo != null && stackInfo.displayId == Display.DEFAULT_DISPLAY
- && mStackView != null) {
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
mStackView.collapseStack();
}
}
@@ -510,9 +514,9 @@
* ultimately ended up, displays an error message toast, and calls this method instead of
* onTaskMovedToFront.
*/
- // TODO(b/124058588): add requestedDisplayId to this callback, ignore unless matches
@Override
- public void onActivityLaunchOnSecondaryDisplayFailed() {
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
+ // TODO(b/124058588): move to ActivityView.StateCallback, filter on virtualDisplay ID
if (mStackView != null) {
mStackView.collapseStack();
}
@@ -543,4 +547,37 @@
return Settings.Secure.getInt(context.getContentResolver(),
ENABLE_BUBBLES, 1) != 0;
}
+
+ /** PinnedStackListener that dispatches IME visibility updates to the stack. */
+ private class BubblesImeListener extends IPinnedStackListener.Stub {
+
+ @Override
+ public void onListenerRegistered(IPinnedStackController controller) throws RemoteException {
+ }
+
+ @Override
+ public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+ Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+ int displayRotation) throws RemoteException {}
+
+ @Override
+ public void onImeVisibilityChanged(boolean imeVisible, int imeHeight)
+ throws RemoteException {
+ if (mStackView != null) {
+ mStackView.post(() -> {
+ mStackView.onImeVisibilityChanged(imeVisible, imeHeight);
+ });
+ }
+ }
+
+ @Override
+ public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight)
+ throws RemoteException {}
+
+ @Override
+ public void onMinimizedStateChanged(boolean isMinimized) throws RemoteException {}
+
+ @Override
+ public void onActionsChanged(ParceledListSlice actions) throws RemoteException {}
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index c2327ad..7884800 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -75,7 +75,6 @@
// Header
private View mHeaderView;
- private TextView mHeaderTextView;
private ImageButton mDeepLinkIcon;
private ImageButton mSettingsIcon;
@@ -197,7 +196,6 @@
mHeaderHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_header_height);
mHeaderView = findViewById(R.id.header_layout);
- mHeaderTextView = findViewById(R.id.header_text);
mDeepLinkIcon = findViewById(R.id.deep_link_button);
mSettingsIcon = findViewById(R.id.settings_button);
mDeepLinkIcon.setOnClickListener(this);
@@ -295,13 +293,6 @@
R.string.bubbles_settings_button_description, mAppName));
mDeepLinkIcon.setContentDescription(getResources().getString(
R.string.bubbles_deep_link_button_description, mAppName));
- if (mEntry != null && mEntry.getBubbleMetadata() != null) {
- mHeaderTextView.setText(mEntry.getBubbleMetadata().getTitle());
- } else {
- // This should only happen if we're auto-bubbling notification content that isn't
- // explicitly a bubble
- mHeaderTextView.setText(mAppName);
- }
}
private void updatePermissionView() {
@@ -321,6 +312,8 @@
mPermissionView.setVisibility(VISIBLE);
((ImageView) mPermissionView.findViewById(R.id.pkgicon)).setImageDrawable(mAppIcon);
((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName);
+ logBubbleClickEvent(mEntry.notification,
+ StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 5546e4c..e20be8e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -100,6 +100,7 @@
private int mExpandedAnimateYDistance;
private int mStatusBarHeight;
private int mPipDismissHeight;
+ private int mImeOffset;
private Bubble mExpandedBubble;
private boolean mIsExpanded;
@@ -162,6 +163,7 @@
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mPipDismissHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.pip_dismiss_gradient_height);
+ mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
mDisplaySize = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -550,8 +552,15 @@
: null;
}
- public PointF getStackPosition() {
- return mStackAnimationController.getStackPosition();
+ /** Moves the bubbles out of the way if they're going to be over the keyboard. */
+ public void onImeVisibilityChanged(boolean visible, int height) {
+ if (!mIsExpanded) {
+ if (visible) {
+ mStackAnimationController.updateBoundsForVisibleImeAndAnimate(height + mImeOffset);
+ } else {
+ mStackAnimationController.updateBoundsForInvisibleImeAndAnimate();
+ }
+ }
}
/** Called when a drag operation on an individual bubble has started. */
@@ -786,7 +795,10 @@
* @return the index of the bubble view within the bubble stack. The range of the position
* is between 0 and the bubble count minus 1.
*/
- int getBubbleIndex(Bubble bubble) {
+ int getBubbleIndex(@Nullable Bubble bubble) {
+ if (bubble == null) {
+ return 0;
+ }
return mBubbleContainer.indexOfChild(bubble.iconView);
}
@@ -808,6 +820,10 @@
.floatValue();
}
+ public PointF getStackPosition() {
+ return mStackAnimationController.getStackPosition();
+ }
+
/**
* Logs the bubble UI event.
*
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 7dfb21c..f47fbe0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -66,6 +66,15 @@
*/
private PointF mStackPosition = new PointF();
+ /** The height of the most recently visible IME. */
+ private float mImeHeight = 0f;
+
+ /**
+ * The Y position of the stack before the IME became visible, or {@link Float#MIN_VALUE} if the
+ * IME is not visible or the user moved the stack since the IME became visible.
+ */
+ private float mPreImeY = Float.MIN_VALUE;
+
/**
* Animations on the stack position itself, which would have been started in
* {@link #flingThenSpringFirstBubbleWithStackFollowing}. These animations dispatch to
@@ -108,6 +117,10 @@
* it with the 'following' effect.
*/
public void moveFirstBubbleWithStackFollowing(float x, float y) {
+ // If we manually move the bubbles with the IME open, clear the return point since we don't
+ // want the stack to snap away from the new position.
+ mPreImeY = Float.MIN_VALUE;
+
moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_X, x);
moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_Y, y);
}
@@ -189,6 +202,44 @@
}
/**
+ * Save the IME height so that the allowable stack bounds reflect the now-visible IME, and
+ * animate the stack out of the way if necessary.
+ */
+ public void updateBoundsForVisibleImeAndAnimate(int imeHeight) {
+ mImeHeight = imeHeight;
+
+ final float maxBubbleY = getAllowableStackPositionRegion().bottom;
+ if (mStackPosition.y > maxBubbleY && mPreImeY == Float.MIN_VALUE) {
+ mPreImeY = mStackPosition.y;
+
+ springFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_Y,
+ getSpringForce(DynamicAnimation.TRANSLATION_Y, /* view */ null)
+ .setStiffness(SpringForce.STIFFNESS_LOW),
+ /* startVel */ 0f,
+ maxBubbleY);
+ }
+ }
+
+ /**
+ * Clear the IME height from the bounds and animate the stack back to its original position,
+ * assuming it wasn't moved in the meantime.
+ */
+ public void updateBoundsForInvisibleImeAndAnimate() {
+ mImeHeight = 0;
+
+ if (mPreImeY > Float.MIN_VALUE) {
+ springFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_Y,
+ getSpringForce(DynamicAnimation.TRANSLATION_Y, /* view */ null)
+ .setStiffness(SpringForce.STIFFNESS_LOW),
+ /* startVel */ 0f,
+ mPreImeY);
+ mPreImeY = Float.MIN_VALUE;
+ }
+ }
+
+ /**
* Returns the region within which the stack is allowed to rest. This goes slightly off the left
* and right sides of the screen, below the status bar/cutout and above the navigation bar.
* While the stack is not allowed to rest outside of these bounds, it can temporarily be
@@ -228,6 +279,7 @@
mLayout.getHeight()
- mIndividualBubbleSize
- mBubblePadding
+ - (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePadding : 0f)
- Math.max(
insets.getSystemWindowInsetBottom(),
insets.getDisplayCutout() != null
@@ -389,8 +441,8 @@
float vel, float finalPosition) {
Log.d(TAG, String.format("Springing %s to final position %f.",
- PhysicsAnimationLayout.getReadablePropertyName(property),
- finalPosition));
+ PhysicsAnimationLayout.getReadablePropertyName(property),
+ finalPosition));
StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
SpringAnimation springAnimation =
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 3346ad2..1740290 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,8 +16,6 @@
package com.android.systemui.pip.phone;
-import static android.view.Display.DEFAULT_DISPLAY;
-
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityManager;
@@ -33,8 +31,6 @@
import android.util.Pair;
import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
-import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
@@ -57,7 +53,6 @@
private Context mContext;
private IActivityManager mActivityManager;
private IActivityTaskManager mActivityTaskManager;
- private IWindowManager mWindowManager;
private Handler mHandler = new Handler();
private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
@@ -178,10 +173,9 @@
mContext = context;
mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
- mWindowManager = WindowManagerGlobal.getWindowManagerService();
try {
- mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener);
+ WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 50dda1c..fdb0b36 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -16,6 +16,7 @@
package com.android.systemui.power;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -41,6 +42,7 @@
import android.util.Log;
import android.util.Slog;
import android.view.View;
+import android.view.WindowManager;
import androidx.annotation.VisibleForTesting;
@@ -48,10 +50,13 @@
import com.android.settingslib.Utils;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.NotificationChannels;
+import com.android.systemui.volume.Events;
import java.io.PrintWriter;
import java.text.NumberFormat;
@@ -118,6 +123,7 @@
private final Context mContext;
private final NotificationManager mNoMan;
private final PowerManager mPowerMan;
+ private final KeyguardManager mKeyguard;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Receiver mReceiver = new Receiver();
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
@@ -141,6 +147,7 @@
private boolean mHighTempWarning;
private SystemUIDialog mHighTempDialog;
private SystemUIDialog mThermalShutdownDialog;
+ @VisibleForTesting SystemUIDialog mUsbHighTempDialog;
/**
*/
@@ -149,6 +156,7 @@
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mKeyguard = mContext.getSystemService(KeyguardManager.class);
mReceiver.init();
}
@@ -165,6 +173,8 @@
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
pw.print("mThermalShutdownDialog=");
pw.println(mThermalShutdownDialog != null ? "not null" : null);
+ pw.print("mUsbHighTempDialog=");
+ pw.println(mUsbHighTempDialog != null ? "not null" : null);
}
private int getLowBatteryAutoTriggerDefaultLevel() {
@@ -434,6 +444,53 @@
}
@Override
+ public void showUsbHighTemperatureAlarm() {
+ mHandler.post(() -> showUsbHighTemperatureAlarmInternal());
+ }
+
+ private void showUsbHighTemperatureAlarmInternal() {
+ if (mUsbHighTempDialog != null) {
+ return;
+ }
+
+ final SystemUIDialog d = new SystemUIDialog(mContext, R.style.Theme_SystemUI_Dialog_Alert);
+ d.setCancelable(false);
+ d.setIconAttribute(android.R.attr.alertDialogIcon);
+ d.setTitle(R.string.high_temp_alarm_title);
+ d.setShowForAllUsers(true);
+ d.setMessage(mContext.getString(R.string.high_temp_alarm_notify_message, ""));
+ d.setPositiveButton((com.android.internal.R.string.ok),
+ (dialogInterface, which) -> mUsbHighTempDialog = null);
+ d.setNegativeButton((R.string.high_temp_alarm_help_care_steps),
+ (dialogInterface, which) -> {
+ final String contextString = mContext.getString(
+ R.string.high_temp_alarm_help_url);
+ final Intent helpIntent = new Intent();
+ helpIntent.setClassName("com.android.settings",
+ "com.android.settings.HelpTrampoline");
+ helpIntent.putExtra(Intent.EXTRA_TEXT, contextString);
+ Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+ true /* dismissShade */, resultCode -> {
+ mUsbHighTempDialog = null;
+ });
+ });
+ d.setOnDismissListener(dialogInterface -> {
+ mUsbHighTempDialog = null;
+ Events.writeEvent(mContext, Events.EVENT_DISMISS_USB_OVERHEAT_ALARM,
+ Events.DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ });
+ d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ d.show();
+ mUsbHighTempDialog = d;
+
+ Events.writeEvent(mContext, Events.EVENT_SHOW_USB_OVERHEAT_ALARM,
+ Events.SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ }
+
+ @Override
public void updateLowBatteryWarning() {
updateNotification();
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index c43f572..e27c25e 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -27,7 +27,6 @@
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Handler;
-import android.os.HardwarePropertiesManager;
import android.os.IBinder;
import android.os.IThermalEventListener;
import android.os.IThermalService;
@@ -43,7 +42,6 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -71,7 +69,6 @@
final Receiver mReceiver = new Receiver();
private PowerManager mPowerManager;
- private HardwarePropertiesManager mHardwarePropertiesManager;
private WarningsUI mWarnings;
private final Configuration mLastConfiguration = new Configuration();
private long mTimeRemaining = Long.MAX_VALUE;
@@ -82,30 +79,21 @@
private boolean mLowWarningShownThisChargeCycle;
private boolean mSevereWarningShownThisChargeCycle;
private Future mLastShowWarningTask;
+ private boolean mEnableSkinTemperatureWarning;
+ private boolean mEnableUsbTemperatureAlarm;
private int mLowBatteryAlertCloseLevel;
private final int[] mLowBatteryReminderLevels = new int[2];
private long mScreenOffTime = -1;
- private float mThresholdTemp;
- private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
- private int mNumTemps;
- private long mNextLogTime;
@VisibleForTesting IThermalService mThermalService;
@VisibleForTesting int mBatteryLevel = 100;
@VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
- // by using the same instance (method references are not guaranteed to be the same object
- // We create a method reference here so that we are guaranteed that we can remove a callback
- // each time they are created).
- private final Runnable mUpdateTempCallback = this::updateTemperatureWarning;
-
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mHardwarePropertiesManager = (HardwarePropertiesManager)
- mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
mWarnings = Dependency.get(WarningsUI.class);
mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
@@ -128,7 +116,7 @@
// to the temperature being too high.
showThermalShutdownDialog();
- initTemperatureWarning();
+ initTemperature();
}
@Override
@@ -137,7 +125,7 @@
// Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
- mHandler.post(this::initTemperatureWarning);
+ mHandler.post(this::initTemperature);
}
}
@@ -383,30 +371,16 @@
return canShowWarning || canShowSevereWarning;
}
- private void initTemperatureWarning() {
+ private void initTemperature() {
ContentResolver resolver = mContext.getContentResolver();
Resources resources = mContext.getResources();
- if (Settings.Global.getInt(resolver, Settings.Global.SHOW_TEMPERATURE_WARNING,
- resources.getInteger(R.integer.config_showTemperatureWarning)) == 0) {
- return;
- }
- mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
- resources.getInteger(R.integer.config_warningTemperature));
-
- if (mThresholdTemp < 0f) {
- // Get the shutdown temperature, adjust for warning tolerance.
- float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
- if (throttlingTemps == null
- || throttlingTemps.length == 0
- || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
- return;
- }
- mThresholdTemp = throttlingTemps[0] -
- resources.getInteger(R.integer.config_warningTemperatureTolerance);
- }
+ mEnableSkinTemperatureWarning = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_TEMPERATURE_WARNING,
+ resources.getInteger(R.integer.config_showTemperatureWarning)) != 0;
+ mEnableUsbTemperatureAlarm = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ resources.getInteger(R.integer.config_showUsbPortAlarm)) != 0;
if (mThermalService == null) {
// Enable push notifications of throttling from vendor thermal
@@ -416,21 +390,27 @@
if (b != null) {
mThermalService = IThermalService.Stub.asInterface(b);
- try {
- mThermalService.registerThermalEventListenerWithType(
- new ThermalEventListener(), Temperature.TYPE_SKIN);
- } catch (RemoteException e) {
- // Should never happen.
- }
+ registerThermalEventListener();
} else {
Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
}
}
+ }
- setNextLogTime();
-
- // We have passed all of the checks, start checking the temp
- mHandler.post(mUpdateTempCallback);
+ @VisibleForTesting
+ void registerThermalEventListener() {
+ try {
+ if (mEnableSkinTemperatureWarning) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventSkinListener(), Temperature.TYPE_SKIN);
+ }
+ if (mEnableUsbTemperatureAlarm) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal callback.", e);
+ }
}
private void showThermalShutdownDialog() {
@@ -440,81 +420,6 @@
}
}
- @VisibleForTesting
- protected void updateTemperatureWarning() {
- float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_CURRENT);
- if (temps.length != 0) {
- float temp = temps[0];
- mRecentTemps[mNumTemps++] = temp;
-
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && !statusBar.isDeviceInVrMode()
- && temp >= mThresholdTemp) {
- logAtTemperatureThreshold(temp);
- mWarnings.showHighTemperatureWarning();
- } else {
- mWarnings.dismissHighTemperatureWarning();
- }
- }
-
- logTemperatureStats();
-
- // Remove any pending callbacks as we only want to enable one
- mHandler.removeCallbacks(mUpdateTempCallback);
- mHandler.postDelayed(mUpdateTempCallback, TEMPERATURE_INTERVAL);
- }
-
- private void logAtTemperatureThreshold(float temp) {
- StringBuilder sb = new StringBuilder();
- sb.append("currentTemp=").append(temp)
- .append(",thresholdTemp=").append(mThresholdTemp)
- .append(",batteryStatus=").append(mBatteryStatus)
- .append(",recentTemps=");
- for (int i = 0; i < mNumTemps; i++) {
- sb.append(mRecentTemps[i]).append(',');
- }
- Slog.i(TAG, sb.toString());
- }
-
- /**
- * Calculates and logs min, max, and average
- * {@link HardwarePropertiesManager#DEVICE_TEMPERATURE_SKIN} over the past
- * {@link #TEMPERATURE_LOGGING_INTERVAL}.
- */
- private void logTemperatureStats() {
- if (mNextLogTime > System.currentTimeMillis() && mNumTemps != MAX_RECENT_TEMPS) {
- return;
- }
-
- if (mNumTemps > 0) {
- float sum = mRecentTemps[0], min = mRecentTemps[0], max = mRecentTemps[0];
- for (int i = 1; i < mNumTemps; i++) {
- float temp = mRecentTemps[i];
- sum += temp;
- if (temp > max) {
- max = temp;
- }
- if (temp < min) {
- min = temp;
- }
- }
-
- float avg = sum / mNumTemps;
- Slog.i(TAG, "avg=" + avg + ",min=" + min + ",max=" + max);
- MetricsLogger.histogram(mContext, "device_skin_temp_avg", (int) avg);
- MetricsLogger.histogram(mContext, "device_skin_temp_min", (int) min);
- MetricsLogger.histogram(mContext, "device_skin_temp_max", (int) max);
- }
- setNextLogTime();
- mNumTemps = 0;
- }
-
- private void setNextLogTime() {
- mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL;
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
@@ -541,34 +446,80 @@
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- pw.print("mThresholdTemp=");
- pw.println(Float.toString(mThresholdTemp));
- pw.print("mNextLogTime=");
- pw.println(Long.toString(mNextLogTime));
+ pw.print("mEnableSkinTemperatureWarning=");
+ pw.println(mEnableSkinTemperatureWarning);
+ pw.print("mEnableUsbTemperatureAlarm=");
+ pw.println(mEnableUsbTemperatureAlarm);
mWarnings.dump(pw);
}
public interface WarningsUI {
void update(int batteryLevel, int bucket, long screenOffTime);
+
void updateEstimate(Estimate estimate);
+
void updateThresholds(long lowThreshold, long severeThreshold);
+
void dismissLowBatteryWarning();
+
void showLowBatteryWarning(boolean playSound);
+
void dismissInvalidChargerWarning();
+
void showInvalidChargerWarning();
+
void updateLowBatteryWarning();
+
boolean isInvalidChargerWarningShowing();
+
void dismissHighTemperatureWarning();
+
void showHighTemperatureWarning();
+
+ /**
+ * Display USB overheat alarm
+ */
+ void showUsbHighTemperatureAlarm();
+
void showThermalShutdownWarning();
+
void dump(PrintWriter pw);
+
void userSwitched();
}
- // Thermal event received from vendor thermal management subsystem
- private final class ThermalEventListener extends IThermalEventListener.Stub {
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventSkinListener extends IThermalEventListener.Stub {
@Override public void notifyThrottling(Temperature temp) {
- mHandler.post(mUpdateTempCallback);
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && !statusBar.isDeviceInVrMode()) {
+ mWarnings.showHighTemperatureWarning();
+ Slog.d(TAG, "ThermalEventSkinListener: notifyThrottling was called "
+ + ", current skin status = " + status
+ + ", temperature = " + temp.getValue());
+ }
+ } else {
+ mWarnings.dismissHighTemperatureWarning();
+ }
+ }
+ }
+
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventUsbListener extends IThermalEventListener.Stub {
+ @Override public void notifyThrottling(Temperature temp) {
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ mWarnings.showUsbHighTemperatureAlarm();
+ Slog.d(TAG, "ThermalEventUsbListener: notifyThrottling was called "
+ + ", current usb port status = " + status
+ + ", temperature = " + temp.getValue());
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
index cf3f89e..409d60f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -135,7 +135,7 @@
final Bitmap hardBitmap = SurfaceControl
.screenshot(new Rect(), mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
mNavigationBarView.getContext().getDisplay().getRotation());
- if (cropRect.bottom <= hardBitmap.getHeight()
+ if (hardBitmap != null && cropRect.bottom <= hardBitmap.getHeight()
&& cropRect.left + cropRect.width() <= hardBitmap.getWidth()) {
final Bitmap cropBitmap = Bitmap.createBitmap(hardBitmap, cropRect.left, cropRect.top,
cropRect.width(), cropRect.height());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index 64209a7..fcf5893 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -103,7 +103,7 @@
public static NavigationBarEdgePanel create(@NonNull Context context, int width, int height,
int gravity) {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index c9fa89e..faa2ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -23,18 +23,15 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
-import android.view.Display;
-import android.view.Display.Mode;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
@@ -84,21 +81,21 @@
private static final String WEIGHT_CENTERED_SUFFIX = "WC";
private final List<NavBarButtonProvider> mPlugins = new ArrayList<>();
- private final Display mDisplay;
protected LayoutInflater mLayoutInflater;
protected LayoutInflater mLandscapeInflater;
- protected FrameLayout mRot0;
- protected FrameLayout mRot90;
- private boolean isRot0Landscape;
+ protected FrameLayout mHorizontal;
+ protected FrameLayout mVertical;
- private SparseArray<ButtonDispatcher> mButtonDispatchers;
+ @VisibleForTesting
+ SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
private View mLastPortrait;
private View mLastLandscape;
+ private boolean mIsVertical;
private boolean mAlternativeOrder;
private boolean mUsingCustomLayout;
@@ -107,14 +104,11 @@
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
createInflaters();
- mDisplay = ((WindowManager)
- context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- Mode displayMode = mDisplay.getMode();
- isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
}
- private void createInflaters() {
+ @VisibleForTesting
+ void createInflaters() {
mLayoutInflater = LayoutInflater.from(mContext);
Configuration landscape = new Configuration();
landscape.setTo(mContext.getResources().getConfiguration());
@@ -132,13 +126,12 @@
private void inflateChildren() {
removeAllViews();
- mRot0 = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout, this, false);
- mRot0.setId(R.id.rot0);
- addView(mRot0);
- mRot90 = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_rot90, this,
- false);
- mRot90.setId(R.id.rot90);
- addView(mRot90);
+ mHorizontal = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout,
+ this /* root */, false /* attachToRoot */);
+ addView(mHorizontal);
+ mVertical = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_vertical,
+ this /* root */, false /* attachToRoot */);
+ addView(mVertical);
updateAlternativeOrder();
}
@@ -198,12 +191,9 @@
}
}
- public void updateButtonDispatchersCurrentView() {
+ void updateButtonDispatchersCurrentView() {
if (mButtonDispatchers != null) {
- final int rotation = mDisplay.getRotation();
- final boolean portrait = rotation == Surface.ROTATION_0
- || rotation == Surface.ROTATION_180;
- final View view = portrait ? mRot0 : mRot90;
+ View view = mIsVertical ? mVertical : mHorizontal;
for (int i = 0; i < mButtonDispatchers.size(); i++) {
final ButtonDispatcher dispatcher = mButtonDispatchers.valueAt(i);
dispatcher.setCurrentView(view);
@@ -211,7 +201,13 @@
}
}
- public void setAlternativeOrder(boolean alternativeOrder) {
+ void setVertical(boolean vertical) {
+ if (vertical != mIsVertical) {
+ mIsVertical = vertical;
+ }
+ }
+
+ void setAlternativeOrder(boolean alternativeOrder) {
if (alternativeOrder != mAlternativeOrder) {
mAlternativeOrder = alternativeOrder;
updateAlternativeOrder();
@@ -219,10 +215,10 @@
}
private void updateAlternativeOrder() {
- updateAlternativeOrder(mRot0.findViewById(R.id.ends_group));
- updateAlternativeOrder(mRot0.findViewById(R.id.center_group));
- updateAlternativeOrder(mRot90.findViewById(R.id.ends_group));
- updateAlternativeOrder(mRot90.findViewById(R.id.center_group));
+ updateAlternativeOrder(mHorizontal.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mHorizontal.findViewById(R.id.center_group));
+ updateAlternativeOrder(mVertical.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mVertical.findViewById(R.id.center_group));
}
private void updateAlternativeOrder(View v) {
@@ -232,10 +228,10 @@
}
private void initiallyFill(ButtonDispatcher buttonDispatcher) {
- addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.ends_group));
- addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.center_group));
- addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.ends_group));
- addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, mHorizontal.findViewById(R.id.ends_group));
+ addAll(buttonDispatcher, mHorizontal.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, mVertical.findViewById(R.id.ends_group));
+ addAll(buttonDispatcher, mVertical.findViewById(R.id.center_group));
}
private void addAll(ButtonDispatcher buttonDispatcher, ViewGroup parent) {
@@ -267,17 +263,23 @@
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
// Inflate these in start to end order or accessibility traversal will be messed up.
- inflateButtons(start, mRot0.findViewById(R.id.ends_group), isRot0Landscape, true);
- inflateButtons(start, mRot90.findViewById(R.id.ends_group), !isRot0Landscape, true);
+ inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),
+ false /* landscape */, true /* start */);
+ inflateButtons(start, mVertical.findViewById(R.id.ends_group),
+ true /* landscape */, true /* start */);
- inflateButtons(center, mRot0.findViewById(R.id.center_group), isRot0Landscape, false);
- inflateButtons(center, mRot90.findViewById(R.id.center_group), !isRot0Landscape, false);
+ inflateButtons(center, mHorizontal.findViewById(R.id.center_group),
+ false /* landscape */, false /* start */);
+ inflateButtons(center, mVertical.findViewById(R.id.center_group),
+ true /* landscape */, false /* start */);
- addGravitySpacer(mRot0.findViewById(R.id.ends_group));
- addGravitySpacer(mRot90.findViewById(R.id.ends_group));
+ addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));
+ addGravitySpacer(mVertical.findViewById(R.id.ends_group));
- inflateButtons(end, mRot0.findViewById(R.id.ends_group), isRot0Landscape, false);
- inflateButtons(end, mRot90.findViewById(R.id.ends_group), !isRot0Landscape, false);
+ inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),
+ false /* landscape */, false /* start */);
+ inflateButtons(end, mVertical.findViewById(R.id.ends_group),
+ true /* landscape */, false /* start */);
updateButtonDispatchersCurrentView();
}
@@ -472,8 +474,8 @@
mButtonDispatchers.valueAt(i).clear();
}
}
- clearAllChildren(mRot0.findViewById(R.id.nav_buttons));
- clearAllChildren(mRot90.findViewById(R.id.nav_buttons));
+ clearAllChildren(mHorizontal.findViewById(R.id.nav_buttons));
+ clearAllChildren(mVertical.findViewById(R.id.nav_buttons));
}
private void clearAllChildren(ViewGroup group) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d6d3d08..f82b05e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -116,9 +116,11 @@
final static boolean ALTERNATE_CAR_MODE_UI = false;
View mCurrentView = null;
- View[] mRotatedViews = new View[4];
+ private View mVertical;
+ private View mHorizontal;
- boolean mVertical;
+ /** Indicates that navigation bar is vertical. */
+ private boolean mIsVertical;
private int mCurrentRotation = -1;
boolean mLongClickableAccessibilityButton;
@@ -350,7 +352,7 @@
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
- mVertical = false;
+ mIsVertical = false;
mLongClickableAccessibilityButton = false;
// Set up the context group of buttons
@@ -471,7 +473,7 @@
public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
mOnVerticalChangedListener = onVerticalChangedListener;
- notifyVerticalChangedListener(mVertical);
+ notifyVerticalChangedListener(mIsVertical);
}
@Override
@@ -547,10 +549,6 @@
return mCurrentView;
}
- public View[] getAllViews() {
- return mRotatedViews;
- }
-
public ButtonDispatcher getRecentsButton() {
return mButtonDispatchers.get(R.id.recent_apps);
}
@@ -657,7 +655,7 @@
// Animate the back button's rotation to the new degrees and only in portrait move up the
// back button to line up with the other buttons
- float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mVertical && useAltBack
+ float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mIsVertical && useAltBack
? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
: 0;
ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
@@ -669,7 +667,7 @@
}
private void orientHomeButton(KeyButtonDrawable drawable) {
- drawable.setRotation(mVertical ? 90 : 0);
+ drawable.setRotation(mIsVertical ? 90 : 0);
}
private KeyButtonDrawable chooseNavigationIconDrawable(@DrawableRes int icon,
@@ -964,7 +962,7 @@
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
DockedStackExistsListener.register(mDockedListener);
- updateRotatedViews();
+ updateOrientationViews();
reloadNavIcons();
}
@@ -1028,34 +1026,35 @@
view.setTranslationY(posY);
}
- private void updateRotatedViews() {
- mRotatedViews[Surface.ROTATION_0] =
- mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
- mRotatedViews[Surface.ROTATION_270] =
- mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
+ private void updateOrientationViews() {
+ mHorizontal = findViewById(R.id.horizontal);
+ mVertical = findViewById(R.id.vertical);
updateCurrentView();
}
- public boolean needsReorient(int rotation) {
+ boolean needsReorient(int rotation) {
return mCurrentRotation != rotation;
}
private void updateCurrentView() {
- final int rot = getContextDisplay().getRotation();
- for (int i=0; i<4; i++) {
- mRotatedViews[i].setVisibility(View.GONE);
- }
- mCurrentView = mRotatedViews[rot];
+ resetViews();
+ mCurrentView = mIsVertical ? mVertical : mHorizontal;
mCurrentView.setVisibility(View.VISIBLE);
- mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
+ mNavigationInflaterView.setVertical(mIsVertical);
+ mCurrentRotation = getContextDisplay().getRotation();
+ mNavigationInflaterView.setAlternativeOrder(mCurrentRotation == Surface.ROTATION_90);
mNavigationInflaterView.updateButtonDispatchersCurrentView();
updateLayoutTransitionsEnabled();
- mCurrentRotation = rot;
+ }
+
+ private void resetViews() {
+ mHorizontal.setVisibility(View.GONE);
+ mVertical.setVisibility(View.GONE);
}
private void updateRecentsIcon() {
- mDockedIcon.setRotation(mDockedStackExists && mVertical ? 90 : 0);
+ mDockedIcon.setRotation(mDockedStackExists && mIsVertical ? 90 : 0);
getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
mBarTransitions.reapplyDarkIntensity();
}
@@ -1077,7 +1076,7 @@
}
public boolean isVertical() {
- return mVertical;
+ return mIsVertical;
}
public void reorient() {
@@ -1101,7 +1100,7 @@
updateTaskSwitchHelper();
updateNavButtonIcons();
- getHomeButton().setVertical(mVertical);
+ getHomeButton().setVertical(mIsVertical);
}
private void updateTaskSwitchHelper() {
@@ -1134,9 +1133,12 @@
"onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
final boolean newVertical = w > 0 && h > w;
- if (newVertical != mVertical) {
- mVertical = newVertical;
- //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
+ if (newVertical != mIsVertical) {
+ mIsVertical = newVertical;
+ if (DEBUG) {
+ Log.d(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w,
+ mIsVertical ? "y" : "n"));
+ }
reorient();
notifyVerticalChangedListener(newVertical);
}
@@ -1347,7 +1349,7 @@
pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s darkIntensity=%.2f",
mDisabledFlags,
- mVertical ? "true" : "false",
+ mIsVertical ? "true" : "false",
getMenuButton().isVisible() ? "true" : "false",
getLightTransitionsController().getCurrentDarkIntensity()));
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index ca55e1f..1596ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -53,6 +53,8 @@
public static final int EVENT_TOUCH_LEVEL_DONE = 16; // (stream|int) (level|bool)
public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
+ public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
+ public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
private static final String[] EVENT_TAGS = {
"show_dialog",
@@ -73,7 +75,9 @@
"mute_changed",
"touch_level_done",
"zen_mode_config_changed",
- "ringer_toggle"
+ "ringer_toggle",
+ "show_usb_overheat_alarm",
+ "dismiss_usb_overheat_alarm"
};
public static final int DISMISS_REASON_UNKNOWN = 0;
@@ -85,6 +89,7 @@
public static final int DISMISS_REASON_DONE_CLICKED = 6;
public static final int DISMISS_STREAM_GONE = 7;
public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
+ public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
public static final String[] DISMISS_REASONS = {
"unknown",
"touch_outside",
@@ -94,16 +99,19 @@
"settings_clicked",
"done_clicked",
"a11y_stream_changed",
- "output_chooser"
+ "output_chooser",
+ "usb_temperature_below_threshold"
};
public static final int SHOW_REASON_UNKNOWN = 0;
public static final int SHOW_REASON_VOLUME_CHANGED = 1;
public static final int SHOW_REASON_REMOTE_VOLUME_CHANGED = 2;
+ public static final int SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED = 3;
public static final String[] SHOW_REASONS = {
"unknown",
"volume_changed",
- "remote_volume_changed"
+ "remote_volume_changed",
+ "usb_temperature_above_threshold"
};
public static final int ICON_STATE_UNKNOWN = 0;
@@ -181,6 +189,19 @@
case EVENT_SUPPRESSOR_CHANGED:
sb.append(list[0]).append(' ').append(list[1]);
break;
+ case EVENT_SHOW_USB_OVERHEAT_ALARM:
+ MetricsLogger.visible(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "show_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
+ break;
+ case EVENT_DISMISS_USB_OVERHEAT_ALARM:
+ MetricsLogger.hidden(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "dismiss_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(DISMISS_REASONS[(Integer) list[0]])
+ .append(" keyguard=").append(list[1]);
+ break;
default:
sb.append(Arrays.asList(list));
break;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index c903ab5..617b191 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -587,8 +587,11 @@
mHandler.removeMessages(H.DISMISS);
mHandler.removeMessages(H.SHOW);
mDialogView.animate().cancel();
- mShowing = false;
-
+ if (mShowing) {
+ mShowing = false;
+ // Only logs when the volume dialog visibility is changed.
+ Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason);
+ }
mDialogView.setTranslationX(0);
mDialogView.setAlpha(1);
ViewPropertyAnimator animator = mDialogView.animate()
@@ -601,8 +604,6 @@
}, 50));
if (!isLandscape()) animator.translationX(mDialogView.getWidth() / 2);
animator.start();
-
- Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason);
mController.notifyVisible(false);
synchronized (mSafetyWarningLock) {
if (mSafetyWarning != null) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index bf6cc53..cd500b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -16,9 +16,8 @@
package com.android.systemui.power;
-import static android.test.MoreAsserts.assertNotEqual;
+import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -38,7 +37,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.NotificationChannels;
-import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -151,4 +149,13 @@
verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
eq(SystemMessage.NOTE_THERMAL_SHUTDOWN), any());
}
+
+ @Test
+ public void testShowUsbHighTemperatureAlarm() {
+ mPowerNotificationWarnings.showUsbHighTemperatureAlarm();
+ waitForIdleSync(mContext.getMainThreadHandler());
+ assertThat(mPowerNotificationWarnings.mUsbHighTempDialog).isNotNull();
+
+ mPowerNotificationWarnings.mUsbHighTempDialog.dismiss();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index c28e74e..0aed63d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -14,14 +14,14 @@
package com.android.systemui.power;
-import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_CURRENT;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_SHUTDOWN;
import static android.provider.Settings.Global.SHOW_TEMPERATURE_WARNING;
+import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -31,9 +31,10 @@
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
-import android.os.HardwarePropertiesManager;
+import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
+import android.os.Temperature;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -74,97 +75,104 @@
private static final int OLD_BATTERY_LEVEL_NINE = 9;
private static final int OLD_BATTERY_LEVEL_10 = 10;
private static final long VERY_BELOW_SEVERE_HYBRID_THRESHOLD = TimeUnit.MINUTES.toMillis(15);
- private HardwarePropertiesManager mHardProps;
private WarningsUI mMockWarnings;
private PowerUI mPowerUI;
private EnhancedEstimates mEnhancedEstimates;
@Mock private PowerManager mPowerManager;
@Mock private IThermalService mThermalServiceMock;
+ private IThermalEventListener mThermalEventUsbListener;
+ private IThermalEventListener mThermalEventSkinListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mMockWarnings = mDependency.injectMockDependency(WarningsUI.class);
mEnhancedEstimates = mDependency.injectMockDependency(EnhancedEstimates.class);
- mHardProps = mock(HardwarePropertiesManager.class);
mContext.putComponent(StatusBar.class, mock(StatusBar.class));
- mContext.addMockSystemService(Context.HARDWARE_PROPERTIES_SERVICE, mHardProps);
mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
createPowerUi();
+ mThermalEventSkinListener = mPowerUI.new ThermalEventSkinListener();
+ mThermalEventUsbListener = mPowerUI.new ThermalEventUsbListener();
}
@Test
- public void testNoConfig_NoWarnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
+ public void testSkinWarning_throttlingCritical() throws Exception {
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
- }
- @Test
- public void testConfig_NoWarnings() {
- setUnderThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1");
+ mThermalEventSkinListener.notifyThrottling(temp);
- mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
- }
-
- @Test
- public void testConfig_Warnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
- mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+ // dismiss skin high temperature warning when throttling status is critical
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mMockWarnings, never()).showHighTemperatureWarning();
+ verify(mMockWarnings, times(1)).dismissHighTemperatureWarning();
}
@Test
- public void testSettingOverrideConfig() {
- setOverThreshold();
+ public void testSkinWarning_throttlingEmergency() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_SKIN, "skin2");
+ mThermalEventSkinListener.notifyThrottling(temp);
+
+ // show skin high temperature warning when throttling status is emergency
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, times(1)).showHighTemperatureWarning();
+ verify(mMockWarnings, never()).dismissHighTemperatureWarning();
+ }
+
+ @Test
+ public void testUsbAlarm_throttlingCritical() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_USB_PORT, "usb1");
+ mThermalEventUsbListener.notifyThrottling(temp);
+
+ // not show usb high temperature alarm when throttling status is critical
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, never()).showUsbHighTemperatureAlarm();
+ }
+
+ @Test
+ public void testUsbAlarm_throttlingEmergency() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_USB_PORT, "usb2");
+ mThermalEventUsbListener.notifyThrottling(temp);
+
+ // show usb high temperature alarm when throttling status is emergency
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, times(1)).showUsbHighTemperatureAlarm();
+ }
+
+ @Test
+ public void testSettingOverrideConfig_enableSkinTemperatureWarning() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+ mPowerUI.registerThermalEventListener();
+
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
}
@Test
- public void testShutdownBasedThreshold() {
- int tolerance = 2;
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
+ public void testSettingOverrideConfig_enableUsbTemperatureAlarm() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, -1);
- resources.addOverride(R.integer.config_warningTemperatureTolerance, tolerance);
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_SHUTDOWN))
- .thenReturn(new float[] { 55 + tolerance });
+ resources.addOverride(R.integer.config_showUsbPortAlarm, 0);
- setCurrentTemp(54); // Below threshold.
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
+ mPowerUI.registerThermalEventListener();
- setCurrentTemp(56); // Above threshold.
- mPowerUI.updateTemperatureWarning();
- verify(mMockWarnings).showHighTemperatureWarning();
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -532,17 +540,14 @@
verify(mEnhancedEstimates, times(2)).getEstimate();
}
- private void setCurrentTemp(float temp) {
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT))
- .thenReturn(new float[] { temp });
+ private Temperature getEmergencyStatusTemp(int type, String name) {
+ final float value = 65;
+ return new Temperature(value, type, name, Temperature.THROTTLING_EMERGENCY);
}
- private void setOverThreshold() {
- setCurrentTemp(50000);
- }
-
- private void setUnderThreshold() {
- setCurrentTemp(5);
+ private Temperature getCriticalStatusTemp(int type, String name) {
+ final float value = 60;
+ return new Temperature(value, type, name, Temperature.THROTTLING_CRITICAL);
}
private void createPowerUi() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
new file mode 100644
index 0000000..093749a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** atest NavigationBarInflaterViewTest */
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class NavigationBarInflaterViewTest extends SysuiTestCase {
+
+ private NavigationBarInflaterView mNavBarInflaterView;
+
+ private static final int BUTTON_ID = 0;
+
+ @Before
+ public void setUp() {
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+
+ mNavBarInflaterView = spy(new NavigationBarInflaterView(mContext, null));
+ doNothing().when(mNavBarInflaterView).createInflaters();
+
+ mNavBarInflaterView.mButtonDispatchers = new SparseArray<>(1);
+ mNavBarInflaterView.mButtonDispatchers.put(BUTTON_ID, new ButtonDispatcher(BUTTON_ID));
+
+ initializeViews();
+ }
+
+ private void initializeViews() {
+ mNavBarInflaterView.mVertical = mock(FrameLayout.class);
+ mNavBarInflaterView.mHorizontal = mock(FrameLayout.class);
+ initializeLayout(mNavBarInflaterView.mVertical);
+ initializeLayout(mNavBarInflaterView.mHorizontal);
+ }
+
+ private void initializeLayout(FrameLayout layout) {
+ View verticalChildView = mock(View.class);
+ verticalChildView.setId(BUTTON_ID);
+ doReturn(layout).when(verticalChildView).getParent();
+ doReturn(verticalChildView).when(layout).findViewById(BUTTON_ID);
+ }
+
+ @After
+ public void tearDown() {
+ mNavBarInflaterView = null;
+ }
+
+ @Test
+ public void testUpdateButtonDispatchersCurrentView_isVerticalTrue() {
+ mNavBarInflaterView.setVertical(true);
+
+ mNavBarInflaterView.updateButtonDispatchersCurrentView();
+
+ ButtonDispatcher button = mNavBarInflaterView.mButtonDispatchers.get(BUTTON_ID);
+ assertEquals("Buttons need to be set to vertical layout",
+ mNavBarInflaterView.mVertical.getId(),
+ ((View) button.getCurrentView().getParent()).getId());
+ }
+
+ @Test
+ public void testUpdateButtonDispatchersCurrentView_isVerticalFalse() {
+ mNavBarInflaterView.setVertical(false);
+
+ mNavBarInflaterView.updateButtonDispatchersCurrentView();
+
+ ButtonDispatcher button = mNavBarInflaterView.mButtonDispatchers.get(BUTTON_ID);
+ assertEquals("Buttons need to be set to horizon layout",
+ mNavBarInflaterView.mHorizontal.getId(),
+ ((View) button.getCurrentView().getParent()).getId());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e4da859..f72d411 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -38,6 +38,7 @@
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -251,6 +252,7 @@
assertScrimTint(mScrimBehind, false /* tinted */);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void transitionToUnlocked() {
mScrimController.setPanelExpansion(0f);
@@ -295,6 +297,7 @@
Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void panelExpansion() {
mScrimController.setPanelExpansion(0f);
@@ -317,6 +320,7 @@
mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void panelExpansionAffectsAlpha() {
mScrimController.setPanelExpansion(0f);
diff --git a/proto/Android.bp b/proto/Android.bp
index 817a54d..7f826b3 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -6,6 +6,7 @@
},
srcs: ["src/**/*.proto"],
no_framework_libs: true,
+ sdk_version: "9",
// Pin java_version until jarjar is certified to support later versions. http://b/72703434
java_version: "1.8",
target: {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 530d115..33555c4 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -247,6 +247,12 @@
LOCATION_GONE = 6; // the view isn't laid out at all
}
+ // Subtypes for profile logging
+ enum ActiveUserProfile {
+ PARENT_PROFILE = 1;
+ MANAGED_PROFILE = 2;
+ }
+
// Known visual elements: views or controls.
enum View {
// Unknown view
@@ -6162,6 +6168,11 @@
// OS: P
FIELD_AUTOFILL_SESSION_ID = 1456;
+ // FIELD: Device USB overheat alarm trigger.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: P
+ POWER_OVERHEAT_ALARM = 1457;
+
// ---- End P Constants, all P constants go above this line ----
// Time since this notification last interrupted (visibly or audible) the user
@@ -7002,6 +7013,10 @@
// Different display can have different orientations, so need to log display id
FIELD_DISPLAY_ID = 1660;
+ // ACTION: Changing from work to parent profile or vice versa
+ // OS: Q
+ ACTION_SWITCH_SHARE_PROFILE = 1661;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index ad0ed8b..ee3777d 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1424,6 +1424,9 @@
// Amount of time wifi is scanning (ms)
optional int64 scan_time_ms = 12;
+
+ // Actual monitored rail energy consumed by wifi (mAh)
+ optional double monitored_rail_energy_consumed_mah = 13;
}
// Metrics for Wifi Wake
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index e0fb337..1cca813 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -30,6 +30,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -699,12 +700,31 @@
}
@Override
- public boolean isCompatibilityModeRequested(@NonNull String packageName,
+ public AutofillOptions getAutofillOptions(@NonNull String packageName,
long versionCode, @UserIdInt int userId) {
- return mAutofillCompatState.isCompatibilityModeRequested(
+ final int loggingLevel;
+ if (verbose) {
+ loggingLevel = AutofillManager.FLAG_ADD_CLIENT_VERBOSE
+ | AutofillManager.FLAG_ADD_CLIENT_DEBUG;
+ } else if (debug) {
+ loggingLevel = AutofillManager.FLAG_ADD_CLIENT_DEBUG;
+ } else {
+ loggingLevel = AutofillManager.NO_LOGGING;
+ }
+ final boolean compatModeEnabled = mAutofillCompatState.isCompatibilityModeRequested(
packageName, versionCode, userId);
- }
+ final AutofillOptions options = new AutofillOptions(loggingLevel, compatModeEnabled);
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ getServiceForUserLocked(UserHandle.getCallingUserId());
+ if (service != null) {
+ service.setAugmentedAutofillWhitelistLocked(options, packageName);
+ }
+ }
+
+ return options;
+ }
}
/**
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 15dce4a..364e537 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -28,6 +28,7 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -1169,6 +1170,13 @@
return mWhitelistedAugmentAutofillPackages.contains(packageName);
}
+ @GuardedBy("mLock")
+ void setAugmentedAutofillWhitelistLocked(@NonNull AutofillOptions options,
+ @NonNull String packageName) {
+ // TODO(b/122595322): need to setwhitelisted activities as well.
+ options.augmentedEnabled = mWhitelistedAugmentAutofillPackages.contains(packageName);
+ }
+
private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
// TODO(b/123100824): add CTS test for when it's null
synchronized (mLock) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0dd1ded..ffda581 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -464,15 +464,25 @@
*/
@Nullable
public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
- for (UserHandle handle : mContext.getSystemService(UserManager.class).getUserProfiles()) {
- UserBackupManagerService userBackupManagerService = getServiceUsers().get(
- handle.getIdentifier());
+ int callingUserId = Binder.getCallingUserHandle().getIdentifier();
+ long oldId = Binder.clearCallingIdentity();
+ int[] userIds;
+ try {
+ userIds = mContext.getSystemService(UserManager.class).getProfileIds(callingUserId,
+ false);
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
+
+ for (int userId : userIds) {
+ UserBackupManagerService userBackupManagerService = getServiceUsers().get(userId);
if (userBackupManagerService != null) {
if (userBackupManagerService.getAncestralSerialNumber() == ancestralSerialNumber) {
- return handle;
+ return UserHandle.of(userId);
}
}
}
+
return null;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 915c131..ed459db 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1060,7 +1060,8 @@
handleRegisterNetworkRequest(new NetworkRequestInfo(
null, networkRequest, new Binder()));
} else {
- handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID);
+ handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
+ /* callOnUnavailable */ false);
}
}
@@ -2641,11 +2642,25 @@
return true;
}
+ private boolean maybeHandleNetworkFactoryMessage(Message msg) {
+ switch (msg.what) {
+ default:
+ return false;
+ case NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
+ handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
+ /* callOnUnavailable */ true);
+ break;
+ }
+ }
+ return true;
+ }
+
@Override
public void handleMessage(Message msg) {
- if (!maybeHandleAsyncChannelMessage(msg) &&
- !maybeHandleNetworkMonitorMessage(msg) &&
- !maybeHandleNetworkAgentInfoMessage(msg)) {
+ if (!maybeHandleAsyncChannelMessage(msg)
+ && !maybeHandleNetworkMonitorMessage(msg)
+ && !maybeHandleNetworkAgentInfoMessage(msg)
+ && !maybeHandleNetworkFactoryMessage(msg)) {
maybeHandleNetworkAgentMessage(msg);
}
}
@@ -2787,6 +2802,9 @@
if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
+ // Finish setting up the full connection
+ mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
+ AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
// A network factory has connected. Send it all current NetworkRequests.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
if (nri.request.isListen()) continue;
@@ -2957,7 +2975,8 @@
if (existingRequest != null) { // remove the existing request.
if (DBG) log("Replacing " + existingRequest.request + " with "
+ nri.request + " because their intents matched.");
- handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
+ handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
+ /* callOnUnavailable */ false);
}
handleRegisterNetworkRequest(nri);
}
@@ -2983,7 +3002,7 @@
int callingUid) {
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
if (nri != null) {
- handleReleaseNetworkRequest(nri.request, callingUid);
+ handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
}
}
@@ -3066,7 +3085,8 @@
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
}
- private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
+ private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
+ boolean callOnUnavailable) {
final NetworkRequestInfo nri =
getNriForAppRequest(request, callingUid, "release NetworkRequest");
if (nri == null) {
@@ -3076,6 +3096,9 @@
log("releasing " + nri.request + " (release request)");
}
handleRemoveNetworkRequest(nri);
+ if (callOnUnavailable) {
+ callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
+ }
}
private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
@@ -3507,7 +3530,8 @@
break;
}
case EVENT_RELEASE_NETWORK_REQUEST: {
- handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
+ handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
+ /* callOnUnavailable */ false);
break;
}
case EVENT_SET_ACCEPT_UNVALIDATED: {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 0ed5beb..4d39f9a 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -145,7 +145,7 @@
# ---------------------------
# SystemServer.run() starts:
3010 boot_progress_system_run (time|2|3)
-
+3011 system_server_start (start_count|1),(uptime|2|3),(elapse_time|2|3)
# ---------------------------
# PackageManagerService.java
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index c334540..b423f62 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -54,7 +54,7 @@
private static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state";
private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
"debug.sys.looper_stats_enabled";
- private static final int DEFAULT_SAMPLING_INTERVAL = 100;
+ private static final int DEFAULT_SAMPLING_INTERVAL = 1000;
private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
private static final boolean DEFAULT_ENABLED = true;
private static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index cd9d84c..a5eab85 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2811,6 +2811,7 @@
@Override
public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
+ Slog.d(TAG, "unlockUserKey: " + userId);
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
@@ -4056,6 +4057,11 @@
@Override
public String[] getVisibleVolumesForUser(int userId) {
+ synchronized (mLock) {
+ if (!ArrayUtils.contains(mSystemUnlockedUsers, userId)) {
+ return EmptyArray.STRING;
+ }
+ }
final ArrayList<String> visibleVolsForUser = new ArrayList<>();
for (int i = mVisibleVols.size() - 1; i >= 0; --i) {
final VolumeInfo vol = mVisibleVols.get(i);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7c46f1d..375c5c4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -187,6 +187,7 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -1486,6 +1487,8 @@
private static String sTheRealBuildSerial = Build.UNKNOWN;
+ private ParcelFileDescriptor[] mLifeMonitorFds;
+
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -4741,12 +4744,12 @@
// Figure out whether the app needs to run in autofill compat mode.
- boolean isAutofillCompatEnabled = false;
+ AutofillOptions autofillOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final AutofillManagerInternal afm = LocalServices.getService(
AutofillManagerInternal.class);
if (afm != null) {
- isAutofillCompatEnabled = afm.isCompatibilityModeRequested(
+ autofillOptions = afm.getAutofillOptions(
app.info.packageName, app.info.versionCode, app.userId);
}
}
@@ -4779,7 +4782,7 @@
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
+ buildSerial, autofillOptions, contentCaptureOptions);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
@@ -4788,7 +4791,7 @@
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
+ buildSerial, autofillOptions, contentCaptureOptions);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
@@ -18500,4 +18503,24 @@
private boolean isOnOffloadQueue(int flags) {
return (mEnableOffloadQueue && ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0));
}
+
+ @Override
+ public ParcelFileDescriptor getLifeMonitor() {
+ if (!isCallerShell()) {
+ throw new SecurityException("Only shell can call it");
+ }
+ synchronized (this) {
+ try {
+ if (mLifeMonitorFds == null) {
+ mLifeMonitorFds = ParcelFileDescriptor.createPipe();
+ }
+ // The returned FD will be closed, but we want to keep our reader open,
+ // so return a dup instead.
+ return mLifeMonitorFds[0].dup();
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to create pipe", e);
+ return null;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 99e0707..8a208a5 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -916,15 +916,17 @@
extras = new Bundle();
}
extras.size(); // Force unpacel.
- mLogger.log("scheduleSync: account=", requestedAccount,
- " u", userId,
- " authority=", requestedAuthority,
- " reason=", reason,
- " extras=", extras,
- " cuid=", callingUid, " cpid=", callingPid, " cpkg=", callingPackage,
- " mdm=", minDelayMillis,
- " ciar=", checkIfAccountReady,
- " sef=", syncExemptionFlag);
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ mLogger.log("scheduleSync: account=", requestedAccount,
+ " u", userId,
+ " authority=", requestedAuthority,
+ " reason=", reason,
+ " extras=", extras,
+ " cuid=", callingUid, " cpid=", callingPid, " cpkg=", callingPackage,
+ " mdm=", minDelayMillis,
+ " ciar=", checkIfAccountReady,
+ " sef=", syncExemptionFlag);
+ }
AccountAndUser[] accounts = null;
if (requestedAccount != null) {
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 31b497d..36d9c0e 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -582,7 +582,7 @@
final SurfaceControl.Builder builder =
new SurfaceControl.Builder(mSurfaceSession).setName("ColorFade");
if (mMode == MODE_FADE) {
- builder.setColorLayer(true);
+ builder.setColorLayer();
} else {
builder.setBufferSize(mDisplayWidth, mDisplayHeight);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b2509e9..b020997 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1482,7 +1482,7 @@
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
pw.println(" mStableDisplaySize=" + mStableDisplaySize);
-
+ pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4b4788c..aa85c83 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -194,6 +194,8 @@
protected IGateKeeperService mGateKeeperService;
protected IAuthSecret mAuthSecretService;
+ private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
+
/**
* The UIDs that are used for system credential storage in keystore.
*/
@@ -405,9 +407,17 @@
return new SyntheticPasswordManager(getContext(), storage, getUserManager());
}
+ public boolean hasBiometrics() {
+ return BiometricManager.hasBiometrics(mContext);
+ }
+
public int binderGetCallingUid() {
return Binder.getCallingUid();
}
+
+ public boolean isGsiRunning() {
+ return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+ }
}
public LockSettingsService(Context context) {
@@ -2217,6 +2227,11 @@
}
tryRemoveUserFromSpCacheLater(userId);
+ if (mInjector.isGsiRunning()) {
+ Slog.w(TAG, "AuthSecret disabled in GSI");
+ return;
+ }
+
// Pass the primary user's auth secret to the HAL
if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
try {
@@ -2423,7 +2438,7 @@
notifyActivePasswordMetricsAvailable(userCredential, userId);
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
// Reset lockout
- if (BiometricManager.hasBiometrics(mContext)) {
+ if (mInjector.hasBiometrics()) {
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
Slog.i(TAG, "Resetting lockout, length: "
+ authResult.gkResponse.getPayload().length);
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b221241..152cf7f 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -77,6 +77,7 @@
private final int mUserId;
private final String mPackageName;
private final String mTag;
+ private final Bundle mSessionInfo;
private final ControllerLink mController;
private final MediaSession.Token mSessionToken;
private final SessionLink mSession;
@@ -121,13 +122,14 @@
private String mMetadataDescription;
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
- SessionCallbackLink cb, String tag, MediaSessionService.ServiceImpl service,
- Looper handlerLooper) {
+ SessionCallbackLink cb, String tag, Bundle sessionInfo,
+ MediaSessionService.ServiceImpl service, Looper handlerLooper) {
mOwnerPid = ownerPid;
mOwnerUid = ownerUid;
mUserId = userId;
mPackageName = ownerPackageName;
mTag = tag;
+ mSessionInfo = sessionInfo;
mController = new ControllerLink(new ControllerStub());
mSessionToken = new MediaSession.Token(mController);
mSession = new SessionLink(new SessionStub());
@@ -1309,6 +1311,11 @@
}
@Override
+ public Bundle getSessionInfo() {
+ return mSessionInfo;
+ }
+
+ @Override
public PendingIntent getLaunchPendingIntent() {
return mLaunchIntent;
}
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index 62d9b20..b86328b 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -549,9 +549,11 @@
}
private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
- String callerPackageName, SessionCallbackLink cb, String tag) throws RemoteException {
+ String callerPackageName, SessionCallbackLink cb, String tag, Bundle sessionInfo)
+ throws RemoteException {
synchronized (mLock) {
- return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb, tag);
+ return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb,
+ tag, sessionInfo);
}
}
@@ -563,7 +565,7 @@
* 4. It needs to be added to the relevant user record.
*/
private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
- String callerPackageName, SessionCallbackLink cb, String tag) {
+ String callerPackageName, SessionCallbackLink cb, String tag, Bundle sessionInfo) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
@@ -571,7 +573,7 @@
}
final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
- callerPackageName, cb, tag, this, mHandler.getLooper());
+ callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
try {
cb.getBinder().linkToDeath(session, 0);
} catch (RemoteException e) {
@@ -991,7 +993,7 @@
@Override
public SessionLink createSession(String packageName, SessionCallbackLink cb, String tag,
- int userId) throws RemoteException {
+ Bundle sessionInfo, int userId) throws RemoteException {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -1002,8 +1004,8 @@
if (cb == null) {
throw new IllegalArgumentException("Controller callback cannot be null");
}
- return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag)
- .getSessionBinder();
+ return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag,
+ sessionInfo).getSessionBinder();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 2aaa1ed..26cc0c1 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -49,12 +50,12 @@
private static final String USAGE =
"usage: cmd notification SUBCMD [args]\n\n"
+ "SUBCMDs:\n"
- + " allow_listener COMPONENT [user_id]\n"
- + " disallow_listener COMPONENT [user_id]\n"
- + " allow_assistant COMPONENT\n"
- + " remove_assistant COMPONENT\n"
- + " allow_dnd PACKAGE\n"
- + " disallow_dnd PACKAGE\n"
+ + " allow_listener COMPONENT [user_id (current user if not specified)]\n"
+ + " disallow_listener COMPONENT [user_id (current user if not specified)]\n"
+ + " allow_assistant COMPONENT [user_id (current user if not specified)]\n"
+ + " remove_assistant COMPONENT [user_id (current user if not specified)]\n"
+ + " allow_dnd PACKAGE [user_id (current user if not specified)]\n"
+ + " disallow_dnd PACKAGE [user_id (current user if not specified)]\n"
+ " suspend_package PACKAGE\n"
+ " unsuspend_package PACKAGE\n"
+ " post [--help | flags] TAG TEXT";
@@ -109,14 +110,24 @@
try {
switch (cmd.replace('-', '_')) {
case "allow_dnd": {
- mBinderService.setNotificationPolicyAccessGranted(
- getNextArgRequired(), true);
+ String packageName = getNextArgRequired();
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationPolicyAccessGrantedForUser(
+ packageName, userId, true);
}
break;
case "disallow_dnd": {
- mBinderService.setNotificationPolicyAccessGranted(
- getNextArgRequired(), false);
+ String packageName = getNextArgRequired();
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationPolicyAccessGrantedForUser(
+ packageName, userId, false);
}
break;
case "allow_listener": {
@@ -125,13 +136,11 @@
pw.println("Invalid listener - must be a ComponentName");
return -1;
}
- String userId = getNextArg();
- if (userId == null) {
- mBinderService.setNotificationListenerAccessGranted(cn, true);
- } else {
- mBinderService.setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), true);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
}
+ mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, true);
}
break;
case "disallow_listener": {
@@ -140,13 +149,11 @@
pw.println("Invalid listener - must be a ComponentName");
return -1;
}
- String userId = getNextArg();
- if (userId == null) {
- mBinderService.setNotificationListenerAccessGranted(cn, false);
- } else {
- mBinderService.setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), false);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
}
+ mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, false);
}
break;
case "allow_assistant": {
@@ -155,7 +162,11 @@
pw.println("Invalid assistant - must be a ComponentName");
return -1;
}
- mBinderService.setNotificationAssistantAccessGranted(cn, true);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationAssistantAccessGrantedForUser(cn, userId, true);
}
break;
case "disallow_assistant": {
@@ -164,7 +175,11 @@
pw.println("Invalid assistant - must be a ComponentName");
return -1;
}
- mBinderService.setNotificationAssistantAccessGranted(cn, false);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationAssistantAccessGrantedForUser(cn, userId, false);
}
break;
case "suspend_package": {
@@ -176,6 +191,7 @@
// only use for testing
mDirectService.simulatePackageSuspendBroadcast(false, getNextArgRequired());
}
+ break;
case "distract_package": {
// only use for testing
// Flag values are in
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 2c47ec0..660309c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -722,7 +722,8 @@
if (!channel.equals(updatedChannel)) {
// only log if there are real changes
- MetricsLogger.action(getChannelLog(updatedChannel, pkg));
+ MetricsLogger.action(getChannelLog(updatedChannel, pkg)
+ .setSubtype(fromUser ? 1 : 0));
}
if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index c2a75ab..bab612d 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -616,6 +616,7 @@
*
* @param pkg name of the package to snapshot user data for.
* @param userId id of the user whose data to snapshot.
+ * @param snapshotId id of this snapshot.
* @param storageFlags flags controlling which data (CE or DE) to snapshot.
*
* @return inode of the snapshot of users CE package data, or {@code 0} if a remote calls
@@ -623,12 +624,12 @@
*
* @throws InstallerException if failed to snapshot user data.
*/
- public long snapshotAppData(String pkg, @UserIdInt int userId, int storageFlags)
+ public long snapshotAppData(String pkg, @UserIdInt int userId, int snapshotId, int storageFlags)
throws InstallerException {
if (!checkBeforeRemote()) return 0;
try {
- return mInstalld.snapshotAppData(null, pkg, userId, storageFlags);
+ return mInstalld.snapshotAppData(null, pkg, userId, snapshotId, storageFlags);
} catch (Exception e) {
throw InstallerException.from(e);
}
@@ -639,8 +640,8 @@
*
* @param pkg name of the package to restore user data for.
* @param appId id of the package to restore user data for.
- * @param ceDataInode inode of CE user data folder of this app.
* @param userId id of the user whose data to restore.
+ * @param snapshotId id of the snapshot to restore.
* @param storageFlags flags controlling which data (CE or DE) to restore.
*
* @return {@code true} if user data restore was successful, or {@code false} if a remote call
@@ -648,12 +649,12 @@
*
* @throws InstallerException if failed to restore user data.
*/
- public boolean restoreAppDataSnapshot(String pkg, @AppIdInt int appId, long ceDataInode,
- String seInfo, @UserIdInt int userId, int storageFlags) throws InstallerException {
+ public boolean restoreAppDataSnapshot(String pkg, @AppIdInt int appId, String seInfo,
+ @UserIdInt int userId, int snapshotId, int storageFlags) throws InstallerException {
if (!checkBeforeRemote()) return false;
try {
- mInstalld.restoreAppDataSnapshot(null, pkg, appId, ceDataInode, seInfo, userId,
+ mInstalld.restoreAppDataSnapshot(null, pkg, appId, seInfo, userId, snapshotId,
storageFlags);
return true;
} catch (Exception e) {
@@ -667,6 +668,7 @@
* @param pkg name of the package to delete user data snapshot for.
* @param userId id of the user whose user data snapshot to delete.
* @param ceSnapshotInode inode of CE user data snapshot.
+ * @param snapshotId id of the snapshot to delete.
* @param storageFlags flags controlling which user data snapshot (CE or DE) to delete.
*
* @return {@code true} if user data snapshot was successfully deleted, or {@code false} if a
@@ -675,11 +677,12 @@
* @throws InstallerException if failed to delete user data snapshot.
*/
public boolean destroyAppDataSnapshot(String pkg, @UserIdInt int userId, long ceSnapshotInode,
- int storageFlags) throws InstallerException {
+ int snapshotId, int storageFlags) throws InstallerException {
if (!checkBeforeRemote()) return false;
try {
- mInstalld.destroyAppDataSnapshot(null, pkg, userId, ceSnapshotInode, storageFlags);
+ mInstalld.destroyAppDataSnapshot(null, pkg, userId, ceSnapshotInode, snapshotId,
+ storageFlags);
return true;
} catch (Exception e) {
throw InstallerException.from(e);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 62c4815..9e912843 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -20,7 +20,6 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.AppDetailsActivity;
import android.app.AppGlobals;
import android.app.IApplicationThread;
import android.app.PendingIntent;
@@ -367,7 +366,8 @@
private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
UserHandle user) {
Intent intent = new Intent();
- intent.setComponent(new ComponentName(packageName, AppDetailsActivity.class.getName()));
+ intent.setComponent(new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME));
final PackageManagerInternal pmInt =
LocalServices.getService(PackageManagerInternal.class);
List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index f06da49..bd74174 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -483,11 +483,12 @@
}
}
- if (params.isStaged) {
+ boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
+ if (params.isStaged || isApex) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
}
- if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+ if (isApex) {
if (!mApexManager.isApexSupported()) {
throw new IllegalArgumentException(
"This device doesn't support the installation of APEX files");
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1b71904..56ef33a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -322,18 +322,7 @@
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_COMMIT:
- synchronized (mLock) {
- try {
- commitLocked();
- } catch (PackageManagerException e) {
- final String completeMsg = ExceptionUtils.getCompleteMessage(e);
- Slog.e(TAG,
- "Commit of session " + sessionId + " failed: " + completeMsg);
- destroyInternal();
- dispatchSessionFinished(e.error, completeMsg, null);
- }
- }
-
+ handleCommit();
break;
case MSG_ON_PACKAGE_INSTALLED:
final SomeArgs args = (SomeArgs) msg.obj;
@@ -1073,38 +1062,66 @@
mCallback.onSessionSealedBlocking(this);
}
- @GuardedBy("mLock")
- private void commitLocked()
- throws PackageManagerException {
+ private void handleCommit() {
if (params.isStaged) {
mStagingManager.commitSession(this);
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}
+
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
- throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
- "APEX packages can only be installed using staged sessions.");
+ destroyInternal();
+ dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ "APEX packages can only be installed using staged sessions.", null);
+ return;
}
+
+ // For a multiPackage session, read the child sessions
+ // outside of the lock, because reading the child
+ // sessions with the lock held could lead to deadlock
+ // (b/123391593).
+ List<PackageInstallerSession> childSessions = null;
+ if (isMultiPackage()) {
+ final int[] childSessionIds = getChildSessionIds();
+ childSessions = new ArrayList<>(childSessionIds.length);
+ for (int childSessionId : childSessionIds) {
+ childSessions.add(mSessionProvider.getSession(childSessionId));
+ }
+ }
+
+ try {
+ synchronized (mLock) {
+ commitNonStagedLocked(childSessions);
+ }
+ } catch (PackageManagerException e) {
+ final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+ Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
+ destroyInternal();
+ dispatchSessionFinished(e.error, completeMsg, null);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void commitNonStagedLocked(List<PackageInstallerSession> childSessions)
+ throws PackageManagerException {
final PackageManagerService.ActiveInstallSession committingSession =
makeSessionActiveLocked();
if (committingSession == null) {
return;
}
if (isMultiPackage()) {
- final int[] childSessionIds = getChildSessionIds();
- List<PackageManagerService.ActiveInstallSession> childSessions =
- new ArrayList<>(childSessionIds.length);
+ List<PackageManagerService.ActiveInstallSession> activeChildSessions =
+ new ArrayList<>(childSessions.size());
boolean success = true;
PackageManagerException failure = null;
- for (int childSessionId : getChildSessionIds()) {
- final PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
+ for (int i = 0; i < childSessions.size(); ++i) {
+ final PackageInstallerSession session = childSessions.get(i);
try {
final PackageManagerService.ActiveInstallSession activeSession =
session.makeSessionActiveLocked();
if (activeSession != null) {
- childSessions.add(activeSession);
+ activeChildSessions.add(activeSession);
}
} catch (PackageManagerException e) {
failure = e;
@@ -1119,7 +1136,7 @@
}
return;
}
- mPm.installStage(childSessions);
+ mPm.installStage(activeChildSessions);
} else {
mPm.installStage(committingSession);
}
@@ -1887,6 +1904,9 @@
false, true).rethrowAsRuntimeException();
}
synchronized (mLock) {
+ assertCallerIsOwnerOrRootLocked();
+ assertPreparedAndNotSealedLocked("addChildSessionId");
+
final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
if (indexOfSession >= 0) {
return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9ff2f44..4bca5e0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -121,7 +121,6 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.AppDetailsActivity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
@@ -4212,6 +4211,55 @@
return -1;
}
+ /**
+ * Check if any package sharing/holding a uid has a low enough target SDK.
+ *
+ * @param uid The uid of the packages
+ * @param higherTargetSDK The target SDK that might be higher than the searched package
+ *
+ * @return {@code true} if there is a package sharing/holding the uid with
+ * {@code package.targetSDK < higherTargetSDK}
+ */
+ private boolean hasTargetSdkInUidLowerThan(int uid, int higherTargetSDK) {
+ int userId = UserHandle.getUserId(uid);
+
+ synchronized (mPackages) {
+ Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj instanceof PackageSetting) {
+ final PackageSetting ps = (PackageSetting) obj;
+
+ if (!ps.getInstalled(userId)) {
+ return false;
+ }
+
+ return ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK;
+ } else if (obj instanceof SharedUserSetting) {
+ final SharedUserSetting sus = (SharedUserSetting) obj;
+
+ final int numPkgs = sus.packages.size();
+ for (int i = 0; i < numPkgs; i++) {
+ final PackageSetting ps = sus.packages.valueAt(i);
+
+ if (!ps.getInstalled(userId)) {
+ continue;
+ }
+
+ if (ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return false;
+ }
+ }
+ }
+
@Override
public int[] getPackageGids(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
@@ -5280,13 +5328,21 @@
@Override
public void grantRuntimePermission(String packageName, String permName, final int userId) {
- mPermissionManager.grantRuntimePermission(permName, packageName, false /*overridePolicy*/,
+ boolean overridePolicy = (checkUidPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED);
+
+ mPermissionManager.grantRuntimePermission(permName, packageName, overridePolicy,
getCallingUid(), userId, mPermissionCallback);
}
@Override
public void revokeRuntimePermission(String packageName, String permName, int userId) {
- mPermissionManager.revokeRuntimePermission(permName, packageName, false /*overridePolicy*/,
+ boolean overridePolicy = (checkUidPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED);
+
+ mPermissionManager.revokeRuntimePermission(permName, packageName, overridePolicy,
getCallingUid(), userId, mPermissionCallback);
}
@@ -5329,10 +5385,37 @@
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int userId) {
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+ int callingUid = getCallingUid();
+ boolean overridePolicy = false;
+
+ if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ if (checkAdjustPolicyFlagPermission) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
+ "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
+ + " to change policy flags");
+ } else if (!hasTargetSdkInUidLowerThan(callingUid, Build.VERSION_CODES.Q)) {
+ throw new IllegalArgumentException(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
+ + " to be checked for packages targeting "
+ + Build.VERSION_CODES.Q + " or later when changing policy "
+ + "flags");
+ }
+
+ overridePolicy = true;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
mPermissionManager.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, getCallingUid(), userId,
- mPermissionCallback);
+ permName, packageName, flagMask, flagValues, callingUid, userId,
+ overridePolicy, mPermissionCallback);
}
/**
@@ -12867,8 +12950,14 @@
"setPackagesSuspendedAsUser");
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
- && getPackageUid(callingPackage, 0, userId) != callingUid) {
+ final int packageUid = getPackageUid(callingPackage, 0, userId);
+ final boolean allowedCallingUid = callingUid == Process.ROOT_UID
+ || callingUid == Process.SYSTEM_UID;
+ final boolean allowedPackageUid = packageUid == callingUid;
+ final boolean allowedShell = callingUid == SHELL_UID
+ && UserHandle.isSameApp(packageUid, callingUid);
+
+ if (!allowedCallingUid && !allowedShell && !allowedPackageUid) {
throw new SecurityException("Calling package " + callingPackage + " in user "
+ userId + " does not belong to calling uid " + callingUid);
}
@@ -13058,6 +13147,7 @@
@Override
public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
+ Preconditions.checkNotNull("packageNames cannot be null", packageNames);
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
"getUnsuspendablePackagesForUser");
final int callingUid = Binder.getCallingUid();
@@ -19947,8 +20037,11 @@
private @Nullable String getDocumenterPackageName() {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+ final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, resolvedType,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
| MATCH_DISABLED_COMPONENTS,
UserHandle.myUserId());
@@ -20103,13 +20196,9 @@
}
// Only allow apps with CHANGE_COMPONENT_ENABLED_STATE permission to change hidden
// app details activity
- if (AppDetailsActivity.class.getName().equals(className)) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.e(TAG, "Cannot disable a protected component: " + packageName);
- return;
- }
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)
+ && !allowedByPermission) {
+ throw new SecurityException("Cannot disable a system-generated component");
}
synchronized (mPackages) {
@@ -22996,7 +23085,7 @@
public void updatePermissionFlagsTEMP(String permName, String packageName, int flagMask,
int flagValues, int userId) {
PackageManagerService.this.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, userId);
+ permName, packageName, flagMask, flagValues, true, userId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d0f192d..3744f68 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1324,6 +1324,7 @@
@Override
public ParcelFileDescriptor getUserIcon(int targetUserId) {
+ checkManageUsersPermission("get user icon");
String iconPath;
synchronized (mPackagesLock) {
UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
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 6369179..93a3d0a 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -206,6 +206,11 @@
// STOPSHIP(b/112545973): remove once feature enabled by default
if (StorageManager.hasIsolatedStorage()) {
MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
+
+ // STOPSHIP(b/124466734): remove these manual grants once the legacy
+ // permission logic is unified with PermissionController
+ MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
@@ -215,6 +220,11 @@
if (StorageManager.hasIsolatedStorage()) {
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
+
+ // STOPSHIP(b/124466734): remove these manual grants once the legacy
+ // permission logic is unified with PermissionController
+ MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
@@ -642,16 +652,10 @@
// Location
if (locationPackageNames != null) {
for (String packageName : locationPackageNames) {
- // STOPSHIP: remove this force-granting of legacy storage
- // permissions once b/124466734 is resolved
- final Set<String> storageWorkaround = new ArraySet<>();
- storageWorkaround.add(Manifest.permission.READ_EXTERNAL_STORAGE);
- storageWorkaround.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
-
grantPermissionsToSystemPackage(packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
- SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, storageWorkaround);
+ SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
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 8df5a71..03da962 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -35,6 +35,7 @@
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.content.pm.PackageManager.MASK_PERMISSION_FLAGS;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.UserHandle.getAppId;
import static android.os.UserHandle.getUid;
@@ -1031,7 +1032,8 @@
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
- permissionsState.updatePermissionFlags(bp, userId, flags, flags);
+ permissionsState.updatePermissionFlags(bp, userId,
+ MASK_PERMISSION_FLAGS, flags);
}
} break;
@@ -1081,7 +1083,8 @@
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
- permissionsState.updatePermissionFlags(bp, userId, flags, flags);
+ permissionsState.updatePermissionFlags(bp, userId,
+ MASK_PERMISSION_FLAGS, flags);
}
} break;
@@ -1198,29 +1201,23 @@
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);
+ int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
- == 0) {
- if (supportsRuntimePermissions) {
- int revokeResult = ps.revokeRuntimePermission(bp, userId);
- if (revokeResult != PERMISSION_OPERATION_FAILURE) {
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking runtime permission "
- + permission + " for " + pkgName
- + " as it is now requested");
- }
+ == 0 && supportsRuntimePermissions) {
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult != PERMISSION_OPERATION_FAILURE) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission "
+ + permission + " for " + pkgName
+ + " as it is now requested");
}
- } else {
- setAppOpMode(permission, pkg, userId, MODE_IGNORED);
}
+ flagsToRemove |=
+ FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_USER_SET;
+
List<String> fgPerms = mBackgroundPermissions.get(permission);
if (fgPerms != null) {
int numFgPerms = fgPerms.size();
@@ -1238,6 +1235,9 @@
}
}
}
+
+ ps.updatePermissionFlags(bp, userId, flagsToRemove, 0);
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
}
}
@@ -1935,7 +1935,7 @@
if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
updatePermissionFlags(permission, pkg.packageName,
PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
- userId, callback);
+ userId, false, callback);
}
}
}
@@ -2441,7 +2441,8 @@
}
private void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int callingUid, int userId, PermissionCallback callback) {
+ int flagValues, int callingUid, int userId, boolean overridePolicy,
+ PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
return;
}
@@ -2454,6 +2455,11 @@
false, // requirePermissionWhenSameUser
"updatePermissionFlags");
+ if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
+ throw new SecurityException("updatePermissionFlags requires "
+ + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
+ }
+
// Only the system can change these flags and nothing else.
if (callingUid != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
@@ -2745,9 +2751,11 @@
}
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int callingUid, int userId, PermissionCallback callback) {
+ int flagValues, int callingUid, int userId, boolean overridePolicy,
+ PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, callingUid, userId, callback);
+ permName, packageName, flagMask, flagValues, callingUid, userId,
+ overridePolicy, callback);
}
@Override
public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 1dd2408..305f165 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -147,7 +147,7 @@
*/
public abstract void updatePermissionFlags(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int callingUid, int userId,
- @Nullable PermissionCallback callback);
+ boolean overridePolicy, @Nullable PermissionCallback callback);
/**
* Updates the flags for all applications by replacing the flags in the specified mask
* with the provided flag values.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c87a81d..68dab34 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2316,14 +2316,15 @@
boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
&& showImeOverKeyguard;
- if (isKeyguardLocked() && isKeyguardOccluded()) {
+ final boolean isKeyguardShowing = mKeyguardDelegate.isShowing();
+
+ if (isKeyguardShowing && isKeyguardOccluded()) {
// Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
allowWhenLocked |= win.canShowWhenLocked()
// Show error dialogs over apps that are shown on lockscreen
|| (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
}
- boolean keyguardLocked = isKeyguardLocked();
boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
&& !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
// If AOD is showing, the IME should be hidden. However, sometimes the AOD is considered
@@ -2333,7 +2334,7 @@
// now shown.
final boolean hideIme = win.isInputMethodWindow()
&& (mAodShowing || !mDefaultDisplayPolicy.isWindowManagerDrawComplete());
- return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
+ return (isKeyguardShowing && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider || hideIme;
}
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 888dd99..77bf930 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -130,6 +130,12 @@
String packageName = componentName != null ? componentName.getPackageName() : null;
return CollectionUtils.singletonOrEmpty(packageName);
}
+ case RoleManager.ROLE_EMERGENCY: {
+ String defaultEmergencyApp = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId);
+ return CollectionUtils.singletonOrEmpty(defaultEmergencyApp);
+ }
default: {
Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName);
return Collections.emptyList();
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c145a22..17d3066 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -237,6 +237,7 @@
migrateRoleIfNecessary(RoleManager.ROLE_SMS, userId);
migrateRoleIfNecessary(RoleManager.ROLE_ASSISTANT, userId);
migrateRoleIfNecessary(RoleManager.ROLE_DIALER, userId);
+ migrateRoleIfNecessary(RoleManager.ROLE_EMERGENCY, userId);
// Some vital packages state has changed since last role grant
// Run grants again
diff --git a/services/core/java/com/android/server/role/TEST_MAPPING b/services/core/java/com/android/server/role/TEST_MAPPING
index 0b967be..0d7bc14 100644
--- a/services/core/java/com/android/server/role/TEST_MAPPING
+++ b/services/core/java/com/android/server/role/TEST_MAPPING
@@ -7,11 +7,14 @@
"include-filter": "android.cts.statsd.atom.UidAtomTests#testRoleHolder"
}
]
- }
- ],
- "postsubmit": [
+ },
{
- "name": "CtsRoleTestCases"
+ "name": "CtsRoleTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index f3b8385..e9ccea54 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -29,6 +29,8 @@
import com.android.server.pm.Installer.InstallerException;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -49,16 +51,11 @@
}
/**
- * Creates an app data snapshot for a specified {@code packageName} for {@code installedUsers},
- * a specified set of users for whom the package is installed.
- *
- * @return a {@link SnapshotAppDataResult}/
- * @see SnapshotAppDataResult
+ * Creates an app data snapshot for a specified {@code packageRollbackInfo}. Updates said {@code
+ * packageRollbackInfo} with the inodes of the CE user data snapshot folders.
*/
- public SnapshotAppDataResult snapshotAppData(String packageName, int[] installedUsers) {
- final IntArray pendingBackups = new IntArray();
- final SparseLongArray ceSnapshotInodes = new SparseLongArray();
-
+ public void snapshotAppData(int snapshotId, PackageRollbackInfo packageRollbackInfo) {
+ final int[] installedUsers = packageRollbackInfo.getInstalledUsers().toArray();
for (int user : installedUsers) {
final int storageFlags;
if (isUserCredentialLocked(user)) {
@@ -66,51 +63,38 @@
// across app user data until the user unlocks their device.
Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
storageFlags = Installer.FLAG_STORAGE_DE;
- pendingBackups.add(user);
+ packageRollbackInfo.addPendingBackup(user);
} else {
storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
}
try {
- long ceSnapshotInode = mInstaller.snapshotAppData(packageName, user, storageFlags);
+ long ceSnapshotInode = mInstaller.snapshotAppData(
+ packageRollbackInfo.getPackageName(), user, snapshotId, storageFlags);
if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) {
- ceSnapshotInodes.put(user, ceSnapshotInode);
+ packageRollbackInfo.putCeSnapshotInode(user, ceSnapshotInode);
}
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to create app data snapshot for: " + packageName
- + ", userId: " + user, ie);
+ Log.e(TAG, "Unable to create app data snapshot for: "
+ + packageRollbackInfo.getPackageName() + ", userId: " + user, ie);
}
}
-
- return new SnapshotAppDataResult(pendingBackups, ceSnapshotInodes);
}
/**
- * Restores an app data snapshot for a specified package ({@code packageName},
- * {@code rollbackData}) for a specified {@code userId}.
+ * Restores an app data snapshot for a specified {@code packageRollbackInfo}, for a specified
+ * {@code userId}.
*
- * @return {@code true} iff. a change to the {@code rollbackData} has been made. Changes to
- * {@code rollbackData} are restricted to the removal or addition of {@code userId} to
- * the list of pending backups or restores.
+ * @return {@code true} iff. a change to the {@code packageRollbackInfo} has been made. Changes
+ * to {@code packageRollbackInfo} are restricted to the removal or addition of {@code
+ * userId} to the list of pending backups or restores.
*/
- public boolean restoreAppData(String packageName, RollbackData rollbackData,
- int userId, int appId, long ceDataInode, String seInfo) {
- if (rollbackData == null) {
- return false;
- }
-
- if (!rollbackData.inProgress) {
- Log.e(TAG, "Request to restore userData for: " + packageName
- + ", but no rollback in progress.");
- return false;
- }
-
- PackageRollbackInfo packageInfo = RollbackManagerServiceImpl.getPackageRollbackInfo(
- rollbackData, packageName);
+ public boolean restoreAppData(int rollbackId, PackageRollbackInfo packageRollbackInfo,
+ int userId, int appId, String seInfo) {
int storageFlags = Installer.FLAG_STORAGE_DE;
- final IntArray pendingBackups = packageInfo.getPendingBackups();
- final List<RestoreInfo> pendingRestores = packageInfo.getPendingRestores();
+ final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
+ final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores();
boolean changedRollbackData = false;
// If we still have a userdata backup pending for this user, it implies that the user
@@ -134,53 +118,60 @@
}
try {
- mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
- seInfo, userId, storageFlags);
+ mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo,
+ userId, rollbackId, storageFlags);
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
+ Log.e(TAG, "Unable to restore app data snapshot: "
+ + packageRollbackInfo.getPackageName(), ie);
}
return changedRollbackData;
}
/**
- * Deletes an app data data snapshot for a specified package {@code packageName} for a
- * given {@code user}.
+ * Deletes an app data snapshot with a given {@code rollbackId} for a specified package
+ * {@code packageName} for a given {@code user}.
*/
- public void destroyAppDataSnapshot(String packageName, int user, long ceSnapshotInode) {
+ public void destroyAppDataSnapshot(int rollbackId, PackageRollbackInfo packageRollbackInfo,
+ int user) {
int storageFlags = Installer.FLAG_STORAGE_DE;
+ final SparseLongArray ceSnapshotInodes = packageRollbackInfo.getCeSnapshotInodes();
+ long ceSnapshotInode = ceSnapshotInodes.get(user);
if (ceSnapshotInode > 0) {
storageFlags |= Installer.FLAG_STORAGE_CE;
}
try {
- mInstaller.destroyAppDataSnapshot(packageName, user, ceSnapshotInode, storageFlags);
+ mInstaller.destroyAppDataSnapshot(packageRollbackInfo.getPackageName(), user,
+ ceSnapshotInode, rollbackId, storageFlags);
+ if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) {
+ ceSnapshotInodes.delete(user);
+ }
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to delete app data snapshot for " + packageName, ie);
+ Log.e(TAG, "Unable to delete app data snapshot for "
+ + packageRollbackInfo.getPackageName(), ie);
}
}
/**
- * Computes the list of pending backups and restores for {@code userId} given lists of
- * available and recent rollbacks. Packages pending backup for the given user are added
- * to {@code pendingBackups} and packages pending restore are added to {@code pendingRestores}
- * along with their corresponding {@code RestoreInfo}.
+ * Computes the list of pending backups for {@code userId} given lists of available rollbacks.
+ * Packages pending backup for the given user are added to {@code pendingBackupPackages} along
+ * with their corresponding {@code PackageRollbackInfo}.
*
- * @return the list of {@code RollbackData} that have been modified during this computation.
+ * @return the list of {@code RollbackData} that has pending backups. Note that some of the
+ * backups won't be performed, because they might be counteracted by pending restores.
*/
- public List<RollbackData> computePendingBackupsAndRestores(int userId,
- ArrayList<String> pendingBackupPackages, Map<String, RestoreInfo> pendingRestores,
- List<RollbackData> availableRollbacks, List<RollbackInfo> recentRollbacks) {
+ private static List<RollbackData> computePendingBackups(int userId,
+ Map<String, PackageRollbackInfo> pendingBackupPackages,
+ List<RollbackData> availableRollbacks) {
List<RollbackData> rd = new ArrayList<>();
- // First check with the list of available rollbacks to see whether there are any
- // pending backup operations that we've not managed to execute.
+
for (RollbackData data : availableRollbacks) {
for (PackageRollbackInfo info : data.packages) {
final IntArray pendingBackupUsers = info.getPendingBackups();
if (pendingBackupUsers != null) {
final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) {
- pendingBackupPackages.add(info.getPackageName());
- pendingBackupUsers.remove(idx);
+ pendingBackupPackages.put(info.getPackageName(), info);
if (rd.indexOf(data) == -1) {
rd.add(data);
}
@@ -188,23 +179,30 @@
}
}
}
+ return rd;
+ }
- // Then check with the list of recently executed rollbacks to see whether there are
- // any rollback operations
+ /**
+ * Computes the list of pending restores for {@code userId} given lists of recent rollbacks.
+ * Packages pending restore are added to {@code pendingRestores} along with their corresponding
+ * {@code PackageRollbackInfo}.
+ *
+ * @return the list of {@code RollbackInfo} that has pending restores. Note that some of the
+ * restores won't be performed, because they might be counteracted by pending backups.
+ */
+ private static List<RollbackInfo> computePendingRestores(int userId,
+ Map<String, PackageRollbackInfo> pendingRestorePackages,
+ List<RollbackInfo> recentRollbacks) {
+ List<RollbackInfo> rd = new ArrayList<>();
+
for (RollbackInfo data : recentRollbacks) {
for (PackageRollbackInfo info : data.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) {
- if (pendingBackupPackages.contains(info.getPackageName())) {
- // This implies that the user hasn't unlocked their device between
- // the request to backup data for this user and the request to restore
- // it, so we do nothing here.
- pendingBackupPackages.remove(info.getPackageName());
- } else {
- pendingRestores.put(info.getPackageName(), ri);
+ pendingRestorePackages.put(info.getPackageName(), info);
+ if (rd.indexOf(data) == -1) {
+ rd.add(data);
}
-
- info.removeRestoreInfo(ri);
}
}
}
@@ -216,47 +214,77 @@
* Commits the list of pending backups and restores for a given {@code userId}. For the pending
* backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId}
* to a inode of theirs CE user data snapshot.
+ *
+ * @return a list {@code RollbackData} that have been changed and should be stored on disk.
*/
- public void commitPendingBackupAndRestoreForUser(int userId,
- ArrayList<String> pendingBackups, Map<String, RestoreInfo> pendingRestores,
- List<RollbackData> changedRollbackData) {
- if (!pendingBackups.isEmpty()) {
- for (String packageName : pendingBackups) {
- try {
- long ceSnapshotInode = mInstaller.snapshotAppData(packageName, userId,
- Installer.FLAG_STORAGE_CE);
- for (RollbackData data : changedRollbackData) {
- for (PackageRollbackInfo info : data.packages) {
- if (info.getPackageName().equals(packageName)) {
- info.putCeSnapshotInode(userId, ceSnapshotInode);
- }
+ public List<RollbackData> commitPendingBackupAndRestoreForUser(int userId,
+ List<RollbackData> availableRollbacks, List<RollbackInfo> recentlyExecutedRollbacks) {
+
+ final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>();
+ final List<RollbackData> pendingBackups = computePendingBackups(userId,
+ pendingBackupPackages, availableRollbacks);
+
+ final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>();
+ final List<RollbackInfo> pendingRestores = computePendingRestores(userId,
+ pendingRestorePackages, recentlyExecutedRollbacks);
+
+ // First remove unnecessary backups, i.e. when user did not unlock their phone between the
+ // request to backup data and the request to restore it.
+ Iterator<Map.Entry<String, PackageRollbackInfo>> iter =
+ pendingBackupPackages.entrySet().iterator();
+ while (iter.hasNext()) {
+ PackageRollbackInfo backupPackage = iter.next().getValue();
+ PackageRollbackInfo restorePackage =
+ pendingRestorePackages.get(backupPackage.getPackageName());
+ if (restorePackage != null) {
+ backupPackage.removePendingBackup(userId);
+ backupPackage.removePendingRestoreInfo(userId);
+ iter.remove();
+ pendingRestorePackages.remove(backupPackage.getPackageName());
+ }
+ }
+
+ if (!pendingBackupPackages.isEmpty()) {
+ for (RollbackData data : pendingBackups) {
+ for (PackageRollbackInfo info : data.packages) {
+ final IntArray pendingBackupUsers = info.getPendingBackups();
+ final int idx = pendingBackupUsers.indexOf(userId);
+ if (idx != -1) {
+ try {
+ long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(),
+ userId, data.rollbackId, Installer.FLAG_STORAGE_CE);
+ info.putCeSnapshotInode(userId, ceSnapshotInode);
+ pendingBackupUsers.remove(idx);
+ } catch (InstallerException ie) {
+ Log.e(TAG,
+ "Unable to create app data snapshot for: "
+ + info.getPackageName() + ", userId: " + userId, ie);
}
}
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to create app data snapshot for: " + packageName
- + ", userId: " + userId, ie);
}
}
}
- // TODO(narayan): Should we perform the restore before the backup for packages that have
- // both backups and restores pending ? We could get into this case if we have a pending
- // restore from a rollback + a snapshot request from a new restore.
- if (!pendingRestores.isEmpty()) {
- for (String packageName : pendingRestores.keySet()) {
- try {
- final RestoreInfo ri = pendingRestores.get(packageName);
-
- // TODO(narayan): Verify that the user of "0" for ceDataInode is accurate
- // here. We know that the user has unlocked (and that their CE data is
- // available) so we shouldn't need to resort to the fallback path.
- mInstaller.restoreAppDataSnapshot(packageName, ri.appId,
- 0 /* ceDataInode */, ri.seInfo, userId, Installer.FLAG_STORAGE_CE);
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to restore app data snapshot for: " + packageName, ie);
+ if (!pendingRestorePackages.isEmpty()) {
+ for (RollbackInfo data : pendingRestores) {
+ for (PackageRollbackInfo info : data.getPackages()) {
+ final RestoreInfo ri = info.getRestoreInfo(userId);
+ if (ri != null) {
+ try {
+ mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
+ ri.seInfo, userId, data.getRollbackId(),
+ Installer.FLAG_STORAGE_CE);
+ info.removeRestoreInfo(ri);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to restore app data snapshot for: "
+ + info.getPackageName(), ie);
+ }
+ }
}
}
}
+
+ return pendingBackups;
}
/**
@@ -267,26 +295,4 @@
return StorageManager.isFileEncryptedNativeOrEmulated()
&& !StorageManager.isUserKeyUnlocked(userId);
}
-
- /**
- * Encapsulates a result of {@link #snapshotAppData} method.
- */
- public static final class SnapshotAppDataResult {
-
- /**
- * A list of users for which the snapshot is pending, usually because data for one or more
- * users is still credential locked.
- */
- public final IntArray pendingBackups;
-
- /**
- * A mapping between user and an inode of theirs CE data snapshot.
- */
- public final SparseLongArray ceSnapshotInodes;
-
- public SnapshotAppDataResult(IntArray pendingBackups, SparseLongArray ceSnapshotInodes) {
- this.pendingBackups = pendingBackups;
- this.ceSnapshotInodes = ceSnapshotInodes;
- }
- }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 05d3c17..11839a5 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -32,7 +32,6 @@
import android.content.pm.VersionedPackage;
import android.content.rollback.IRollbackManager;
import android.content.rollback.PackageRollbackInfo;
-import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Binder;
@@ -466,18 +465,17 @@
void onUnlockUser(int userId) {
getHandler().post(() -> {
- final ArrayList<String> pendingBackupPackages = new ArrayList<>();
- final Map<String, RestoreInfo> pendingRestorePackages = new HashMap<>();
- final List<RollbackData> changed;
+ final List<RollbackData> availableRollbacks;
+ final List<RollbackInfo> recentlyExecutedRollbacks;
synchronized (mLock) {
ensureRollbackDataLoadedLocked();
- changed = mAppDataRollbackHelper.computePendingBackupsAndRestores(userId,
- pendingBackupPackages, pendingRestorePackages, mAvailableRollbacks,
- mRecentlyExecutedRollbacks);
+ availableRollbacks = new ArrayList<>(mAvailableRollbacks);
+ recentlyExecutedRollbacks = new ArrayList<>(mRecentlyExecutedRollbacks);
}
- mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId,
- pendingBackupPackages, pendingRestorePackages, changed);
+ final List<RollbackData> changed =
+ mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId,
+ availableRollbacks, recentlyExecutedRollbacks);
for (RollbackData rd : changed) {
try {
@@ -844,13 +842,7 @@
for (PackageRollbackInfo info : rd.packages) {
if (info.getPackageName().equals(packageName)) {
info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
- AppDataRollbackHelper.SnapshotAppDataResult rs =
- mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
- info.getPendingBackups().addAll(rs.pendingBackups);
- for (int i = 0; i < rs.ceSnapshotInodes.size(); i++) {
- info.putCeSnapshotInode(rs.ceSnapshotInodes.keyAt(i),
- rs.ceSnapshotInodes.valueAt(i));
- }
+ mAppDataRollbackHelper.snapshotAppData(rd.rollbackId, info);
try {
mRollbackStore.saveAvailableRollback(rd);
} catch (IOException ioe) {
@@ -919,18 +911,10 @@
VersionedPackage installedVersion = new VersionedPackage(packageName,
pkgInfo.getLongVersionCode());
- final AppDataRollbackHelper.SnapshotAppDataResult result;
- if (snapshotUserData && !isApex) {
- result = mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
- } else {
- result = new AppDataRollbackHelper.SnapshotAppDataResult(IntArray.wrap(new int[0]),
- new SparseLongArray());
- }
-
PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion,
- result.pendingBackups, new ArrayList<>(), isApex, IntArray.wrap(installedUsers),
- result.ceSnapshotInodes);
-
+ new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
+ isApex, IntArray.wrap(installedUsers),
+ new SparseLongArray() /* ceSnapshotInodes */);
RollbackData data;
try {
int childSessionId = session.getSessionId();
@@ -948,7 +932,7 @@
int rollbackId = allocateRollbackIdLocked();
if (session.isStaged()) {
data = mRollbackStore.createPendingStagedRollback(rollbackId,
- parentSessionId);
+ parentSessionId);
} else {
data = mRollbackStore.createAvailableRollback(rollbackId);
}
@@ -961,6 +945,10 @@
return false;
}
+ if (snapshotUserData && !isApex) {
+ mAppDataRollbackHelper.snapshotAppData(data.rollbackId, info);
+ }
+
try {
RollbackStore.backupPackageCode(data, packageName, pkgInfo.applicationInfo.sourceDir);
} catch (IOException e) {
@@ -978,29 +966,45 @@
}
getHandler().post(() -> {
- final RollbackData rollbackData = getRollbackForPackage(packageName);
- for (int userId : userIds) {
- final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
- packageName, rollbackData, userId, appId, ceDataInode, seInfo);
- // We've updated metadata about this rollback, so save it to flash.
- if (changedRollbackData) {
- try {
- mRollbackStore.saveAvailableRollback(rollbackData);
- } catch (IOException ioe) {
- // TODO(narayan): What is the right thing to do here ? This isn't a fatal
- // error, since it will only result in us trying to restore data again,
- // which will be a no-op if there's no data available.
- Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
- }
- }
- }
-
+ restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token);
final PackageManagerInternal pmi = LocalServices.getService(
PackageManagerInternal.class);
pmi.finishPackageInstall(token, false);
});
}
+ private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
+ long ceDataInode, String seInfo, int token) {
+ final RollbackData rollbackData = getRollbackForPackage(packageName);
+ if (rollbackData == null) {
+ return;
+ }
+
+ if (!rollbackData.inProgress) {
+ Log.e(TAG, "Request to restore userData for: " + packageName
+ + ", but no rollback in progress.");
+ return;
+ }
+
+ for (int userId : userIds) {
+ final PackageRollbackInfo info = getPackageRollbackInfo(rollbackData, packageName);
+ final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
+ rollbackData.rollbackId, info, userId, appId, seInfo);
+
+ // We've updated metadata about this rollback, so save it to flash.
+ if (changedRollbackData) {
+ try {
+ mRollbackStore.saveAvailableRollback(rollbackData);
+ } catch (IOException ioe) {
+ // TODO(narayan): What is the right thing to do here ? This isn't a fatal
+ // error, since it will only result in us trying to restore data again,
+ // which will be a no-op if there's no data available.
+ Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
+ }
+ }
+ }
+ }
+
@Override
public boolean notifyStagedSession(int sessionId) {
final LinkedBlockingQueue<Boolean> result = new LinkedBlockingQueue<>();
@@ -1252,7 +1256,7 @@
* Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
* a specified {@code RollbackData}.
*/
- static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
+ private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
String packageName) {
for (PackageRollbackInfo info : data.packages) {
if (info.getPackageName().equals(packageName)) {
@@ -1281,11 +1285,10 @@
private void deleteRollback(RollbackData rollbackData) {
for (PackageRollbackInfo info : rollbackData.packages) {
IntArray installedUsers = info.getInstalledUsers();
- SparseLongArray ceSnapshotInodes = info.getCeSnapshotInodes();
for (int i = 0; i < installedUsers.size(); i++) {
int userId = installedUsers.get(i);
- mAppDataRollbackHelper.destroyAppDataSnapshot(info.getPackageName(), userId,
- ceSnapshotInodes.get(userId, 0));
+ mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.rollbackId, info,
+ userId);
}
}
mRollbackStore.deleteAvailableRollback(rollbackData);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 932cfd3..a4457e2 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -4019,7 +4019,7 @@
"Prepare close transition: finishing " + r);
if (endTask) {
mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
- task.taskId);
+ task.getTaskInfo());
}
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
@@ -4924,8 +4924,7 @@
mRootActivityContainer.resumeFocusedStacksTopActivities();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
-
- mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
+ mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
} finally {
getDisplay().continueUpdateImeTarget();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 9823ecc..df76030 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2358,7 +2358,8 @@
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
mService.getTaskChangeNotificationController()
- .notifyActivityLaunchOnSecondaryDisplayFailed();
+ .notifyActivityLaunchOnSecondaryDisplayFailed(task.getTaskInfo(),
+ preferredDisplayId);
return;
} else if (!forceNonResizable && handleForcedResizableTask(task,
FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY)) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 9ea819e..9f04166 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -46,6 +46,7 @@
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
@@ -1457,6 +1458,14 @@
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTaskRecord().setIntent(mStartActivity);
+ } else {
+ final boolean taskOnHome =
+ (mStartActivity.intent.getFlags() & FLAG_ACTIVITY_TASK_ON_HOME) != 0;
+ if (taskOnHome) {
+ reusedActivity.getTaskRecord().intent.addFlags(FLAG_ACTIVITY_TASK_ON_HOME);
+ } else {
+ reusedActivity.getTaskRecord().intent.removeFlags(FLAG_ACTIVITY_TASK_ON_HOME);
+ }
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 49c020b..cb4664f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2777,7 +2777,7 @@
r.setTaskDescription(td);
final TaskRecord task = r.getTaskRecord();
task.updateTaskDescription();
- mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
+ mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.getTaskInfo());
}
}
}
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 497e412..84ba5ca9 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -48,7 +48,7 @@
surface = dc.makeOverlay()
.setName("BlackSurface")
- .setColorLayer(true)
+ .setColorLayer()
.setParent(null) // TODO: Work-around for b/69259549
.build();
transaction.setWindowCrop(surface, w, h);
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 1373e18..ee28084 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -164,7 +164,7 @@
private SurfaceControl makeDimLayer() {
return mHost.makeChildSurface(null)
.setParent(mHost.getSurfaceControl())
- .setColorLayer(true)
+ .setColorLayer()
.setName("Dim Layer for - " + mHost.getName())
.build();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a19721f..ae76740 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -899,7 +899,9 @@
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
- final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession).setOpaque(true);
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
+ .setOpaque(true)
+ .setContainerLayer();
mWindowingLayer = b.setName("Display Root").build();
mOverlayLayer = b.setName("Display Overlays").build();
@@ -4647,7 +4649,7 @@
@Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
SurfaceSession s = child != null ? child.getSession() : getSession();
- final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s);
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
if (child == null) {
return b;
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 543f196..c6b7060 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.IntDef;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
@@ -49,6 +50,8 @@
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Defines the mapping between orientation and rotation of a display.
@@ -96,11 +99,36 @@
private int mUserRotation = Surface.ROTATION_0;
/**
+ * Flag that indicates this is a display that may run better when fixed to user rotation.
+ */
+ private boolean mDefaultFixedToUserRotation;
+
+ /**
+ * No overridden behavior is provided in terms of fixing rotation to user rotation. Use other
+ * flags to derive the default behavior, such as {@link WindowManagerService#mIsPc} and
+ * {@link WindowManagerService#mForceDesktopModeOnExternalDisplays}.
+ */
+ static final int FIXED_TO_USER_ROTATION_DEFAULT = 0;
+ /**
+ * Don't fix display rotation to {@link #mUserRotation} only. Always allow other factors to play
+ * a role in deciding display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_DISABLED = 1;
+ /**
+ * Only use {@link #mUserRotation} as the display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_ENABLED = 2;
+ @IntDef({ FIXED_TO_USER_ROTATION_DEFAULT, FIXED_TO_USER_ROTATION_DISABLED,
+ FIXED_TO_USER_ROTATION_ENABLED })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FixedToUserRotation {}
+
+ /**
* A flag to indicate if the display rotation should be fixed to user specified rotation
* regardless of all other states (including app requrested orientation). {@code true} the
* display rotation should be fixed to user specified rotation, {@code false} otherwise.
*/
- private boolean mFixedToUserRotation;
+ private int mFixedToUserRotation = FIXED_TO_USER_ROTATION_DEFAULT;
private int mDemoHdmiRotation;
private int mDemoRotation;
@@ -220,19 +248,14 @@
PackageManager.FEATURE_LEANBACK);
final boolean isCloseToSquare =
isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
- final boolean forceDefaultOrientationInRes =
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
- final boolean forceDefaultOrienation =
- ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv || isCloseToSquare)
- && forceDefaultOrientationInRes
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- && !"true".equals(SystemProperties.get("config.override_forced_orient"));
- // Configuration says we force to use the default orientation. We can fall back to fix
- // rotation to only user rotation. As long as OEM doesn't change user rotation then the
- // rotation of this display is effectively stuck at 0 deg.
- setFixedToUserRotation(forceDefaultOrienation);
+ final boolean forceDesktopMode =
+ mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay;
+ mDefaultFixedToUserRotation =
+ (isCar || isTv || mService.mIsPc || forceDesktopMode || isCloseToSquare)
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ && !"true".equals(SystemProperties.get("config.override_forced_orient"));
}
private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
@@ -263,7 +286,7 @@
}
void restoreSettings(int userRotationMode, int userRotation,
- boolean fixedToUserRotation) {
+ @FixedToUserRotation int fixedToUserRotation) {
mFixedToUserRotation = fixedToUserRotation;
// We will retrieve user rotation and user rotation mode from settings for default display.
@@ -285,14 +308,13 @@
mUserRotation = userRotation;
}
- void setFixedToUserRotation(boolean fixedToUserRotation) {
+ void setFixedToUserRotation(@FixedToUserRotation int fixedToUserRotation) {
if (mFixedToUserRotation == fixedToUserRotation) {
return;
}
mFixedToUserRotation = fixedToUserRotation;
- mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
- fixedToUserRotation);
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent, fixedToUserRotation);
mService.updateRotation(true /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
@@ -346,7 +368,14 @@
}
boolean isFixedToUserRotation() {
- return mFixedToUserRotation;
+ switch (mFixedToUserRotation) {
+ case FIXED_TO_USER_ROTATION_DISABLED:
+ return false;
+ case FIXED_TO_USER_ROTATION_ENABLED:
+ return true;
+ default:
+ return mDefaultFixedToUserRotation;
+ }
}
/**
@@ -355,7 +384,7 @@
* false} is when {@link #isFixedToUserRotation()} is {@code true}.
*/
boolean respectAppRequestedOrientation() {
- return !mFixedToUserRotation;
+ return !isFixedToUserRotation();
}
public int getLandscapeRotation() {
@@ -461,7 +490,7 @@
* screen is switched off.
*/
private boolean needSensorRunning() {
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
// We are sure we only respect user rotation settings, so we are sure we will not
// support sensor rotation.
return false;
@@ -527,7 +556,7 @@
);
}
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return mUserRotation;
}
@@ -739,7 +768,7 @@
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return false; // Rotation is forced to user settings.
}
@@ -899,7 +928,7 @@
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
- pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
+ pw.println(prefix + " mFixedToUserRotation=" + isFixedToUserRotation());
}
private class OrientationListener extends WindowOrientationListener {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 5cfa7de..4617890 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -80,7 +81,8 @@
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
- private boolean mFixedToUserRotation;
+ private @DisplayRotation.FixedToUserRotation int mFixedToUserRotation =
+ FIXED_TO_USER_ROTATION_DEFAULT;
private Entry(String name) {
mName = name;
@@ -99,7 +101,7 @@
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
&& !mShouldShowIme
- && !mFixedToUserRotation;
+ && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT;
}
}
@@ -188,7 +190,8 @@
writeSettingsIfNeeded(entry, displayInfo);
}
- void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ void setFixedToUserRotation(DisplayContent displayContent,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final Entry entry = getOrCreateEntry(displayInfo);
entry.mFixedToUserRotation = fixedToUserRotation;
@@ -464,8 +467,7 @@
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
- entry.mFixedToUserRotation = getBooleanAttribute(parser,
- "fixedToUserRotation");
+ entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -549,9 +551,9 @@
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
- if (entry.mFixedToUserRotation) {
+ if (entry.mFixedToUserRotation != FIXED_TO_USER_ROTATION_DEFAULT) {
out.attribute(null, "fixedToUserRotation",
- Boolean.toString(entry.mFixedToUserRotation));
+ Integer.toString(entry.mFixedToUserRotation));
}
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 3f77e1c..2b2231a 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -164,7 +164,7 @@
if (mInputSurface == null) {
mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
- .getSession()).setContainerLayer(true)
+ .getSession()).setContainerLayer()
.setName("Drag and Drop Input Consumer").build();
}
final InputWindowHandle h = getInputWindowHandle();
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 4df5a0b..ab95e4b 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -22,13 +22,11 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.view.InputChannel;
-import android.view.WindowManager;
-
import android.view.InputApplicationHandle;
+import android.view.InputChannel;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
-import android.util.Slog;
+import android.view.WindowManager;
import java.io.PrintWriter;
@@ -89,7 +87,7 @@
mWindowHandle.scaleFactor = 1.0f;
mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
- .getSession()).setContainerLayer(true).setName("Input Consumer " + name)
+ .getSession()).setContainerLayer().setName("Input Consumer " + name)
.build();
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index d67193e..f8f693c 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -233,7 +233,7 @@
private void createSurface() {
mSurface = mFactory.get().setName("Letterbox - " + mType)
- .setFlags(HIDDEN).setColorLayer(true).build();
+ .setFlags(HIDDEN).setColorLayer().build();
mSurface.setLayer(-1);
mSurface.setColor(new float[]{0, 0, 0});
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 15478b4..c6c85fd 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -70,7 +70,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.am.ActivityManagerService;
-import com.android.server.wm.TaskRecord.TaskActivitiesReport;
import com.google.android.collect.Sets;
@@ -180,7 +179,6 @@
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
- private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
@VisibleForTesting
RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
@@ -1587,7 +1585,7 @@
*/
ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- tr.fillTaskInfo(rti, mTmpReport);
+ tr.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 34282cd..3bf437d 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -35,8 +35,6 @@
private static final Comparator<TaskRecord> LAST_ACTIVE_TIME_COMPARATOR =
(o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);
- private final TaskRecord.TaskActivitiesReport mTmpReport =
- new TaskRecord.TaskActivitiesReport();
private final TreeSet<TaskRecord> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
@@ -80,7 +78,7 @@
*/
private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
final RunningTaskInfo rti = new RunningTaskInfo();
- task.fillTaskInfo(rti, mTmpReport);
+ task.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.taskId;
return rti;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 84cd8d1..2d5c97f 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -257,7 +257,7 @@
mOriginalWidth = originalWidth;
mOriginalHeight = originalHeight;
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ final SurfaceControl.Transaction t = mService.mTransactionFactory.make();
try {
mSurfaceControl = displayContent.makeOverlay()
.setName("ScreenshotSurface")
@@ -267,13 +267,13 @@
// In case display bounds change, screenshot buffer and surface may mismatch so set a
// scaling mode.
- SurfaceControl.Transaction t2 = new SurfaceControl.Transaction();
+ SurfaceControl.Transaction t2 = mService.mTransactionFactory.make();
t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
t2.apply(true /* sync */);
// Capture a screenshot into the surface we just created.
final int displayId = display.getDisplayId();
- final Surface surface = new Surface();
+ final Surface surface = mService.mSurfaceFactory.make();
surface.copyFrom(mSurfaceControl);
if (mService.mDisplayManagerInternal.screenshot(displayId, surface)) {
t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
diff --git a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl b/services/core/java/com/android/server/wm/SurfaceFactory.java
similarity index 62%
rename from core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
rename to services/core/java/com/android/server/wm/SurfaceFactory.java
index c032cfdb..076b7df 100644
--- a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
+++ b/services/core/java/com/android/server/wm/SurfaceFactory.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
+/*
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,14 @@
* limitations under the License.
*/
-package android.service.contentcapture;
+package com.android.server.wm;
-parcelable ContentCaptureEventsRequest;
+import android.view.Surface;
+
+/**
+ * Helper class to inject custom {@link Surface} objects into window manager.
+ */
+interface SurfaceFactory {
+ Surface make();
+};
+
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index bb3df02..789f987e 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -16,9 +16,11 @@
package com.android.server.wm;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ITaskStackListener;
-import android.app.ActivityManager.TaskDescription;
+import android.app.TaskInfo;
import android.content.ComponentName;
import android.os.Binder;
import android.os.Handler;
@@ -80,11 +82,11 @@
};
private final TaskStackConsumer mNotifyTaskMovedToFront = (l, m) -> {
- l.onTaskMovedToFront(m.arg1);
+ l.onTaskMovedToFront((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyTaskDescriptionChanged = (l, m) -> {
- l.onTaskDescriptionChanged(m.arg1, (TaskDescription) m.obj);
+ l.onTaskDescriptionChanged((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
@@ -92,7 +94,7 @@
};
private final TaskStackConsumer mNotifyTaskRemovalStarted = (l, m) -> {
- l.onTaskRemovalStarted(m.arg1);
+ l.onTaskRemovalStarted((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
@@ -125,7 +127,7 @@
};
private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
- l.onActivityLaunchOnSecondaryDisplayFailed();
+ l.onActivityLaunchOnSecondaryDisplayFailed((RunningTaskInfo) m.obj, m.arg1);
};
private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> {
@@ -344,10 +346,11 @@
msg.sendToTarget();
}
- void notifyActivityLaunchOnSecondaryDisplayFailed() {
+ void notifyActivityLaunchOnSecondaryDisplayFailed(TaskInfo ti, int requestedDisplayId) {
mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
final Message msg = mHandler.obtainMessage(
- NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
+ NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG, requestedDisplayId,
+ 0 /* unused */, ti);
forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
msg.sendToTarget();
}
@@ -366,16 +369,15 @@
msg.sendToTarget();
}
- void notifyTaskMovedToFront(int taskId) {
- final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG,
- taskId, 0 /* unused */);
+ void notifyTaskMovedToFront(TaskInfo ti) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG, ti);
forAllLocalListeners(mNotifyTaskMovedToFront, msg);
msg.sendToTarget();
}
- void notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription) {
+ void notifyTaskDescriptionChanged(TaskInfo taskInfo) {
final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG,
- taskId, 0 /* unused */, taskDescription);
+ taskInfo);
forAllLocalListeners(mNotifyTaskDescriptionChanged, msg);
msg.sendToTarget();
@@ -393,12 +395,10 @@
* the window manager. This allows interested parties to perform relevant animations before
* the window disappears.
*/
- void notifyTaskRemovalStarted(int taskId) {
- final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId,
- 0 /* unused */);
+ void notifyTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskInfo);
forAllLocalListeners(mNotifyTaskRemovalStarted, msg);
msg.sendToTarget();
-
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 9163165..cdcb857 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -83,7 +83,7 @@
final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
if (mInputSurface == null) {
mInputSurface = mService.makeSurfaceBuilder(dc.getSession())
- .setContainerLayer(true)
+ .setContainerLayer()
.setName("Drag and Drop Input Consumer").build();
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 9d3112f..1392762 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -341,6 +341,9 @@
// TODO: remove after unification
Task mTask;
+ /** Used by fillTaskInfo */
+ final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
+
/**
* Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
* ActivityInfo, Intent, TaskDescription)} instead.
@@ -2319,26 +2322,24 @@
/**
* Fills in a {@link TaskInfo} with information from this task.
* @param info the {@link TaskInfo} to fill in
- * @param reuseActivitiesReport a temporary activities report that we can reuse to fetch the
- * running activities
*/
- void fillTaskInfo(TaskInfo info, TaskActivitiesReport reuseActivitiesReport) {
- getNumRunningActivities(reuseActivitiesReport);
+ void fillTaskInfo(TaskInfo info) {
+ getNumRunningActivities(mReuseActivitiesReport);
info.userId = userId;
info.stackId = getStackId();
info.taskId = taskId;
info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
info.isRunning = getTopActivity() != null;
info.baseIntent = new Intent(getBaseIntent());
- info.baseActivity = reuseActivitiesReport.base != null
- ? reuseActivitiesReport.base.intent.getComponent()
+ info.baseActivity = mReuseActivitiesReport.base != null
+ ? mReuseActivitiesReport.base.intent.getComponent()
: null;
- info.topActivity = reuseActivitiesReport.top != null
- ? reuseActivitiesReport.top.mActivityComponent
+ info.topActivity = mReuseActivitiesReport.top != null
+ ? mReuseActivitiesReport.top.mActivityComponent
: null;
info.origActivity = origActivity;
info.realActivity = realActivity;
- info.numActivities = reuseActivitiesReport.numActivities;
+ info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
info.taskDescription = new ActivityManager.TaskDescription(lastTaskDescription);
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
@@ -2346,6 +2347,15 @@
info.configuration.setTo(getConfiguration());
}
+ /**
+ * Returns a {@link TaskInfo} with information from this task.
+ */
+ ActivityManager.RunningTaskInfo getTaskInfo() {
+ ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
+ fillTaskInfo(info);
+ return info;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("userId="); pw.print(userId);
pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 2d3e3ae..938c8b4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -61,12 +61,12 @@
import android.util.Slog;
import android.view.DisplayCutout;
import android.view.IWindowSession;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
-import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index fc95789..241f14e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -832,7 +832,7 @@
updateSurfaceBounds();
if (mAnimationBackgroundSurface == null) {
- mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
+ mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer()
.setName("animation background stackId=" + mStackId)
.build();
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 74fb3fa..dddc6b7 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -50,6 +50,7 @@
import android.view.WindowManager;
import android.view.animation.Animation;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
@@ -700,24 +701,37 @@
mWallpaperTokens.remove(token);
}
+
+ @VisibleForTesting
+ boolean canScreenshotWallpaper() {
+ return canScreenshotWallpaper(getTopVisibleWallpaper());
+ }
+
+ private boolean canScreenshotWallpaper(WindowState wallpaperWindowState) {
+ if (!mService.mPolicy.isScreenOn()) {
+ if (DEBUG_SCREENSHOT) {
+ Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
+ }
+ return false;
+ }
+
+ if (wallpaperWindowState == null) {
+ if (DEBUG_SCREENSHOT) {
+ Slog.i(TAG_WM, "No visible wallpaper to screenshot");
+ }
+ return false;
+ }
+ return true;
+ }
+
/**
* Take a screenshot of the wallpaper if it's visible.
*
* @return Bitmap of the wallpaper
*/
Bitmap screenshotWallpaperLocked() {
- if (!mService.mPolicy.isScreenOn()) {
- if (DEBUG_SCREENSHOT) {
- Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
- }
- return null;
- }
-
final WindowState wallpaperWindowState = getTopVisibleWallpaper();
- if (wallpaperWindowState == null) {
- if (DEBUG_SCREENSHOT) {
- Slog.i(TAG_WM, "No visible wallpaper to screenshot");
- }
+ if (!canScreenshotWallpaper(wallpaperWindowState)) {
return null;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 39df0e4..e19c7c6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -209,6 +209,7 @@
import android.view.IWindowSessionCallback;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InsetsState;
import android.view.KeyEvent;
@@ -814,8 +815,9 @@
SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
+ SurfaceFactory mSurfaceFactory = Surface::new;
- private final SurfaceControl.Transaction mTransaction = mTransactionFactory.make();
+ private final SurfaceControl.Transaction mTransaction;
static void boostPriorityForLockedSection() {
sThreadPriorityBooster.boost();
@@ -909,9 +911,21 @@
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
+ return main(context, im, showBootMsgs, onlyCore, policy, atm,
+ SurfaceControl.Transaction::new);
+ }
+
+ /**
+ * Creates and returns an instance of the WindowManagerService. This call allows the caller
+ * to override the {@link TransactionFactory} to stub functionality under test.
+ */
+ @VisibleForTesting
+ public static WindowManagerService main(final Context context, final InputManagerService im,
+ final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
+ ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
- atm), 0);
+ atm, transactionFactory), 0);
return sInstance;
}
@@ -933,7 +947,7 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm) {
+ ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
installLock(this, INDEX_WINDOW);
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
@@ -962,6 +976,9 @@
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplayWindowSettings = new DisplayWindowSettings(this);
+
+ mTransactionFactory = transactionFactory;
+ mTransaction = mTransactionFactory.make();
mPolicy = policy;
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
@@ -3503,14 +3520,15 @@
}
}
- void setRotateForApp(int displayId, boolean enabled) {
+ void setRotateForApp(int displayId,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
synchronized (mGlobalLock) {
final DisplayContent display = mRoot.getDisplayContent(displayId);
if (display == null) {
Slog.w(TAG, "Trying to set rotate for app for a missing display.");
return;
}
- display.getDisplayRotation().setFixedToUserRotation(enabled);
+ display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation);
}
}
@@ -7403,4 +7421,16 @@
}
}
}
+
+ @Override
+ public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
+ synchronized (mGlobalLock) {
+ mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+ new SurfaceControl.Transaction()
+ .syncInputWindows()
+ .apply(true);
+ }
+
+ return mInputManager.injectInputEvent(ev, mode);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index d13ee45..7384bb7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -342,21 +342,24 @@
arg = getNextArgRequired();
}
- final boolean enabled;
+ final @DisplayRotation.FixedToUserRotation int fixedToUserRotation;
switch (arg) {
case "enabled":
- enabled = true;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
break;
case "disabled":
- enabled = false;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+ break;
+ case "default":
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
break;
default:
- getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
- + arg);
+ getErrPrintWriter().println("Error: expecting enabled, disabled or default, but we "
+ + "get " + arg);
return -1;
}
- mInternal.setRotateForApp(displayId, enabled);
+ mInternal.setRotateForApp(displayId, fixedToUserRotation);
return 0;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 21a557e..ab1b6ae 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -114,6 +114,7 @@
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
+import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT;
import static com.android.server.wm.WindowStateProto.ANIMATOR;
@@ -4777,7 +4778,9 @@
// then we can drop all negative layering on the windowing side and simply inherit
// the default implementation here.
public void assignChildLayers(Transaction t) {
- int layer = 1;
+ // The surface of the main window might be preserved. So the child window on top of the main
+ // window should be also on top of the preserved surface.
+ int layer = PRESERVED_SURFACE_LAYER + 1;
for (int i = 0; i < mChildren.size(); i++) {
final WindowState w = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6b4d6d2..2e2da6d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -75,6 +75,7 @@
class WindowStateAnimator {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
+ static final int PRESERVED_SURFACE_LAYER = 1;
/**
* Mode how the window gets clipped by the stack bounds during an animation: The clipping should
@@ -373,8 +374,8 @@
if (mSurfaceController != null) {
// Our SurfaceControl is always at layer 0 within the parent Surface managed by
// window-state. We want this old Surface to stay on top of the new one
- // until we do the swap, so we place it at layer 1.
- mSurfaceController.mSurfaceControl.setLayer(1);
+ // until we do the swap, so we place it at a positive layer.
+ mSurfaceController.mSurfaceControl.setLayer(PRESERVED_SURFACE_LAYER);
}
mDestroyPreservedSurfaceUponRedraw = true;
mSurfaceDestroyDeferred = true;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 2ee58fe..cc791787 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -85,6 +85,12 @@
return mDeferDepth > 0;
}
+ void performSurfacePlacementIfScheduled() {
+ if (mTraversalScheduled) {
+ performSurfacePlacement();
+ }
+ }
+
final void performSurfacePlacement() {
performSurfacePlacement(false /* force */);
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index d178c3a..fe94168 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2248,7 +2248,7 @@
measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
- measCorrClass, "getSingleSatCorrectionList", "()Ljava.util.List;");
+ measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava.util.List;");
}
jdouble latitudeDegreesCorr = env->CallDoubleMethod(
@@ -2285,15 +2285,15 @@
if (firstGnssMeasurementCorrectionInjected == false) {
jclass singleSatCorrClass = env->GetObjectClass(singleSatCorrectionObj);
method_correctionSatFlags = env->GetMethodID(
- singleSatCorrClass, "getSingleSatCorrectionFlags", "()I");
+ singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
method_correctionSatConstType = env->GetMethodID(
singleSatCorrClass, "getConstellationType", "()I");
method_correctionSatId= env->GetMethodID(
- singleSatCorrClass, "getSatId", "()I");
+ singleSatCorrClass, "getSatelliteId", "()I");
method_correctionSatCarrierFreq = env->GetMethodID(
singleSatCorrClass, "getCarrierFrequencyHz", "()F");
method_correctionSatIsLosProb = env->GetMethodID(
- singleSatCorrClass,"getProbSatIsLos", "()F");
+ singleSatCorrClass,"getProbabilityLineOfSight", "()F");
method_correctionSatEpl = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthMeters", "()F");
method_correctionSatEplUnc = env->GetMethodID(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ae48dad..3070488 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -134,6 +134,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
@@ -171,6 +172,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
+import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
@@ -187,6 +189,7 @@
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.os.storage.StorageManager;
+import android.permission.PermissionControllerManager;
import android.provider.CalendarContract;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
@@ -1890,6 +1893,21 @@
return LocalServices.getService(ActivityTaskManagerInternal.class);
}
+ @NonNull PermissionControllerManager getPermissionControllerManager(
+ @NonNull UserHandle user) {
+ if (user.equals(mContext.getUser())) {
+ return mContext.getSystemService(PermissionControllerManager.class);
+ } else {
+ try {
+ return mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+ user).getSystemService(PermissionControllerManager.class);
+ } catch (NameNotFoundException notPossible) {
+ // not possible
+ throw new IllegalStateException(notPossible);
+ }
+ }
+ }
+
UsageStatsManagerInternal getUsageStatsManagerInternal() {
return LocalServices.getService(UsageStatsManagerInternal.class);
}
@@ -11582,8 +11600,11 @@
}
@Override
- public boolean setPermissionGrantState(ComponentName admin, String callerPackage,
- String packageName, String permission, int grantState) throws RemoteException {
+ public void setPermissionGrantState(ComponentName admin, String callerPackage,
+ String packageName, String permission, int grantState, RemoteCallback callback)
+ throws RemoteException {
+ Preconditions.checkNotNull(callback);
+
UserHandle user = mInjector.binderGetCallingUserHandle();
synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a permission grant state delegate.
@@ -11591,53 +11612,60 @@
DELEGATION_PERMISSION_GRANT);
long ident = mInjector.binderClearCallingIdentity();
try {
- if (getTargetSdk(packageName, user.getIdentifier())
- < android.os.Build.VERSION_CODES.M) {
- return false;
+ boolean isPostQAdmin = getTargetSdk(callerPackage, user.getIdentifier())
+ >= android.os.Build.VERSION_CODES.Q;
+ if (!isPostQAdmin) {
+ // Legacy admins assume that they cannot control pre-M apps
+ if (getTargetSdk(packageName, user.getIdentifier())
+ < android.os.Build.VERSION_CODES.M) {
+ callback.sendResult(null);
+ return;
+ }
}
- if (!isRuntimePermission(permission)) {
- return false;
+ try {
+ if (!isRuntimePermission(permission)) {
+ callback.sendResult(null);
+ return;
+ }
+ } catch (NameNotFoundException e) {
+ throw new RemoteException(
+ "Cannot check if " + permission + "is a runtime permission", e, false,
+ true);
}
- final PackageManager packageManager = mInjector.getPackageManager();
- switch (grantState) {
- case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
- mInjector.getPackageManagerInternal().grantRuntimePermission(packageName,
- permission, user.getIdentifier(), true /* override policy */);
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
- } break;
- case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
- mInjector.getPackageManagerInternal().revokeRuntimePermission(packageName,
- permission, user.getIdentifier(), true /* override policy */);
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
- } break;
+ if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
+ || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
+ || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
+ mInjector.getPermissionControllerManager(user)
+ .setRuntimePermissionGrantStateByDeviceAdmin(callerPackage,
+ packageName, permission, grantState, mContext.getMainExecutor(),
+ (permissionWasSet) -> {
+ if (isPostQAdmin && !permissionWasSet) {
+ callback.sendResult(null);
+ return;
+ }
- case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: {
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, 0, user);
- } break;
+ final boolean isDelegate = (admin == null);
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums
+ .SET_PERMISSION_GRANT_STATE)
+ .setAdmin(callerPackage)
+ .setStrings(permission)
+ .setInt(grantState)
+ .setBoolean(isDelegate)
+ .write();
+
+ callback.sendResult(Bundle.EMPTY);
+ });
}
- } catch (SecurityException se) {
- return false;
- } catch (NameNotFoundException e) {
- return false;
+ } catch (SecurityException e) {
+ Slog.e(LOG_TAG, "Could not set permission grant state", e);
+
+ callback.sendResult(null);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
- final boolean isDelegate = (admin == null);
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.SET_PERMISSION_GRANT_STATE)
- .setAdmin(callerPackage)
- .setStrings(permission)
- .setInt(grantState)
- .setBoolean(isDelegate)
- .write();
- return true;
}
@Override
@@ -11654,8 +11682,26 @@
synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
try {
- int granted = mIPackageManager.checkPermission(permission,
- packageName, user.getIdentifier());
+ int granted;
+ if (getTargetSdk(callerPackage, user.getIdentifier())
+ < android.os.Build.VERSION_CODES.Q) {
+ // The per-Q behavior was to not check the app-ops state.
+ granted = mIPackageManager.checkPermission(permission, packageName,
+ user.getIdentifier());
+ } else {
+ try {
+ int uid = packageManager.getPackageUidAsUser(packageName,
+ user.getIdentifier());
+
+ // TODO: Prevent noting the app-op
+ granted = PermissionChecker.checkPermission(mContext, permission, -1,
+ uid, packageName);
+ } catch (NameNotFoundException e) {
+ throw new RemoteException(
+ "Cannot check if " + permission + "is a runtime permission", e,
+ false, true);
+ }
+ }
int permFlags = packageManager.getPermissionFlags(permission, packageName, user);
if ((permFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED)
!= PackageManager.FLAG_PERMISSION_POLICY_FIXED) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 439a8ca..8d88c5a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -278,6 +278,8 @@
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
private static final String BLOCK_MAP_FILE = "/cache/recovery/block.map";
+ private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
+
// maximum number of binder threads used for system_server
// will be higher than the system default
private static final int sMaxBinderThreads = 31;
@@ -308,6 +310,7 @@
private boolean mOnlyCore;
private boolean mFirstBoot;
+ private final int mStartCount;
private final boolean mRuntimeRestart;
private final long mRuntimeStartElapsedTime;
private final long mRuntimeStartUptime;
@@ -315,6 +318,9 @@
private static final String START_SENSOR_SERVICE = "StartSensorService";
private static final String START_HIDL_SERVICES = "StartHidlServices";
+ private static final String SYSPROP_START_COUNT = "sys.system_server.start_count";
+ private static final String SYSPROP_START_ELAPSED = "sys.system_server.start_elapsed";
+ private static final String SYSPROP_START_UPTIME = "sys.system_server.start_uptime";
private Future<?> mSensorServiceStart;
private Future<?> mZygotePreload;
@@ -344,16 +350,33 @@
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
- // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
- mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
+ // Record process start information.
+ // Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
+ // one for the password screen, second for the actual boot.
+ mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
+
+ // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
+ // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
+ // TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
+ // sys.boot_completed is set. Fix it.
+ mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
private void run() {
try {
traceBeginAndSlog("InitBeforeStartServices");
+
+ // Record the process start information in sys props.
+ SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
+ SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
+ SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
+
+ EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
+ mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
+
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
@@ -1167,7 +1190,8 @@
traceEnd();
final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
- if (hasPdb) {
+ final boolean hasGsi = SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+ if (hasPdb && !hasGsi) {
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
index 5cb6cbb..26b1224 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
@@ -213,7 +213,8 @@
@Override
public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
- int flagValues, int userId) throws RemoteException {
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)
+ throws RemoteException {
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index cf89cb8..aadf924 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -87,6 +87,7 @@
MockSyntheticPasswordManager mSpManager;
IAuthSecret mAuthSecretService;
WindowManagerInternal mMockWindowManager;
+ FakeGsiService mGsiService;
protected boolean mHasSecureLockScreen;
@Override
@@ -101,6 +102,7 @@
mDevicePolicyManager = mock(DevicePolicyManager.class);
mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class);
mMockWindowManager = mock(WindowManagerInternal.class);
+ mGsiService = new FakeGsiService();
LocalServices.removeServiceForTest(LockSettingsInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -137,7 +139,7 @@
mAuthSecretService = mock(IAuthSecret.class);
mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage,
mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
- mSpManager, mAuthSecretService);
+ mSpManager, mAuthSecretService, mGsiService);
when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
installChildProfile(MANAGED_PROFILE_USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java
new file mode 100644
index 0000000..1033163
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 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.locksettings;
+
+public class FakeGsiService {
+ private boolean mIsGsiRunning;
+
+ public boolean isGsiRunning() {
+ return mIsGsiRunning;
+ }
+
+ public void setIsGsiRunning(boolean isGsiRunning) {
+ mIsGsiRunning = isGsiRunning;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index fe683ab..bf71318 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -44,11 +44,12 @@
private IStorageManager mStorageManager;
private SyntheticPasswordManager mSpManager;
private IAuthSecret mAuthSecretService;
+ private FakeGsiService mGsiService;
public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
IActivityManager activityManager, LockPatternUtils lockPatternUtils,
IStorageManager storageManager, SyntheticPasswordManager spManager,
- IAuthSecret authSecretService) {
+ IAuthSecret authSecretService, FakeGsiService gsiService) {
super(context);
mLockSettingsStorage = storage;
mKeyStore = keyStore;
@@ -56,6 +57,7 @@
mLockPatternUtils = lockPatternUtils;
mStorageManager = storageManager;
mSpManager = spManager;
+ mGsiService = gsiService;
}
@Override
@@ -104,17 +106,28 @@
}
@Override
+ public boolean hasBiometrics() {
+ return false;
+ }
+
+ @Override
public int binderGetCallingUid() {
return Process.SYSTEM_UID;
}
+
+ @Override
+ public boolean isGsiRunning() {
+ return mGsiService.isGsiRunning();
+ }
}
protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils,
LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore,
IStorageManager storageManager, IActivityManager mActivityManager,
- SyntheticPasswordManager spManager, IAuthSecret authSecretService) {
+ SyntheticPasswordManager spManager, IAuthSecret authSecretService,
+ FakeGsiService gsiService) {
super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils,
- storageManager, spManager, authSecretService));
+ storageManager, spManager, authSecretService, gsiService));
mGateKeeperService = gatekeeper;
mAuthSecretService = authSecretService;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 0595a5b..89e155e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -554,6 +554,18 @@
assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
}
+ public void testGsiDisablesAuthSecret() throws RemoteException {
+ mGsiService.setIsGsiRunning(true);
+
+ final String password = "testGsiDisablesAuthSecret-password";
+
+ initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
+ }
+
// b/62213311
//TODO: add non-migration work profile case, and unify/un-unify transition.
//TODO: test token after user resets password
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index 50dbaf5..d848b2d 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -16,19 +16,22 @@
package com.android.server.rollback;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.content.rollback.RollbackInfo;
import android.util.IntArray;
import android.util.SparseLongArray;
@@ -42,7 +45,9 @@
import java.io.File;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
@RunWith(JUnit4.class)
public class AppDataRollbackHelperTest {
@@ -55,72 +60,54 @@
// All users are unlocked so we should snapshot data for them.
doReturn(true).when(helper).isUserCredentialLocked(eq(10));
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
- AppDataRollbackHelper.SnapshotAppDataResult result = helper.snapshotAppData("com.foo.bar",
- new int[]{10, 11});
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
+ helper.snapshotAppData(5, info);
- assertEquals(2, result.pendingBackups.size());
- assertEquals(10, result.pendingBackups.get(0));
- assertEquals(11, result.pendingBackups.get(1));
+ assertEquals(2, info.getPendingBackups().size());
+ assertEquals(10, info.getPendingBackups().get(0));
+ assertEquals(11, info.getPendingBackups().get(1));
- assertEquals(0, result.ceSnapshotInodes.size());
+ assertEquals(0, info.getCeSnapshotInodes().size());
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(10), eq(5), eq(Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(11), eq(5), eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
// One of the users is unlocked but the other isn't
doReturn(false).when(helper).isUserCredentialLocked(eq(10));
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
- when(installer.snapshotAppData(anyString(), anyInt(), anyInt())).thenReturn(239L);
+ when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(239L);
- result = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
- assertEquals(1, result.pendingBackups.size());
- assertEquals(11, result.pendingBackups.get(0));
+ PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
+ helper.snapshotAppData(7, info2);
+ assertEquals(1, info2.getPendingBackups().size());
+ assertEquals(11, info2.getPendingBackups().get(0));
- assertEquals(1, result.ceSnapshotInodes.size());
- assertEquals(239L, result.ceSnapshotInodes.get(10));
+ assertEquals(1, info2.getCeSnapshotInodes().size());
+ assertEquals(239L, info2.getCeSnapshotInodes().get(10));
inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(10),
+ eq("com.foo.bar"), eq(10), eq(7),
eq(Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(11), eq(7), eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
}
- private static RollbackData createInProgressRollbackData(String packageName) {
- RollbackData data = new RollbackData(1, new File("/does/not/exist"), -1, true);
- data.packages.add(new PackageRollbackInfo(
- new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1),
- new IntArray(), new ArrayList<>(), false, new IntArray(), new SparseLongArray()));
- data.inProgress = true;
-
- return data;
+ private static PackageRollbackInfo createPackageRollbackInfo(String packageName,
+ final int[] installedUsers) {
+ return new PackageRollbackInfo(
+ new VersionedPackage(packageName, 2), new VersionedPackage(packageName, 1),
+ new IntArray(), new ArrayList<>(), false, IntArray.wrap(installedUsers),
+ new SparseLongArray());
}
- @Test
- public void testRestoreAppDataSnapshot_noRollbackData() throws Exception {
- Installer installer = mock(Installer.class);
- AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
-
- assertFalse(helper.restoreAppData("com.foo", null, 0, 0, 0, "seinfo"));
- verifyZeroInteractions(installer);
- }
-
- @Test
- public void testRestoreAppDataSnapshot_noRollbackInProgress() throws Exception {
- Installer installer = mock(Installer.class);
- AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
-
- RollbackData rd = createInProgressRollbackData("com.foo");
- // Override the in progress flag.
- rd.inProgress = false;
- assertFalse(helper.restoreAppData("com.foo", rd, 0, 0, 0, "seinfo"));
- verifyZeroInteractions(installer);
+ private static PackageRollbackInfo createPackageRollbackInfo(String packageName) {
+ return createPackageRollbackInfo(packageName, new int[] {});
}
@Test
@@ -128,18 +115,20 @@
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
- RollbackData rd = createInProgressRollbackData("com.foo");
- IntArray pendingBackups = rd.packages.get(0).getPendingBackups();
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
+ IntArray pendingBackups = info.getPendingBackups();
pendingBackups.add(10);
pendingBackups.add(11);
- assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ assertTrue(helper.restoreAppData(13 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
+ "seinfo"));
// Should only require FLAG_STORAGE_DE here because we have a pending backup that we
// didn't manage to execute.
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(13) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
assertEquals(1, pendingBackups.size());
@@ -152,16 +141,18 @@
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
doReturn(true).when(helper).isUserCredentialLocked(eq(10));
- RollbackData rd = createInProgressRollbackData("com.foo");
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
- assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ assertTrue(helper.restoreAppData(73 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
+ "seinfo"));
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(73) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
- ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
assertEquals(1, pendingRestores.size());
assertEquals(10, pendingRestores.get(0).userId);
assertEquals(1, pendingRestores.get(0).appId);
@@ -169,21 +160,23 @@
}
@Test
- public void testRestoreAppDataSnapshot_availableBackupForUnockedUser() throws Exception {
+ public void testRestoreAppDataSnapshot_availableBackupForUnlockedUser() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
doReturn(false).when(helper).isUserCredentialLocked(eq(10));
- RollbackData rd = createInProgressRollbackData("com.foo");
- assertFalse(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
+ assertFalse(helper.restoreAppData(101 /* rollbackId */, info, 10 /* userId */,
+ 1 /* appId */, "seinfo"));
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10),
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(101) /* rollbackId */,
eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
inOrder.verifyNoMoreInteractions();
- ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
assertEquals(0, pendingRestores.size());
}
@@ -191,48 +184,99 @@
public void destroyAppData() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
- SparseLongArray ceSnapshotInodes = new SparseLongArray();
- ceSnapshotInodes.put(11, 239L);
- helper.destroyAppDataSnapshot("com.foo.bar", 10, 0L);
- helper.destroyAppDataSnapshot("com.foo.bar", 11, 239L);
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
+ info.putCeSnapshotInode(11, 239L);
+ helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 10 /* userId */);
+ helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 11 /* userId */);
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).destroyAppDataSnapshot(
- eq("com.foo.bar"), eq(10), eq(0L),
- eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(10) /* userId */, eq(0L) /* ceSnapshotInode */,
+ eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).destroyAppDataSnapshot(
- eq("com.foo.bar"), eq(11), eq(239L),
- eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
+ eq("com.foo.bar"), eq(11) /* userId */, eq(239L) /* ceSnapshotInode */,
+ eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
inOrder.verifyNoMoreInteractions();
+
+ assertEquals(0, info.getCeSnapshotInodes().size());
}
@Test
- public void commitPendingBackupAndRestoreForUser_updatesRollbackData() throws Exception {
+ public void commitPendingBackupAndRestoreForUser() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
- ArrayList<RollbackData> changedRollbackData = new ArrayList<>();
- changedRollbackData.add(createInProgressRollbackData("com.foo.bar"));
+ when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(53L);
- when(installer.snapshotAppData(anyString(), anyInt(), anyInt())).thenReturn(239L);
+ // This one should be backed up.
+ PackageRollbackInfo pendingBackup = createPackageRollbackInfo("com.foo", new int[]{37, 73});
+ pendingBackup.addPendingBackup(37);
- ArrayList<String> pendingBackups = new ArrayList<>();
- pendingBackups.add("com.foo.bar");
+ // Nothing should be done for this one.
+ PackageRollbackInfo wasRecentlyRestored = createPackageRollbackInfo("com.bar",
+ new int[]{37, 73});
+ wasRecentlyRestored.addPendingBackup(37);
+ wasRecentlyRestored.getPendingRestores().add(
+ new RestoreInfo(37 /* userId */, 239 /* appId*/, "seInfo"));
- helper.commitPendingBackupAndRestoreForUser(11, pendingBackups,
- new HashMap<>() /* pendingRestores */, changedRollbackData);
+ // This one should be restored
+ PackageRollbackInfo pendingRestore = createPackageRollbackInfo("com.abc",
+ new int[]{37, 73});
+ pendingRestore.putCeSnapshotInode(37, 1543L);
+ pendingRestore.getPendingRestores().add(
+ new RestoreInfo(37 /* userId */, 57 /* appId*/, "seInfo"));
- assertEquals(1, changedRollbackData.size());
- assertEquals(1, changedRollbackData.get(0).packages.size());
- PackageRollbackInfo info = changedRollbackData.get(0).packages.get(0);
+ // This one shouldn't be processed, because it hasn't pending backups/restores for userId
+ // 37.
+ PackageRollbackInfo ignoredInfo = createPackageRollbackInfo("com.bar",
+ new int[]{3, 73});
+ wasRecentlyRestored.addPendingBackup(3);
+ wasRecentlyRestored.addPendingBackup(73);
+ wasRecentlyRestored.getPendingRestores().add(
+ new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
- assertEquals(1, info.getCeSnapshotInodes().size());
- assertEquals(239L, info.getCeSnapshotInodes().get(11));
+ RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1,
+ true);
+ dataWithPendingBackup.packages.add(pendingBackup);
+ RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"),
+ -1, true);
+ dataWithRecentRestore.packages.add(wasRecentlyRestored);
+
+ RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"),
+ -1, true);
+ dataForDifferentUser.packages.add(ignoredInfo);
+
+ RollbackInfo rollbackInfo = new RollbackInfo(17239,
+ Arrays.asList(pendingRestore, wasRecentlyRestored), false);
+
+ List<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37,
+ Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser),
+ Collections.singletonList(rollbackInfo));
InOrder inOrder = Mockito.inOrder(installer);
- inOrder.verify(installer).snapshotAppData("com.foo.bar", 11 /* userId */,
- Installer.FLAG_STORAGE_CE);
+
+ // Check that pending backup and restore for the same package mutually destroyed each other.
+ assertEquals(-1, wasRecentlyRestored.getPendingBackups().indexOf(37));
+ assertNull(wasRecentlyRestored.getRestoreInfo(37));
+
+ // Check that backup was performed.
+ inOrder.verify(installer).snapshotAppData(eq("com.foo"), eq(37), eq(101),
+ eq(Installer.FLAG_STORAGE_CE));
+ assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
+ assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));
+
+ // Check that changed returns correct RollbackData.
+ assertEquals(2, changed.size());
+ assertEquals(dataWithPendingBackup, changed.get(0));
+ assertEquals(dataWithRecentRestore, changed.get(1));
+
+ // Check that restore was performed.
+ inOrder.verify(installer).restoreAppDataSnapshot(
+ eq("com.abc"), eq(57) /* appId */, eq("seInfo"), eq(37) /* userId */,
+ eq(17239) /* rollbackId */, eq(Installer.FLAG_STORAGE_CE));
+ assertNull(pendingRestore.getRestoreInfo(37));
+
inOrder.verifyNoMoreInteractions();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 2627ec7..c072d4e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -59,8 +59,7 @@
public void setUpOnDisplay(DisplayContent dc) {
mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mToken = WindowTestUtils.createTestAppWindowToken(dc);
- mToken.mSkipOnParentChanged = false;
+ mToken = WindowTestUtils.createTestAppWindowToken(dc, false /* skipOnParentChanged */);
mTask.addChild(mToken, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index afadc79..b91f3ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -55,8 +55,11 @@
@Before
public void setUp() throws Exception {
- spyOn(mWm.mRoot);
- doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ synchronized (mWm.mGlobalLock) {
+ // Hold the lock to protect the stubbing from being accessed by other threads.
+ spyOn(mWm.mRoot);
+ doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ }
mDc = mWm.getDefaultDisplayContentLocked();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 108ee180b..e007c86 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -18,7 +18,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.SurfaceControl.Transaction;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -30,6 +29,9 @@
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
import org.junit.Before;
@@ -38,8 +40,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
/**
* Animation related tests for the {@link AppWindowToken} class.
@@ -55,8 +55,6 @@
private TestAppWindowToken mToken;
@Mock
- private Transaction mTransaction;
- @Mock
private AnimationAdapter mSpec;
@Before
@@ -65,7 +63,6 @@
mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* skipOnParentChanged */);
- mToken.setPendingTransaction(mTransaction);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 1dd72ec..2c575f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -60,7 +60,7 @@
* Tests for the {@link AppWindowToken} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:AppWindowTokenTests
+ * atest WmTests:AppWindowTokenTests
*/
@SmallTest
@Presubmit
@@ -76,9 +76,9 @@
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+ mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent,
+ false /* skipOnParentChanged */);
- mToken.mSkipOnParentChanged = false;
mTask.addChild(mToken, 0);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index b1b8e8c..69f7ced 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -621,7 +621,8 @@
@Test
public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
final DisplayContent dc = createNewDisplay();
- dc.getDisplayRotation().setFixedToUserRotation(true);
+ dc.getDisplayRotation().setFixedToUserRotation(
+ DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
? SCREEN_ORIENTATION_PORTRAIT
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 8733674..1c10ffb0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -31,6 +32,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -160,9 +164,7 @@
@Test
public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
freezeRotation(Surface.ROTATION_180);
@@ -187,9 +189,7 @@
@Test
public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
thawRotation();
@@ -203,14 +203,22 @@
public void testPersistsFixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_ENABLED);
reset(mMockDisplayWindowSettings);
- mTarget.setFixedToUserRotation(false);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DISABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DISABLED);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DEFAULT);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DEFAULT);
}
// ========================================
@@ -355,22 +363,7 @@
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
- mTarget.setFixedToUserRotation(true);
- mTarget.updateOrientationListener();
- verifyOrientationListenerRegistration(0);
- }
-
- @Test
- public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
- mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
-
- when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
- when(mMockDisplayPolicy.isAwake()).thenReturn(true);
- when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
- when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
mTarget.updateOrientationListener();
verifyOrientationListenerRegistration(0);
}
@@ -378,8 +371,6 @@
@Test
public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
@@ -393,8 +384,6 @@
@Test
public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
@@ -405,6 +394,19 @@
verifyOrientationListenerRegistration(0);
}
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
private void enableOrientationSensor() {
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
@@ -513,21 +515,8 @@
// Tests for Policy based Rotation
// =================================
@Test
- public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
- mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
-
- assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
- Surface.ROTATION_180));
- }
-
- @Test
public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
@@ -537,8 +526,6 @@
@Test
public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
@@ -546,6 +533,15 @@
}
@Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
public void testReturnsLidOpenRotation_LidOpen() throws Exception {
mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
@@ -591,7 +587,7 @@
mBuilder.build();
configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
freezeRotation(Surface.ROTATION_180);
@@ -625,7 +621,7 @@
@Test
public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
assertFalse("Display rotation shouldn't respect app requested orientation if"
+ " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
@@ -647,9 +643,14 @@
width = 1080;
height = 1920;
break;
+ case SCREEN_ORIENTATION_LOCKED:
+ // We use locked for squared display.
+ width = 1080;
+ height = 1080;
+ break;
default:
- throw new IllegalArgumentException("displayOrientation needs to be either landscape"
- + " or portrait, but we got "
+ throw new IllegalArgumentException("displayOrientation needs to be landscape, "
+ + "portrait or locked, but we got "
+ ActivityInfo.screenOrientationToString(displayOrientation));
}
@@ -659,6 +660,10 @@
.thenReturn(isCar);
when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
.thenReturn(isTv);
+ when(mMockDisplayPolicy.getNonDecorDisplayWidth(anyInt(), anyInt(), anyInt(), anyInt(),
+ any())).thenReturn(width);
+ when(mMockDisplayPolicy.getNonDecorDisplayHeight(anyInt(), anyInt(), anyInt(), anyInt(),
+ any())).thenReturn(height);
final int shortSizeDp = (isCar || isTv) ? 540 : 720;
final int longSizeDp = 960;
@@ -826,6 +831,9 @@
.thenReturn(convertRotationToDegrees(mDeskDockRotation));
when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
.thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+ when(mMockRes.getFloat(
+ com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio))
+ .thenReturn(1.33f);
mMockSensorManager = mock(SensorManager.class);
when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 992d017..2dad187 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -26,6 +26,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -407,7 +410,7 @@
}
@Test
- public void testNotFixedToUserRotationByDefault() {
+ public void testFixedToUserRotationDefault() {
mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
Surface.ROTATION_0);
@@ -419,13 +422,14 @@
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DEFAULT));
mockitoSession.finishMocking();
}
@Test
- public void testSetFixedToUserRotation() {
- mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+ public void testSetFixedToUserRotationDisabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_DISABLED);
final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
.startMocking();
@@ -435,7 +439,25 @@
applySettingsToDisplayByNewInstance(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DISABLED));
+ mockitoSession.finishMocking();
+ }
+
+ @Test
+ public void testSetFixedToUserRotationEnabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_ENABLED);
+
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .startMocking();
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ spyOn(mPrimaryDisplay);
+ doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_ENABLED));
mockitoSession.finishMocking();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java b/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java
new file mode 100644
index 0000000..66139e6
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 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.mockito.Mockito.mock;
+
+import android.view.SurfaceControl;
+
+/**
+ * Stubbed {@link SurfaceControl.Builder} class that returns a mocked SurfaceControl instance
+ * that can be used for unit testing.
+ */
+class MockSurfaceControlBuilder extends SurfaceControl.Builder {
+ @Override
+ public SurfaceControl.Builder setParent(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl build() {
+ return mock(SurfaceControl.class);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
new file mode 100644
index 0000000..d919fc8
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 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.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.InputWindowHandle;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+/**
+ * Stubbed {@link android.view.SurfaceControl.Transaction} class that can be used when unit
+ * testing to avoid calls to native code.
+ */
+public class StubTransaction extends SurfaceControl.Transaction {
+ @Override
+ public void apply() {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void apply(boolean sync) {
+ }
+
+ @Override
+ public SurfaceControl.Transaction setVisibility(SurfaceControl sc, boolean visible) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction show(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction hide(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setPosition(SurfaceControl sc, float x, float y) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setBufferSize(SurfaceControl sc,
+ int w, int h) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayer(SurfaceControl sc, int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo,
+ int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setTransparentRegionHint(SurfaceControl sc,
+ Region transparentRegion) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAlpha(SurfaceControl sc, float alpha) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setInputWindowInfo(SurfaceControl sc,
+ InputWindowHandle handle) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction transferTouchFocus(IBinder fromToken, IBinder toToken) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setGeometry(SurfaceControl sc, Rect sourceCrop,
+ Rect destFrame, @Surface.Rotation int orientation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc,
+ float dsdx, float dtdx, float dtdy, float dsdy) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorTransform(SurfaceControl sc, float[] matrix,
+ float[] translation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle,
+ long frameNumber) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction deferTransactionUntilSurface(SurfaceControl sc,
+ Surface barrierSurface,
+ long frameNumber) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction reparentChildren(SurfaceControl sc, IBinder newParentHandle) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction reparent(SurfaceControl sc, SurfaceControl newParent) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction detachChildren(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setOverrideScalingMode(SurfaceControl sc,
+ int overrideScalingMode) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColor(SurfaceControl sc, float[] color) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setGeometryAppliesWithResize(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setSecure(SurfaceControl sc, boolean isSecure) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayProjection(IBinder displayToken,
+ int orientation, Rect layerStackRect, Rect displayRect) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySize(IBinder displayToken, int width, int height) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAnimationTransaction() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setEarlyWakeup() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(int key, int data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(int key, Parcel data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction merge(SurfaceControl.Transaction other) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction remove(SurfaceControl sc) {
+ return this;
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 712cd1e..366acea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -167,7 +167,7 @@
mWindowManagerPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
mWindowManagerService = WindowManagerService.main(
- context, ims, false, false, mWindowManagerPolicy, atms);
+ context, ims, false, false, mWindowManagerPolicy, atms, StubTransaction::new);
mWindowManagerService.onInitReady();
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 388f98f..5d07888 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -38,6 +38,7 @@
import static org.mockito.Mockito.mock;
import android.app.ActivityManager;
+import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -109,8 +110,7 @@
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());
+ final TaskInfo info = task.getTaskInfo();
// The intent of info should be a copy so assert that they are different instances.
assertThat(info.baseIntent, not(sameInstance(task.getBaseIntent())));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index d07230e..6249bde 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -21,11 +21,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNull;
-
-import android.graphics.Bitmap;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
@@ -37,7 +35,7 @@
* Tests for the {@link WallpaperController} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WallpaperControllerTests
+ * atest WmTests:WallpaperControllerTests
*/
@SmallTest
@Presubmit
@@ -49,34 +47,29 @@
synchronized (mWm.mGlobalLock) {
// No wallpaper
final DisplayContent dc = createNewDisplay();
- Bitmap wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// No wallpaper WSA Surface
WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
true, dc, true /* ownerCanManageAppTokens */);
WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER,
wallpaperWindowToken, "wallpaperWindow");
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// Wallpaper with not visible WSA surface.
wallpaperWindow.mWinAnimator.mSurfaceController = windowSurfaceController;
wallpaperWindow.mWinAnimator.mLastAlpha = 1;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
when(windowSurfaceController.getShown()).thenReturn(true);
// Wallpaper with WSA alpha set to 0.
wallpaperWindow.mWinAnimator.mLastAlpha = 0;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// Wallpaper window with WSA Surface
wallpaperWindow.mWinAnimator.mLastAlpha = 1;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNotNull(wallpaperBitmap);
+ assertTrue(dc.mWallpaperController.canScreenshotWallpaper());
}
}
}
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 5bfa0c6..da1defa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -28,7 +28,6 @@
import android.os.IBinder;
import android.view.IApplicationToken;
import android.view.IWindow;
-import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
/**
@@ -72,7 +71,6 @@
static class TestAppWindowToken extends AppWindowToken {
boolean mOnTop = false;
private boolean mSkipPrepareSurfaces;
- private Transaction mPendingTransactionOverride;
boolean mSkipOnParentChanged = true;
private TestAppWindowToken(DisplayContent dc, boolean skipOnParentChanged) {
@@ -126,17 +124,6 @@
void setSkipPrepareSurfaces(boolean ignore) {
mSkipPrepareSurfaces = ignore;
}
-
- void setPendingTransaction(Transaction transaction) {
- mPendingTransactionOverride = transaction;
- }
-
- @Override
- public Transaction getPendingTransaction() {
- return mPendingTransactionOverride == null
- ? super.getPendingTransaction()
- : mPendingTransactionOverride;
- }
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 0d7d085..d202e16 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -37,7 +37,10 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+
+import static org.mockito.Mockito.mock;
+
import android.content.Context;
import android.content.res.Configuration;
@@ -47,6 +50,8 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IWindow;
+import android.view.Surface;
+import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
import com.android.server.AttributeCache;
@@ -96,10 +101,9 @@
private MockTracker mMockTracker;
/**
- * To restore the original SurfaceControl.Transaction factory if any tests changed
- * {@link WindowManagerService#mTransactionFactory}.
+ * Spied {@link Transaction} class than can be used to verify calls.
*/
- private TransactionFactory mOriginalTransactionFactory;
+ Transaction mTransaction;
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -129,11 +133,21 @@
// in the set up are clear. This can be removed when b/37850063 is fixed.
try {
mMockSession = mock(Session.class);
+ mTransaction = spy(StubTransaction.class);
final Context context = getInstrumentation().getTargetContext();
mWm = mSystemServicesTestRule.getWindowManagerService();
- mOriginalTransactionFactory = mWm.mTransactionFactory;
+
+ // Setup factory classes to prevent calls to native code.
+
+ // Return a spied Transaction class than can be used to verify calls.
+ mWm.mTransactionFactory = () -> mTransaction;
+ // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
+ mWm.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
+ // Return mocked Surface instances.
+ mWm.mSurfaceFactory = () -> mock(Surface.class);
+
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
@@ -183,7 +197,6 @@
// stable state to clean up for consistency.
waitUntilHandlersIdle();
- mWm.mTransactionFactory = mOriginalTransactionFactory;
final LinkedList<WindowState> nonCommonWindows = new LinkedList<>();
synchronized (mWm.mGlobalLock) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index f3b8a62..2907021 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -23,15 +23,20 @@
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.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER;
+
import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.Presubmit;
@@ -44,6 +49,7 @@
import org.junit.After;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -404,6 +410,28 @@
assertWindowHigher(mediaOverlayChild, child);
}
+ @Test
+ public void testAssignWindowLayers_ForPostivelyZOrderedSubtype() {
+ final WindowState anyWindow = createWindow("anyWindow");
+ final ArrayList<WindowState> childList = new ArrayList<>();
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_PANEL, mDisplayContent,
+ "TypeApplicationPanelChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_SUB_PANEL, mDisplayContent,
+ "TypeApplicationSubPanelChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_ATTACHED_DIALOG, mDisplayContent,
+ "TypeApplicationAttachedDialogChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_ABOVE_SUB_PANEL, mDisplayContent,
+ "TypeApplicationAboveSubPanelPanelChild"));
+
+ final LayerRecordingTransaction t = mTransaction;
+ mDisplayContent.assignChildLayers(t);
+
+ for (int i = childList.size() - 1; i >= 0; i--) {
+ assertThat(t.getLayer(childList.get(i).getSurfaceControl()))
+ .isGreaterThan(PRESERVED_SURFACE_LAYER);
+ }
+ }
+
@FlakyTest(bugId = 124088319)
@Test
public void testDockedDividerPosition() {
diff --git a/telecomm/java/android/telecom/CallIdentification.java b/telecomm/java/android/telecom/CallIdentification.java
index 87834fd..cde7f60 100644
--- a/telecomm/java/android/telecom/CallIdentification.java
+++ b/telecomm/java/android/telecom/CallIdentification.java
@@ -45,13 +45,13 @@
* {@link CallIdentification} for a screened call.
*/
public static class Builder {
- private String mName;
- private String mDescription;
- private String mDetails;
+ private CharSequence mName;
+ private CharSequence mDescription;
+ private CharSequence mDetails;
private Icon mPhoto;
private int mNuisanceConfidence = CallIdentification.CONFIDENCE_UNKNOWN;
private String mPackageName;
- private String mAppName;
+ private CharSequence mAppName;
/**
* Default builder constructor.
@@ -67,7 +67,7 @@
* @param callIdAppName The app name.
* @hide
*/
- public Builder(String callIdPackageName, String callIdAppName) {
+ public Builder(String callIdPackageName, CharSequence callIdAppName) {
mPackageName = callIdPackageName;
mAppName = callIdAppName;
}
@@ -80,7 +80,7 @@
* @param name The name associated with the call, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setName(@Nullable String name) {
+ public Builder setName(@Nullable CharSequence name) {
mName = name;
return this;
}
@@ -97,7 +97,7 @@
* @param description The call description, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setDescription(@Nullable String description) {
+ public Builder setDescription(@Nullable CharSequence description) {
mDescription = description;
return this;
}
@@ -114,7 +114,7 @@
* @param details The call details, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setDetails(@Nullable String details) {
+ public Builder setDetails(@Nullable CharSequence details) {
mDetails = details;
return this;
}
@@ -241,10 +241,10 @@
* call identification.
* @hide
*/
- private CallIdentification(@Nullable String name, @Nullable String description,
- @Nullable String details, @Nullable Icon photo,
+ private CallIdentification(@Nullable CharSequence name, @Nullable CharSequence description,
+ @Nullable CharSequence details, @Nullable Icon photo,
@NuisanceConfidence int nuisanceConfidence, @NonNull String callScreeningPackageName,
- @NonNull String callScreeningAppName) {
+ @NonNull CharSequence callScreeningAppName) {
mName = name;
mDescription = description;
mDetails = details;
@@ -254,13 +254,13 @@
mCallScreeningPackageName = callScreeningPackageName;
}
- private String mName;
- private String mDescription;
- private String mDetails;
+ private CharSequence mName;
+ private CharSequence mDescription;
+ private CharSequence mDetails;
private Icon mPhoto;
private int mNuisanceConfidence;
private String mCallScreeningPackageName;
- private String mCallScreeningAppName;
+ private CharSequence mCallScreeningAppName;
@Override
public int describeContents() {
@@ -269,13 +269,13 @@
@Override
public void writeToParcel(Parcel parcel, int i) {
- parcel.writeString(mName);
- parcel.writeString(mDescription);
- parcel.writeString(mDetails);
+ parcel.writeCharSequence(mName);
+ parcel.writeCharSequence(mDescription);
+ parcel.writeCharSequence(mDetails);
parcel.writeParcelable(mPhoto, 0);
parcel.writeInt(mNuisanceConfidence);
parcel.writeString(mCallScreeningPackageName);
- parcel.writeString(mCallScreeningAppName);
+ parcel.writeCharSequence(mCallScreeningAppName);
}
/**
@@ -286,13 +286,13 @@
@Override
public CallIdentification createFromParcel(Parcel source) {
- String name = source.readString();
- String description = source.readString();
- String details = source.readString();
+ CharSequence name = source.readCharSequence();
+ CharSequence description = source.readCharSequence();
+ CharSequence details = source.readCharSequence();
Icon photo = source.readParcelable(ClassLoader.getSystemClassLoader());
int nuisanceConfidence = source.readInt();
String callScreeningPackageName = source.readString();
- String callScreeningAppName = source.readString();
+ CharSequence callScreeningAppName = source.readCharSequence();
return new CallIdentification(name, description, details, photo,
nuisanceConfidence, callScreeningPackageName, callScreeningAppName);
}
@@ -311,7 +311,7 @@
*
* @return The name associated with the number, or {@code null} if none was provided.
*/
- public final @Nullable String getName() {
+ public final @Nullable CharSequence getName() {
return mName;
}
@@ -325,7 +325,7 @@
*
* @return The call description, or {@code null} if none was provided.
*/
- public final @Nullable String getDescription() {
+ public final @Nullable CharSequence getDescription() {
return mDescription;
}
@@ -340,7 +340,7 @@
*
* @return The call details, or {@code null} if none was provided.
*/
- public final @Nullable String getDetails() {
+ public final @Nullable CharSequence getDetails() {
return mDetails;
}
@@ -363,8 +363,7 @@
*
* @return The nuisance confidence.
*/
- public final @NuisanceConfidence
- int getNuisanceConfidence() {
+ public final @NuisanceConfidence int getNuisanceConfidence() {
return mNuisanceConfidence;
}
@@ -387,7 +386,7 @@
*
* @return The name of the app.
*/
- public final @NonNull String getCallScreeningAppName() {
+ public final @NonNull CharSequence getCallScreeningAppName() {
return mCallScreeningAppName;
}
@@ -407,7 +406,7 @@
* @param callScreeningAppName The app name.
* @hide
*/
- public void setCallScreeningAppName(@NonNull String callScreeningAppName) {
+ public void setCallScreeningAppName(@NonNull CharSequence callScreeningAppName) {
mCallScreeningAppName = callScreeningAppName;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ad98e36..c0444bb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2992,9 +2992,9 @@
/* Default value is 1024 kbps */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024);
/* Default value is 10 seconds */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
/* Default value is 10 seconds. */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a1aee6d..3dc1199 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1569,6 +1569,17 @@
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @TelephonyManager.NetworkType int getDataNetworkType() {
+ final NetworkRegistrationState iwlanRegState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WLAN);
+ if (iwlanRegState != null
+ && iwlanRegState.getRegState() == NetworkRegistrationState.REG_STATE_HOME) {
+ // If the device is on IWLAN, return IWLAN as the network type. This is to simulate the
+ // behavior of legacy mode device. In the future caller should use
+ // getNetworkRegistrationState() to retrieve the actual data network type on cellular
+ // or on IWLAN.
+ return iwlanRegState.getAccessNetworkTechnology();
+ }
+
final NetworkRegistrationState regState = getNetworkRegistrationState(
NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
if (regState != null) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 94f26a8..c28d1fb 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2081,7 +2081,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subId = iSub.getActiveSubIdList();
+ subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
}
} catch (RemoteException ex) {
// ignore it
@@ -2866,7 +2866,7 @@
*
* @hide
*/
- private boolean shouldHideSubscription(SubscriptionInfo info) {
+ public boolean shouldHideSubscription(SubscriptionInfo info) {
if (info == null) return false;
// If hasCarrierPrivileges or canManageSubscription returns true, it means caller
@@ -2874,8 +2874,14 @@
boolean hasCarrierPrivilegePermission = (info.isEmbedded() && canManageSubscription(info))
|| TelephonyManager.from(mContext).hasCarrierPrivileges(info.getSubscriptionId());
- return (!TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic()
- && !hasCarrierPrivilegePermission);
+ return isInvisibleSubscription(info) && !hasCarrierPrivilegePermission;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean isInvisibleSubscription(SubscriptionInfo info) {
+ return info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic();
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0b72679..f1869b0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10306,24 +10306,25 @@
/**
* Returns if the usage of multiple SIM cards at the same time to register on the network
- * (e.g. Dual Standby or Dual Active) is restricted.
+ * (e.g. Dual Standby or Dual Active) is supported by the device and by the carrier.
*
- * @return true if usage of multiple SIMs is restricted, false otherwise.
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @hide
+ * @return true if usage of multiple SIMs is supported, false otherwise.
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isMultisimCarrierRestricted() {
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isMultisimSupported() {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultisimCarrierRestricted();
+ return service.isMultisimSupported(getOpPackageName());
}
} catch (RemoteException e) {
- Log.e(TAG, "isMultisimCarrierRestricted RemoteException", e);
+ Log.e(TAG, "isMultisimSupported RemoteException", e);
}
- return true;
+ return false;
}
/**
@@ -10338,8 +10339,8 @@
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void switchMultiSimConfig(int numOfSims) {
//only proceed if multi-sim is not restricted
- if (isMultisimCarrierRestricted()) {
- Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted.");
+ if (!isMultisimSupported()) {
+ Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted or not supported.");
return;
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 75a4d82..79e0aa1 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -275,7 +275,7 @@
void clearDefaultsForInactiveSubIds();
- int[] getActiveSubIdList();
+ int[] getActiveSubIdList(boolean visibleOnly);
int setSubscriptionProperty(int subId, String propKey, String propValue);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c54a606..d183837 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1834,10 +1834,12 @@
void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted);
/**
- * Returns if the usage of multiple SIM cards at the same time is restricted.
- * @hide
+ * Returns if the usage of multiple SIM cards at the same time is supported.
+ *
+ * @param callingPackage The package making the call.
+ * @return true if multisim is supported, false otherwise.
*/
- boolean isMultisimCarrierRestricted();
+ boolean isMultisimSupported(String callingPackage);
/**
* Switch configs to enable multi-sim or switch back to single-sim
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 603c4c2..030c3f4 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -188,18 +188,17 @@
*/
static final String PROPERTY_IGNORE_NITZ = "telephony.test.ignore.nitz";
- /**
+ /**
* Property to set multi sim feature.
* Type: String(dsds, dsda)
*/
static final String PROPERTY_MULTI_SIM_CONFIG = "persist.radio.multisim.config";
- /**
+ /**
* Property to indicate if reboot is required when changing modems configurations
* Type: String(true, false) default is false; most devices don't need reboot
*/
- String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE =
- "persist.radio.reboot_on_modem_change";
+ String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE = "persist.radio.reboot_on_modem_change";
/**
* Property to store default subscription.
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index 0cb8f22..6765316 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -1,6 +1,10 @@
// Signature format: 2.0
package android.test.mock {
+ public class MockContext extends android.content.Context {
+ method public android.view.Display getDisplay();
+ }
+
@Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
method public boolean arePermissionsIndividuallyControlled();
method public String getDefaultBrowserPackageNameAsUser(int);
diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk
index 0967ad3..9e5d8ce 100644
--- a/tests/RollbackTest/Android.mk
+++ b/tests/RollbackTest/Android.mk
@@ -76,13 +76,13 @@
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
LOCAL_COMPATIBILITY_SUITE := general-tests
-LOCAL_COMPATIBILITY_SUPPORT_FILES := $(ROLLBACK_TEST_APEX_V1)
LOCAL_JAVA_RESOURCE_FILES := \
$(ROLLBACK_TEST_APP_AV1) \
$(ROLLBACK_TEST_APP_AV2) \
$(ROLLBACK_TEST_APP_A_CRASHING_V2) \
$(ROLLBACK_TEST_APP_BV1) \
$(ROLLBACK_TEST_APP_BV2) \
+ $(ROLLBACK_TEST_APEX_V1) \
$(ROLLBACK_TEST_APEX_V2)
LOCAL_MANIFEST_FILE := RollbackTest/AndroidManifest.xml
LOCAL_SDK_VERSION := system_current
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index f3edf09..bd0881f 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -587,9 +587,13 @@
RollbackTestUtils.installMultiPackage(false,
"RollbackTestAppAv1.apk",
"RollbackTestAppBv1.apk");
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
RollbackTestUtils.installMultiPackage(true,
"RollbackTestAppAv2.apk",
"RollbackTestAppBv2.apk");
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
@@ -614,6 +618,9 @@
assertRollbackInfoForAandB(rollbackB);
assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId());
+
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
} finally {
RollbackTestUtils.dropShellPermissionIdentity();
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index 280ee1d..097d33d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -66,7 +66,7 @@
Context context = InstrumentationRegistry.getContext();
PackageManager pm = context.getPackageManager();
try {
- PackageInfo info = pm.getPackageInfo(packageName, 0);
+ PackageInfo info = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
return info.getLongVersionCode();
} catch (PackageManager.NameNotFoundException e) {
return -1;
@@ -142,7 +142,7 @@
session = packageInstaller.openSession(sessionId);
ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
InputStream is = loader.getResourceAsStream(resourceName);) {
byte[] buffer = new byte[4096];
int n;
@@ -168,7 +168,8 @@
}
/**
- * Installs the apks with the given resource names as an atomic set.
+ * Installs the APKs or APEXs with the given resource names as an atomic
+ * set. A resource is assumed to be an APEX if it has the .apex extension.
* <p>
* In case of staged installs, this function will return succesfully after
* the staged install has been committed and is ready for the device to
@@ -206,6 +207,9 @@
if (staged) {
params.setStaged();
}
+ if (resourceName.endsWith(".apex")) {
+ params.setInstallAsApex();
+ }
if (enableRollback) {
params.setEnableRollback();
}
@@ -213,7 +217,7 @@
session = packageInstaller.openSession(sessionId);
ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
InputStream is = loader.getResourceAsStream(resourceName);) {
byte[] buffer = new byte[4096];
int n;
@@ -247,7 +251,9 @@
}
/**
- * Installs the apks with the given resource names as a staged atomic set.
+ * Installs the APKs or APEXs with the given resource names as a staged
+ * atomic set. A resource is assumed to be an APEX if it has the .apex
+ * extension.
*
* @param enableRollback if rollback should be enabled.
* @param resourceNames names of the class loader resource for the apks to
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 297bf86..b65917b 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.After;
@@ -46,6 +47,11 @@
private static final String TAG = "RollbackTest";
private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
+ private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
+ private static final String TEST_APEX_V1 =
+ "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
+ private static final String TEST_APEX_V2 =
+ "com.android.tests.rollback.testapex.RollbackTestApexV2.apex";
/**
* Adopts common shell permissions needed for rollback tests.
@@ -68,10 +74,11 @@
/**
- * Test basic rollbacks. Enable rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Enable rollback phase.
*/
@Test
- public void testBasicEnableRollback() throws Exception {
+ public void testApkOnlyEnableRollback() throws Exception {
RollbackTestUtils.uninstall(TEST_APP_A);
assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
@@ -81,14 +88,15 @@
RollbackTestUtils.installStaged(true, "RollbackTestAppAv2.apk");
// At this point, the host test driver will reboot the device and run
- // testBasicCommitRollback().
+ // testApkOnlyCommitRollback().
}
/**
- * Test basic rollbacks. Commit rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Commit rollback phase.
*/
@Test
- public void testBasicCommitRollback() throws Exception {
+ public void testApkOnlyCommitRollback() throws Exception {
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackManager rm = RollbackTestUtils.getRollbackManager();
@@ -111,14 +119,15 @@
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
// At this point, the host test driver will reboot the device and run
- // testBasicConfirmRollback().
+ // testApkOnlyConfirmRollback().
}
/**
- * Test basic rollbacks. Confirm rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Confirm rollback phase.
*/
@Test
- public void testBasicConfirmRollback() throws Exception {
+ public void testApkOnlyConfirmRollback() throws Exception {
assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackManager rm = RollbackTestUtils.getRollbackManager();
@@ -128,4 +137,83 @@
assertTrue(rollback.isStaged());
assertNotEquals(-1, rollback.getCommittedSessionId());
}
+
+ /**
+ * Test rollbacks of staged installs involving only apex.
+ * Prepare apex phase.
+ */
+ @Test
+ public void testApexOnlyPrepareApex() throws Exception {
+ // Note: We can't uninstall the apex if it is already on device,
+ // because that isn't supported yet (b/123667725). As long as nothing
+ // is failing, this should be fine because we don't expect the tests
+ // to leave the device with v2 of the apex installed.
+ RollbackTestUtils.installStaged(false, TEST_APEX_V1);
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyEnableRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apex.
+ * Enable rollback phase.
+ */
+ @Test
+ public void testApexOnlyEnableRollback() throws Exception {
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+ RollbackTestUtils.installStaged(true, TEST_APEX_V2);
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyCommitRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apks.
+ * Commit rollback phase.
+ */
+ @Test
+ public void testApexOnlyCommitRollback() throws Exception {
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APEX_PKG);
+ assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, rollback);
+ assertTrue(rollback.isStaged());
+
+ RollbackTestUtils.rollback(rollback.getRollbackId());
+
+ // Note: We can't use getUniqueRollbackInfoForPackage for the apex,
+ // because we can't uninstall the apex (b/123667725), which means
+ // there's no way to clear info about rollbacks from previous tests
+ // run on the device. Look up the info by rollback id instead.
+ RollbackInfo committed = null;
+ for (RollbackInfo info : rm.getRecentlyCommittedRollbacks()) {
+ if (info.getRollbackId() == rollback.getRollbackId()) {
+ assertNull(committed);
+ committed = info;
+ break;
+ }
+ }
+ assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
+ assertTrue(committed.isStaged());
+ assertNotEquals(-1, committed.getCommittedSessionId());
+
+ RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
+
+ // The apex should not be rolled back until after reboot.
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyConfirmRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apks.
+ * Confirm rollback phase.
+ */
+ @Test
+ public void testApexOnlyConfirmRollback() throws Exception {
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+ }
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 6cb0dd0..24a51dc 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -34,7 +34,7 @@
* Runs the given phase of a test by calling into the device.
* Throws an exception if the test phase fails.
* <p>
- * For example, <code>runPhase("testBasicEnableRollback");</code>
+ * For example, <code>runPhase("testApkOnlyEnableRollback");</code>
*/
private void runPhase(String phase) throws Exception {
assertTrue(runDeviceTests("com.android.tests.rollback",
@@ -43,14 +43,28 @@
}
/**
- * Tests staged rollbacks.
+ * Tests staged rollbacks involving only apks.
*/
@Test
- public void testBasic() throws Exception {
- runPhase("testBasicEnableRollback");
+ public void testApkOnly() throws Exception {
+ runPhase("testApkOnlyEnableRollback");
getDevice().reboot();
- runPhase("testBasicCommitRollback");
+ runPhase("testApkOnlyCommitRollback");
getDevice().reboot();
- runPhase("testBasicConfirmRollback");
+ runPhase("testApkOnlyConfirmRollback");
+ }
+
+ /**
+ * Tests staged rollbacks involving only apex.
+ */
+ @Test
+ public void testApexOnly() throws Exception {
+ runPhase("testApexOnlyPrepareApex");
+ getDevice().reboot();
+ runPhase("testApexOnlyEnableRollback");
+ getDevice().reboot();
+ runPhase("testApexOnlyCommitRollback");
+ getDevice().reboot();
+ runPhase("testApexOnlyConfirmRollback");
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a10fb4e..ed524f6 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -154,6 +154,7 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.net.VpnConfig;
import com.android.internal.util.ArrayUtils;
@@ -748,6 +749,10 @@
// mExpectations is non-empty.
private boolean mExpectingAdditions;
+ // Used to collect the networks requests managed by this factory. This is a duplicate of
+ // the internal information stored in the NetworkFactory (which is private).
+ private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
+
public MockNetworkFactory(Looper looper, Context context, String logTag,
NetworkCapabilities filter) {
super(looper, context, logTag, filter);
@@ -800,6 +805,7 @@
}
// Add the request.
+ mNetworkRequests.put(request.requestId, request);
super.handleAddRequest(request, score, factorySerialNumber);
mExpectations.notify();
}
@@ -817,11 +823,17 @@
}
// Remove the request.
+ mNetworkRequests.remove(request.requestId);
super.handleRemoveRequest(request);
mExpectations.notify();
}
}
+ // Trigger releasing the request as unfulfillable
+ public void triggerUnfulfillable(NetworkRequest r) {
+ super.releaseRequestAsUnfulfillableByAnyFactory(r);
+ }
+
private void assertNoExpectations() {
if (mExpectations.size() != 0) {
fail("Can't add expectation, " + mExpectations.size() + " already pending");
@@ -861,9 +873,11 @@
assertEquals(msg, 0, count);
}
- public void waitForNetworkRequests(final int count) throws InterruptedException {
+ public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
+ throws InterruptedException {
waitForRequests();
assertEquals(count, getMyRequestCount());
+ return mNetworkRequests;
}
}
@@ -3533,6 +3547,55 @@
networkCallback.assertNoCallback();
}
+ /**
+ * Validate the callback flow for a factory releasing a request as unfulfillable.
+ */
+ @Test
+ public void testUnfulfillableNetworkRequest() throws Exception {
+ NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
+ NetworkCapabilities.TRANSPORT_WIFI).build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+
+ final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
+ handlerThread.start();
+ NetworkCapabilities filter = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET);
+ final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "testFactory", filter);
+ testFactory.setScoreFilter(40);
+
+ // Register the factory and expect it to receive the default request.
+ testFactory.expectAddRequestsWithScores(0);
+ testFactory.register();
+ SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
+
+ assertEquals(1, requests.size()); // have 1 request at this point
+ int origRequestId = requests.valueAt(0).requestId;
+
+ // Now file the test request and expect it.
+ testFactory.expectAddRequestsWithScores(0);
+ mCm.requestNetwork(nr, networkCallback);
+ requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
+
+ int newRequestId = 0;
+ for (int i = 0; i < requests.size(); ++i) {
+ if (requests.valueAt(i).requestId != origRequestId) {
+ newRequestId = requests.valueAt(i).requestId;
+ break;
+ }
+ }
+
+ // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
+ testFactory.expectRemoveRequests(1);
+ testFactory.triggerUnfulfillable(requests.get(newRequestId));
+ networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+ testFactory.waitForRequests();
+
+ testFactory.unregister();
+ handlerThread.quit();
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index f31f771..56a242f 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -128,13 +128,11 @@
}
case FILETYPE_VIRTUALKEYDEFINITION: {
- VirtualKeyMap* map;
- status_t status = VirtualKeyMap::load(filename, &map);
- if (status) {
- error("Error %d parsing virtual key definition file.\n\n", status);
+ std::unique_ptr<VirtualKeyMap> map = VirtualKeyMap::load(filename);
+ if (!map) {
+ error("Error while parsing virtual key definition file.\n\n");
return false;
}
- delete map;
break;
}
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index af9fdfb..089b59a 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -137,6 +137,16 @@
private boolean mOsuAp;
/**
+ * Fully qualified domain name of a Passpoint configuration
+ */
+ private String mFqdn;
+
+ /**
+ * Name of Passpoint credential provider
+ */
+ private String mProviderFriendlyName;
+
+ /**
* If connected to a network suggestion or specifier, store the package name of the app,
* else null.
*/
@@ -223,6 +233,8 @@
setEphemeral(false);
setOsuAp(false);
setNetworkSuggestionOrSpecifierPackageName(null);
+ setFQDN(null);
+ setProviderFriendlyName(null);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
@@ -257,6 +269,8 @@
mNetworkSuggestionOrSpecifierPackageName =
source.mNetworkSuggestionOrSpecifierPackageName;
mOsuAp = source.mOsuAp;
+ mFqdn = source.mFqdn;
+ mProviderFriendlyName = source.mProviderFriendlyName;
txBad = source.txBad;
txRetries = source.txRetries;
txSuccess = source.txSuccess;
@@ -504,6 +518,34 @@
}
/** {@hide} */
+ @SystemApi
+ public boolean isPasspointAp() {
+ return mFqdn != null && mProviderFriendlyName != null;
+ }
+
+ /** {@hide} */
+ public void setFQDN(@Nullable String fqdn) {
+ mFqdn = fqdn;
+ }
+
+ /** {@hide} */
+ @SystemApi
+ public @Nullable String getFqdn() {
+ return mFqdn;
+ }
+
+ /** {@hide} */
+ public void setProviderFriendlyName(@Nullable String providerFriendlyName) {
+ mProviderFriendlyName = providerFriendlyName;
+ }
+
+ /** {@hide} */
+ @SystemApi
+ public @Nullable String getProviderFriendlyName() {
+ return mProviderFriendlyName;
+ }
+
+ /** {@hide} */
public void setNetworkSuggestionOrSpecifierPackageName(@Nullable String packageName) {
mNetworkSuggestionOrSpecifierPackageName = packageName;
}
@@ -677,6 +719,8 @@
mSupplicantState.writeToParcel(dest, flags);
dest.writeInt(mOsuAp ? 1 : 0);
dest.writeString(mNetworkSuggestionOrSpecifierPackageName);
+ dest.writeString(mFqdn);
+ dest.writeString(mProviderFriendlyName);
}
/** Implement the Parcelable interface {@hide} */
@@ -716,6 +760,8 @@
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
info.mOsuAp = in.readInt() != 0;
info.mNetworkSuggestionOrSpecifierPackageName = in.readString();
+ info.mFqdn = in.readString();
+ info.mProviderFriendlyName = in.readString();
return info;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7caace6..6c645fc 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1738,10 +1738,7 @@
* @deprecated This is no longer supported.
*/
@Deprecated
- @RequiresPermission(anyOf = {
- android.Manifest.permission.NETWORK_SETTINGS,
- android.Manifest.permission.NETWORK_SETUP_WIZARD
- })
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void removePasspointConfiguration(String fqdn) {
try {
if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 948dcfa..b303496 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -36,6 +36,8 @@
private static final long TEST_TX_BAD = 3;
private static final long TEST_RX_SUCCESS = 4;
private static final String TEST_PACKAGE_NAME = "com.test.example";
+ private static final String TEST_FQDN = "test.com";
+ private static final String TEST_PROVIDER_NAME = "test";
/**
* Verify parcel write/read with WifiInfo.
@@ -49,6 +51,8 @@
writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
writeWifiInfo.setTrusted(true);
writeWifiInfo.setOsuAp(true);
+ writeWifiInfo.setFQDN(TEST_FQDN);
+ writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
writeWifiInfo.setNetworkSuggestionOrSpecifierPackageName(TEST_PACKAGE_NAME);
Parcel parcel = Parcel.obtain();
@@ -64,6 +68,9 @@
assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
assertTrue(readWifiInfo.isTrusted());
assertTrue(readWifiInfo.isOsuAp());
+ assertTrue(readWifiInfo.isPasspointAp());
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
+ assertEquals(TEST_FQDN, readWifiInfo.getFqdn());
+ assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getProviderFriendlyName());
}
}