diff options
185 files changed, 3798 insertions, 2008 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java b/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java index e417ca791c45..c1362dc3a6a7 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 @@ public class BenchmarkResults { 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/current.txt b/api/current.txt index 9e28ada17a93..343fbd9bcf5d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5478,7 +5478,7 @@ package android.app { 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; } @@ -5492,7 +5492,7 @@ package android.app { 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 { @@ -6664,7 +6664,7 @@ package android.app.admin { 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); @@ -6775,7 +6775,7 @@ package android.app.admin { 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>); @@ -11475,7 +11475,6 @@ package android.content.pm { 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(); @@ -24014,8 +24013,8 @@ package android.media { 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); } @@ -24028,8 +24027,8 @@ package android.media { 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); } @@ -27458,6 +27457,7 @@ package android.media.session { 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); @@ -27517,6 +27517,7 @@ package android.media.session { 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(); @@ -29987,7 +29988,7 @@ package android.net.wifi { 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); @@ -43339,11 +43340,11 @@ package android.telecom { 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); @@ -43358,9 +43359,9 @@ package android.telecom { 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); } @@ -45192,6 +45193,7 @@ package android.telephony { 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(); @@ -47477,6 +47479,7 @@ package android.text.style { 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 c831522f1286..b7f435acf3e4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -15,6 +15,7 @@ package android { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.net.wifi { } 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 @@ package android.os { 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 @@ package android.os { 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 @@ package android.permission { 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"; } @@ -7912,7 +7923,6 @@ package android.telephony { 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 2a45cd3b15a2..ba497d476ed9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -17,6 +17,10 @@ package android { 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 @@ package android.app { 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 @@ package android.app { 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.bluetooth { 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 @@ package android.content { 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.media.audiofx { } +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 @@ package android.os { 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 @@ package android.provider { 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 @@ package android.provider { 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"; @@ -2380,6 +2473,10 @@ package android.util { method public E valueAtUnchecked(int); } + public class TimeUtils { + method public static String formatDuration(long); + } + } package android.util.proto { @@ -2601,6 +2698,10 @@ package android.view { 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/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index e7f7af2c09e1..8d1cf33b0001 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -355,21 +355,25 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition, 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); - } - - // 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(); - } + 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(); + } + } 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; } diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 696d4fa7ae45..24e14b1ffc92 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -255,6 +255,8 @@ private: 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/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index a9d2c8810adc..28caedea5b79 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -52,15 +52,72 @@ const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs; 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 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { * 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 @@ TEST(ValueMetricProducerTest, TestFirstBucket) { * 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) { 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 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) { 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 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) { * 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { 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 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { 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 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { 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, TestPushedEventsWithUpgrade) { } 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, TestPulledValueWithUpgrade) { } 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, TestPulledWithAppUpgradeDisabled) { } 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 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) { 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, TestPushedEventsWithoutCondition) { } 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 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) { 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 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { 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(ValueMetricProducerTest, TestAnomalyDetection) { // 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { * 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { * 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) { 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 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) { 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, TestPushedAggregateMin) { } 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, TestPushedAggregateMax) { } 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, TestPushedAggregateAvg) { } 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, TestPushedAggregateSum) { } 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, TestSkipZeroDiffOutput) { } 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 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) { * 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { * 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 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 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 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 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 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 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 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 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 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 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 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 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB 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 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) { })) .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 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) { 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 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { 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, TestResetBaseOnPullTooLate) { } 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 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) { 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); - valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1); - - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) { 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 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) { 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); - valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1); - - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + 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 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) { 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 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) { 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 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) { 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 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) { 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 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { 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 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { 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 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { 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 @@ static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) { } 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 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) { 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, TestPullNeededFastDump) { } 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 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { 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, TestFastDumpWithoutCurrentBucket) { } 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 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { 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 62225df0d6ae..68fb8e694e6f 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 @@ public class Svc { 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 000000000000..b9104d169fa6 --- /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 a836e8ef202f..2abb6317702f 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -688,7 +688,6 @@ Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String; 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;-><init>()V 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 89e848b2820e..a63350cb89b4 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -7608,7 +7608,7 @@ public class Activity extends ContextThemeWrapper 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 5d4f988c3630..ee7288ffd52c 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3925,6 +3925,14 @@ public class ActivityManager { /** * @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 001cd69067a1..92302c501caf 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -43,6 +43,7 @@ import android.app.servertransaction.PendingTransactionActions; 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 @@ public final class ActivityThread extends ClientTransactionHandler { /** 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 @@ public final class ActivityThread extends ClientTransactionHandler { 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 @@ public final class ActivityThread extends ClientTransactionHandler { 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 @@ public final class ActivityThread extends ClientTransactionHandler { 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 a4b763dbfa9c..2ef085690f8f 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_OWN_C 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 @@ import java.util.List; * on VirtualDisplays. * @hide */ +@TestApi public class ActivityView extends ViewGroup { private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay"; @@ -92,7 +93,6 @@ public class ActivityView extends ViewGroup { private Insets mForwardedInsets; - @UnsupportedAppUsage public ActivityView(Context context) { this(context, null /* attrs */); } @@ -151,7 +151,7 @@ public class ActivityView extends ViewGroup { * 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 @@ public class ActivityView extends ViewGroup { * @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 @@ public class ActivityView extends ViewGroup { * @see StateCallback * @see #startActivity(Intent) */ - @UnsupportedAppUsage public void startActivity(@NonNull PendingIntent pendingIntent) { final ActivityOptions options = prepareActivityOptions(); try { @@ -272,7 +270,6 @@ public class ActivityView extends ViewGroup { * * @see StateCallback */ - @UnsupportedAppUsage public void release() { if (mVirtualDisplay == null) { throw new IllegalStateException( @@ -556,7 +553,7 @@ public class ActivityView extends ViewGroup { // notifying the callback if (stackInfo != null && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) { - mActivityViewCallback.onTaskMovedToFront(stackInfo); + mActivityViewCallback.onTaskMovedToFront(taskInfo.taskId); } } diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 98032dc3d297..d3e350779c6b 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -696,7 +696,9 @@ public class ApplicationPackageManager extends PackageManager { 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 @@ public class ApplicationPackageManager extends PackageManager { } @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 3a1e80dc1c3f..b607f9adebbe 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; 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 @@ class ContextImpl extends Context { // 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 @@ class ContextImpl extends Context { 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 @@ class ContextImpl extends Context { /** @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 3aa9fa7fedee..dcef9d24d3ae 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -486,4 +486,7 @@ interface IActivityManager { * 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 b73092a1276f..b8af8989170e 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -21,6 +21,7 @@ import android.app.IUiAutomationConnection; 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 @@ oneway interface IApplicationThread { 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/Notification.java b/core/java/android/app/Notification.java index 0166f521999e..2e7093db92f0 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -8409,7 +8409,6 @@ public class Notification implements Parcelable private PendingIntent mPendingIntent; private PendingIntent mDeleteIntent; - private CharSequence mTitle; private Icon mIcon; private int mDesiredHeight; private int mFlags; @@ -8438,9 +8437,8 @@ public class Notification implements Parcelable private static final int FLAG_SUPPRESS_INITIAL_NOTIFICATION = 0x00000002; private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent, - CharSequence title, Icon icon, int height) { + Icon icon, int height) { mPendingIntent = expandIntent; - mTitle = title; mIcon = icon; mDesiredHeight = height; mDeleteIntent = deleteIntent; @@ -8448,7 +8446,6 @@ public class Notification implements Parcelable private BubbleMetadata(Parcel in) { mPendingIntent = PendingIntent.CREATOR.createFromParcel(in); - mTitle = in.readCharSequence(); mIcon = Icon.CREATOR.createFromParcel(in); mDesiredHeight = in.readInt(); mFlags = in.readInt(); @@ -8474,11 +8471,13 @@ public class Notification implements Parcelable /** * @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 mTitle; + return ""; } - /** * @return the icon that will be displayed for this bubble when it is collapsed. */ @@ -8534,7 +8533,6 @@ public class Notification implements Parcelable @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); @@ -8554,7 +8552,6 @@ public class Notification implements Parcelable public static class Builder { private PendingIntent mPendingIntent; - private CharSequence mTitle; private Icon mIcon; private int mDesiredHeight; private int mFlags; @@ -8583,12 +8580,11 @@ public class Notification implements Parcelable * * <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; } @@ -8667,13 +8663,10 @@ public class Notification implements Parcelable 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, mDeleteIntent, mTitle, + BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent, mIcon, mDesiredHeight); data.setFlags(mFlags); return data; diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 31521a369a4c..7e074460bff8 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -128,7 +128,13 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { : 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 3587c68ef234..a32e01fb68e5 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -59,6 +59,7 @@ import android.os.Build; 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.Arrays; 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 class DevicePolicyManager { 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 @@ public class DevicePolicyManager { * 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 @@ public class DevicePolicyManager { * @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 @@ public class DevicePolicyManager { * @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 5790fda718a7..9478a3c83d23 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -311,8 +311,8 @@ interface IDevicePolicyManager { 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/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 3e9dd2882600..85f0e2342412 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -30,7 +30,6 @@ import android.content.pm.PackageManager.NameNotFoundException; 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 class AppWidgetHostView extends FrameLayout { */ 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 000000000000..7e4fed20957f --- /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 000000000000..fd7e52aaebcd --- /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 fdb0041d49ed..29added9aa51 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5241,9 +5241,10 @@ public abstract class Context { 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 @@ public abstract class Context { /** * @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 68b4320568c2..40559d31d631 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -919,11 +919,9 @@ public class ContextWrapper extends Context { return mBase.getDisplayAdjustments(displayId); } - /** - * @hide - */ + /** @hide */ + @TestApi @Override - @UnsupportedAppUsage public Display getDisplay() { return mBase.getDisplay(); } @@ -1031,22 +1029,17 @@ public class ContextWrapper extends Context { 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 14e77258c65e..dcbb4ac2d5f3 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -111,7 +111,7 @@ interface IPackageManager { 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 80954731bffb..badd48f9ea53 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1545,7 +1545,11 @@ public class PackageInstaller { /** * 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 00419212544a..6b2442f65b49 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -33,6 +33,7 @@ import android.annotation.UnsupportedAppUsage; 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 abstract class PackageManager { 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 @@ public abstract class PackageManager { @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 0f67262bf901..d7ca757d8025 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -48,7 +48,6 @@ import android.annotation.Nullable; 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 @@ public class PackageParser { } 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 @@ public class PackageParser { 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/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java index 19848ee6d415..5496e17206d9 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 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; * @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 5f356ca00d88..27f9a5dbf51c 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 @@ import java.util.concurrent.TimeUnit; * @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 6d195ae47449..c1bce5e52a8d 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3147,9 +3147,9 @@ public class ConnectivityManager { /** * 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 0dfe7a495738..5b1d12c603b4 100644 --- a/core/java/android/net/NetworkFactory.java +++ b/core/java/android/net/NetworkFactory.java @@ -27,11 +27,13 @@ import android.util.Log; 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 @@ public class NetworkFactory extends Handler { */ 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 @@ public class NetworkFactory extends Handler { @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 @@ public class NetworkFactory extends Handler { }); } + /** + * 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 83a7654d494b..0425c6234a04 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -107,6 +107,7 @@ public class Build { * 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/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 47b1eefdcb07..650d21785ec2 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -664,8 +664,15 @@ public class GraphicsEnvironment { .append(abi); final String paths = sb.toString(); - if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths); - setDriverPath(paths); + final String sphalLibraries = + coreSettings.getString(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES); + + if (DEBUG) { + Log.v(TAG, + "gfx driver package search path: " + paths + + ", required sphal libraries: " + sphalLibraries); + } + setDriverPathAndSphalLibraries(paths, sphalLibraries); if (driverAppInfo.metaData == null) { throw new NullPointerException("apk's meta-data cannot be null"); @@ -700,7 +707,7 @@ public class GraphicsEnvironment { private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); private static native void setDebugLayersGLES(String layers); - private static native void setDriverPath(String path); + private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName); private static native void setAngleInfo(String path, String appPackage, String devOptIn, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index e2b5730e10f4..067375590c99 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2697,6 +2697,19 @@ public class UserManager { } /** + * 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 @@ public class UserManager { } /** + * 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 @@ public class UserManager { } /** + * 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 7e9ba5d4b628..cb2517e956df 100644 --- a/core/java/android/permission/IPermissionController.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -40,4 +40,6 @@ oneway interface IPermissionController { 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 d62bc6c5a872..cd7bbfddbbd5 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.RequiresPermission; 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 @@ public final class PermissionControllerManager { } /** + * 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 @@ public final class PermissionControllerManager { } /** + * 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 fb6c061c536f..e883d25ab0bd 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.BinderThread; 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 class PermissionControllerService extends Service { 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 @@ public abstract class PermissionControllerService extends Service { 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 @@ public abstract class PermissionControllerService extends Service { 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 f63c0adbdf4b..44adc1c5cba4 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -783,7 +783,7 @@ public class CallLog { 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 @@ public class CallLog { } 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 @@ public class CallLog { 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 f6a8388a7d40..868a36b56bf4 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -169,7 +169,7 @@ public final class DeviceConfig { * * @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 a465b3271407..15306260dcba 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8131,6 +8131,7 @@ public final class Settings { * * @hide */ + @TestApi public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners"; private static final Validator ENABLED_VR_LISTENERS_VALIDATOR = @@ -10780,6 +10781,7 @@ public final class Settings { * * @hide */ + @TestApi public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices"; /** @@ -14096,17 +14098,16 @@ public final class Settings { public static final String SHOW_TEMPERATURE_WARNING = "show_temperature_warning"; /** - * Temperature at which the high temperature warning notification should be shown. + * Whether to show the usb high temperature alarm notification. * @hide */ - public static final String WARNING_TEMPERATURE = "warning_temperature"; - + public static final String SHOW_USB_TEMPERATURE_ALARM = "show_usb_temperature_alarm"; /** - * USB Temperature at which the high temperature alarm notification should be shown. + * Temperature at which the high temperature warning notification should be shown. * @hide */ - public static final String USB_ALARM_TEMPERATURE = "usb_alarm_temperature"; + public static final String WARNING_TEMPERATURE = "warning_temperature"; /** * Whether the diskstats logging task is enabled/disabled. diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java index 575401458691..1a508a1f6c6d 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.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import java.lang.annotation.Retention; import java.lang.ref.WeakReference; /** @@ -80,10 +84,21 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { /** * 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 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { /** * 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 e4c8eeb3b9b0..f8b38e9d215d 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -18,6 +18,7 @@ package android.util; 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 @@ public class TimeUtils { } /** @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 cb5100a4d57a..94a9a1c0ff30 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE; 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 @@ public final class Display { * @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 2ef7c4b16d9d..5dc54a566676 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -582,4 +582,13 @@ interface IWindowManager * 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 e5db44eca684..aaf85aff2e8f 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -189,6 +189,7 @@ public final class SurfaceControl implements Parcelable { 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; @@ -2109,6 +2110,17 @@ public final class SurfaceControl implements Parcelable { } /** + * 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/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ab4847ded0e6..89c67032f8c2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; 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 @@ public final class ViewRootImpl implements ViewParent, 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 e9b16836157f..9dcbe05a06d1 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -28,6 +28,7 @@ import android.annotation.RequiresFeature; 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 @@ public final class AutofillManager { @GuardedBy("mLock") private CompatibilityBridge mCompatibilityBridge; + @Nullable + private final AutofillOptions mOptions; + /** @hide */ public interface AutofillClient { /** @@ -618,6 +622,12 @@ public final class AutofillManager { 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 @@ public final class AutofillManager { 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 155fe721311c..d5862bd2f942 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 class AutofillManagerInternal { 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 b0e7ad5d7264..2ad17a84a64e 100644 --- a/core/java/android/view/textclassifier/ExtrasUtils.java +++ b/core/java/android/view/textclassifier/ExtrasUtils.java @@ -94,7 +94,8 @@ public final class ExtrasUtils { 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 a05920960dcf..052ee953e971 100644 --- a/core/java/android/view/textclassifier/TextClassification.java +++ b/core/java/android/view/textclassifier/TextClassification.java @@ -54,6 +54,7 @@ import java.util.Collections; 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 @@ public final class TextClassification implements Parcelable { @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 @@ public final class TextClassification implements Parcelable { 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 295c8b72b943..e628f19668ae 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -240,9 +240,7 @@ public final class TextClassifierImpl implements TextClassifier { 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 @@ public final class TextClassifierImpl implements TextClassifier { 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 @@ public final class TextClassifierImpl implements TextClassifier { 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 @@ public final class TextClassifierImpl implements TextClassifier { } } - 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 @@ public final class TextClassifierImpl implements TextClassifier { /** * 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 @@ public final class TextClassifierImpl implements TextClassifier { 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 @@ public final class TextClassifierImpl implements TextClassifier { 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 @@ public final class TextClassifierImpl implements TextClassifier { } /** + * 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 0fbd4dca700b..89e3d6b6460f 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -381,6 +381,8 @@ public class ChooserActivity extends ResolverActivity { 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 @@ public class ChooserActivity extends ResolverActivity { } /** + * 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 d13bcf2aa186..64f00103eb4b 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.IPackageManager; 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.util.Slog; 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 @@ public class IntentForwarderActivity extends Activity { private Injector mInjector; + private MetricsLogger mMetricsLogger; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -78,9 +83,17 @@ public class IntentForwarderActivity extends Activity { 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 @@ public class IntentForwarderActivity extends Activity { 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/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index d9d3cdf43d18..72e3d3495e37 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -27,9 +27,12 @@ int getCanLoadSystemLibraries_native() { return android::GraphicsEnv::getInstance().getCanLoadSystemLibraries(); } -void setDriverPath(JNIEnv* env, jobject clazz, jstring path) { +void setDriverPathAndSphalLibraries_native(JNIEnv* env, jobject clazz, jstring path, + jstring sphalLibraries) { ScopedUtfChars pathChars(env, path); - android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str()); + ScopedUtfChars sphalLibrariesChars(env, sphalLibraries); + android::GraphicsEnv::getInstance().setDriverPathAndSphalLibraries(pathChars.c_str(), + sphalLibrariesChars.c_str()); } void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, @@ -84,7 +87,7 @@ void setDebugLayersGLES_native(JNIEnv* env, jobject clazz, jstring layers) { const JNINativeMethod g_methods[] = { { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) }, - { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) }, + { "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPathAndSphalLibraries_native) }, { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) }, { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) }, { "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) }, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 6b8d8b1bb91f..003ee37995af 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -406,6 +406,11 @@ static void nativeTransferTouchFocus(JNIEnv* env, jclass clazz, jlong transactio 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 @@ static const JNINativeMethod sSurfaceControlMethods[] = { "(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 15ceca96313e..4c5b2849ec27 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 CreateDir(const std::string& dir, } } -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 @@ static void MountPkgSpecificDir(const std::string& mntSourceRoot, 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 @@ static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames, 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 PreparePkgSpecificDirs(const std::vector<std::string>& packageNames, } } +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 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode, } 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 cccb40d51722..c1cbd525b4d1 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -920,8 +920,7 @@ message GlobalSettingsProto { // 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 fc896cf3c514..0149365b4fb5 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3418,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 6571cd264583..eb6953546330 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 e1ce2f69ba70..5a3c536b0042 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 4ae239e191e3..8df0e196e41c 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 9fabe44f2a8a..d73c174212bd 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.IApplicationThread; 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 @@ public class TransactionParcelTests { 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 46cac7a49f13..3a1a4fc7b65f 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -429,6 +429,7 @@ public class SettingsBackupTest { 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 @@ public class SettingsBackupTest { 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 99c959ef57e4..d54402975f65 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 @@ public class TextClassificationTest { 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 @@ public class TextClassificationTest { // 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 f27f3f9ca427..9fbc1666aed1 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 androidx.test.rule.ActivityTestRule; 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 @@ public class ChooserActivityTest { 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 @@ public class ChooserActivityTest { 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 @@ public class ChooserActivityTest { 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 @@ public class ChooserActivityTest { 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 57c84ff5c8ac..a8dd69a2666d 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.net.Uri; 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 @@ public class ChooserWrapperActivity extends ChooserActivity { 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 class ChooserWrapperActivity extends ChooserActivity { public boolean resolverForceException; public Bitmap previewThumbnail; public MetricsLogger metricsLogger; + public int alternateProfileSetting; public void reset() { onSafelyStartCallback = null; @@ -139,6 +149,7 @@ public class ChooserWrapperActivity extends ChooserActivity { 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 9b13af2a4357..abfb4fb3cedc 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.anyInt; 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.IPackageManager; 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.InstrumentationRegistry; 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 @@ public class IntentForwarderActivityTest { "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 @@ public class IntentForwarderActivityTest { 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 @@ public class IntentForwarderActivityTest { private Intent mStartActivityIntent; private int mUserIdActivityLaunchedIn; + private MetricsLogger mMetricsLogger = mock(MetricsLogger.class); @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -559,6 +624,11 @@ public class IntentForwarderActivityTest { 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 62647741dcfa..15d855e9560c 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 @@ public class ImageFormat { * @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 @@ public class ImageFormat { * * @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 3ce48b4f7627..9d3211d1b4f8 100644 --- a/location/java/android/location/GnssMeasurementCorrections.java +++ b/location/java/android/location/GnssMeasurementCorrections.java @@ -124,7 +124,7 @@ public final class GnssMeasurementCorrections implements Parcelable { * 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 @@ public final class GnssMeasurementCorrections implements Parcelable { 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 @@ public final class GnssMeasurementCorrections implements Parcelable { .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 @@ public final class GnssMeasurementCorrections implements Parcelable { } /** 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 @@ public final class GnssMeasurementCorrections implements Parcelable { * 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 64b37524e37f..9a106a760ec4 100644 --- a/location/java/android/location/GnssReflectingPlane.java +++ b/location/java/android/location/GnssReflectingPlane.java @@ -116,7 +116,7 @@ public final class GnssReflectingPlane implements Parcelable { } /** 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 4d5303f18b81..f719e1a985b8 100644 --- a/location/java/android/location/GnssSingleSatCorrection.java +++ b/location/java/android/location/GnssSingleSatCorrection.java @@ -60,6 +60,7 @@ public final class GnssSingleSatCorrection implements Parcelable { private int mSingleSatCorrectionFlags; /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */ + @GnssStatus.ConstellationType private int mConstellationType; /** @@ -115,7 +116,7 @@ public final class GnssSingleSatCorrection implements Parcelable { } /** Gets a bitmask of fields present in this object */ - public int getSingleSatCorrectionFlags() { + public int getSingleSatelliteCorrectionFlags() { return mSingleSatCorrectionFlags; } @@ -136,7 +137,7 @@ public final class GnssSingleSatCorrection implements Parcelable { * <p>Interpretation depends on {@link #getConstellationType()}. See {@link * GnssStatus#getSvid(int)}. */ - public int getSatId() { + public int getSatelliteId() { return mSatId; } @@ -162,7 +163,7 @@ public final class GnssSingleSatCorrection implements Parcelable { * location. */ @FloatRange(from = 0f, to = 1f) - public float getProbSatIsLos() { + public float getProbabilityLineOfSight() { return mProbSatIsLos; } @@ -189,8 +190,8 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { } /** 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 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { * 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 8f46e84195d5..ae5ca4069e5c 100644 --- a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java +++ b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java @@ -53,15 +53,15 @@ public class GnssMeasurementCorrectionsTest extends TestCase { 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 @@ public class GnssMeasurementCorrectionsTest extends TestCase { 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 f358806d0b26..60f33f07c170 100644 --- a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java +++ b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java @@ -40,11 +40,11 @@ public class GnssSingleSatCorrectionsTest extends TestCase { } 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 @@ public class GnssSingleSatCorrectionsTest extends TestCase { } 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 10accf23364c..4f2de230b60c 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -401,7 +401,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, 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 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, 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 6116429ae561..ba87f2bbffb5 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 @@ public class ImageReader implements AutoCloseable { * 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 @@ public class ImageReader implements AutoCloseable { * @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 dd09afc3ddb0..f813d1b68419 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 @@ public class ImageWriter implements AutoCloseable { * {@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 @@ public class ImageWriter implements AutoCloseable { * * @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 cf5711d73278..a9e33fd8e472 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -19,9 +19,9 @@ package android.media; 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 @@ import java.util.ArrayList; 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 @@ public final class MediaCas implements AutoCloseable { 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 @@ public final class MediaCas implements AutoCloseable { } @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 @@ public final class MediaCas implements AutoCloseable { mEventHandler.sendMessage(msg); } }; - /** * Describe a CAS plugin with its CA_system_ID and string name. * @@ -338,9 +350,14 @@ public final class MediaCas implements AutoCloseable { 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 final class MediaCas implements AutoCloseable { */ 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 @@ public final class MediaCas implements AutoCloseable { } } - 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 65f3294800f5..49867ab62cea 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -19,6 +19,7 @@ package android.media.audiopolicy; 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 @@ public class AudioPolicy { 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 @@ public class AudioPolicy { 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 f725cacf5f21..a56fd31fbaeb 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -18,8 +18,6 @@ package android.media.audiopolicy; 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 40c716607697..5828fbdd1700 100644 --- a/media/java/android/media/session/ControllerLink.java +++ b/media/java/android/media/session/ControllerLink.java @@ -158,6 +158,18 @@ public final class ControllerLink implements Parcelable { } /** + * 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 @@ public final class ControllerLink implements Parcelable { 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 @@ public final class ControllerLink implements Parcelable { } @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 3e7b4fbdebd3..298085f005da 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -44,6 +44,7 @@ interface ISessionController { 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 8143bfa00dc1..e85461f93731 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -35,7 +35,7 @@ import android.view.KeyEvent; */ 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 9e4199cba47a..fb21f69b2aca 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -79,6 +79,7 @@ public final class MediaController { private boolean mCbRegistered = false; private String mPackageName; private String mTag; + private Bundle mSessionInfo; private final TransportControls mTransportControls; @@ -410,6 +411,23 @@ public final class MediaController { } /** + * 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 8ab893b03a62..9fdefa62a35f 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -132,6 +132,27 @@ public final class MediaSession { * @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 @@ public final class MediaSession { .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 46f6c71c5be0..fde4f8837fa5 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -28,6 +28,7 @@ import android.media.AudioManager; 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 @@ public final class MediaSessionManager { * 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/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index f865563200e1..68f1e6fb6f13 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 ef8dd3de56a9..4f2913101c38 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 97b9036157a3..36e04bb5f2bf 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 6e37c9a6eeda..89d6361395eb 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 41b0fbda408f..1e9a0d51ee67 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 0292cabb73bf..ae97fb24f573 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 0c2f0eefb0e7..88de8f43b888 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 7daf9564cc9b..ac15f1b55564 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 54ddf845847e..847586e06cfc 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 dcf3e3cb46ec..0675b6be525e 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 71716cec6886..3cf43c844354 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 65ed110d3c46..c22362927e31 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/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 81b304dc2ce4..0f8fd9265eaa 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 @@ class SettingsProtoDumpUtil { 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 78304fd894dd..000000000000 --- 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/nav_bar_tuner_inflater.xml b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml index b2376333a30e..133b2158c771 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 d72021e27e0b..db1c79d24c54 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 index 24a0c71f3bad..285c5c4e0a01 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 4396a42929ba..b4dc0eff0761 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/strings.xml b/packages/SystemUI/res/values/strings.xml index 0fde2de1e2f1..4905e572af1d 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/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index c5dc3244d0a3..3827e445c136 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.util.DisplayMetrics; 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 @@ public final class ClockManager { // 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 @@ public final class ClockManager { 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 9efa656b3ed3..60e6083790dc 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -474,8 +474,6 @@ public class SwipeHelper implements Gefingerpoken { if (anim == null) { return; } - int duration = SNAP_ANIM_LEN; - anim.setDuration(duration); anim.addListener(new AnimatorListenerAdapter() { boolean wasCancelled = false; @@ -495,6 +493,9 @@ public class SwipeHelper implements Gefingerpoken { }); 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/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index 50dda1c1de6b..fdb0b36ee51e 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.text.style.URLSpan; 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.internal.messages.nano.SystemMessageProto.SystemMessage; 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 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { 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 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { private boolean mHighTempWarning; private SystemUIDialog mHighTempDialog; private SystemUIDialog mThermalShutdownDialog; + @VisibleForTesting SystemUIDialog mUsbHighTempDialog; /** */ @@ -149,6 +156,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { 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 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { 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 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { } @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 c43f5728aaa2..e27c25efd88f 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.content.res.Resources; 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.Log; 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 @@ public class PowerUI extends SystemUI { 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 @@ public class PowerUI extends SystemUI { 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 @@ public class PowerUI extends SystemUI { // to the temperature being too high. showThermalShutdownDialog(); - initTemperatureWarning(); + initTemperature(); } @Override @@ -137,7 +125,7 @@ public class PowerUI extends SystemUI { // 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 @@ public class PowerUI extends SystemUI { 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,103 +390,34 @@ public class PowerUI extends SystemUI { 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); - } - - private void showThermalShutdownDialog() { - if (mPowerManager.getLastShutdownReason() - == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) { - mWarnings.showThermalShutdownWarning(); - } } @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(); + void registerThermalEventListener() { + try { + if (mEnableSkinTemperatureWarning) { + mThermalService.registerThermalEventListenerWithType( + new ThermalEventSkinListener(), Temperature.TYPE_SKIN); } - } - - 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; - } + if (mEnableUsbTemperatureAlarm) { + mThermalService.registerThermalEventListenerWithType( + new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT); } - - 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); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register thermal callback.", e); } - setNextLogTime(); - mNumTemps = 0; } - private void setNextLogTime() { - mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL; + private void showThermalShutdownDialog() { + if (mPowerManager.getLastShutdownReason() + == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) { + mWarnings.showThermalShutdownWarning(); + } } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -541,34 +446,80 @@ public class PowerUI extends SystemUI { 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 cf3f89ef8788..409d60fa6c17 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 @@ public class NavBarTintController { 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/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java index c9fa89e7cb97..faa2ab105816 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.graphics.drawable.Icon; 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 @@ public class NavigationBarInflaterView extends FrameLayout 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 class NavigationBarInflaterView extends FrameLayout 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 @@ public class NavigationBarInflaterView extends FrameLayout 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 class NavigationBarInflaterView extends FrameLayout } } - 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 class NavigationBarInflaterView extends FrameLayout } } - 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 @@ public class NavigationBarInflaterView extends FrameLayout } 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 @@ public class NavigationBarInflaterView extends FrameLayout } 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 @@ public class NavigationBarInflaterView extends FrameLayout 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 @@ public class NavigationBarInflaterView extends FrameLayout 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 d6d3d0807659..f82b05e78ff9 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 class NavigationBarView extends FrameLayout implements PluginListener<Nav public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) { mOnVerticalChangedListener = onVerticalChangedListener; - notifyVerticalChangedListener(mVertical); + notifyVerticalChangedListener(mIsVertical); } @Override @@ -547,10 +549,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return mCurrentView; } - public View[] getAllViews() { - return mRotatedViews; - } - public ButtonDispatcher getRecentsButton() { return mButtonDispatchers.get(R.id.recent_apps); } @@ -657,7 +655,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav // 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener); DockedStackExistsListener.register(mDockedListener); - updateRotatedViews(); + updateOrientationViews(); reloadNavIcons(); } @@ -1028,34 +1026,35 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 class NavigationBarView extends FrameLayout implements PluginListener<Nav } public boolean isVertical() { - return mVertical; + return mIsVertical; } public void reorient() { @@ -1101,7 +1100,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav updateTaskSwitchHelper(); updateNavButtonIcons(); - getHomeButton().setVertical(mVertical); + getHomeButton().setVertical(mIsVertical); } private void updateTaskSwitchHelper() { @@ -1134,9 +1133,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav "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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 ca55e1f23d20..1596ddbafda0 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 class Events { 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 @@ public class Events { "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 class Events { 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 @@ public class Events { "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 @@ public class Events { 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/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java index bf6cc53aa5e9..cd500b4c38f9 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.internal.messages.nano.SystemMessageProto.SystemMessage; 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 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { 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 c28e74e7c6a1..0aed63d25112 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 static org.mockito.Mockito.when; 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 @@ public class PowerUITest extends SysuiTestCase { 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(); + + final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1"); + mThermalEventSkinListener.notifyThrottling(temp); + + // dismiss skin high temperature warning when throttling status is critical + TestableLooper.get(this).processAllMessages(); verify(mMockWarnings, never()).showHighTemperatureWarning(); + verify(mMockWarnings, times(1)).dismissHighTemperatureWarning(); } @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); - + public void testSkinWarning_throttlingEmergency() throws Exception { mPowerUI.start(); - verify(mMockWarnings, never()).showHighTemperatureWarning(); + + 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 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); + 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(); - // Guarantees mHandler has processed all messages. + + 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).showHighTemperatureWarning(); + verify(mMockWarnings, times(1)).showUsbHighTemperatureAlarm(); } @Test - public void testSettingOverrideConfig() { - setOverThreshold(); + 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 @@ public class PowerUITest extends SysuiTestCase { verify(mEnhancedEstimates, times(2)).getEstimate(); } - private void setCurrentTemp(float temp) { - when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT)) - .thenReturn(new float[] { temp }); - } - - private void setOverThreshold() { - setCurrentTemp(50000); + private Temperature getEmergencyStatusTemp(int type, String name) { + final float value = 65; + return new Temperature(value, type, name, Temperature.THROTTLING_EMERGENCY); } - 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 000000000000..093749adf1c3 --- /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 e4da859946af..f72d4119b50c 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.app.AlarmManager; 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 @@ public class ScrimControllerTest extends SysuiTestCase { assertScrimTint(mScrimBehind, false /* tinted */); } + @FlakyTest(bugId = 124858892) @Test public void transitionToUnlocked() { mScrimController.setPanelExpansion(0f); @@ -295,6 +297,7 @@ public class ScrimControllerTest extends SysuiTestCase { Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED); } + @FlakyTest(bugId = 124858892) @Test public void panelExpansion() { mScrimController.setPanelExpansion(0f); @@ -317,6 +320,7 @@ public class ScrimControllerTest extends SysuiTestCase { 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 817a54d93268..7f826b3a9a6f 100644 --- a/proto/Android.bp +++ b/proto/Android.bp @@ -6,6 +6,7 @@ java_library_static { }, 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 530d1156a5e4..33555c43d928 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -247,6 +247,12 @@ message MetricsEvent { 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 @@ message MetricsEvent { // 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 @@ message MetricsEvent { // 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/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index e0fb33799ff7..1cca813ece25 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.Nullable; 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 @@ public final class AutofillManagerService } @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 15dce4af405b..2e99654b9298 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.annotation.Nullable; 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; @@ -1084,6 +1085,7 @@ final class AutofillManagerServiceImpl if (remoteService != null) { remoteService.destroy(); } + mRemoteAugmentedAutofillService = null; } }, mMaster.isInstantServiceAllowed(), mMaster.verbose); } @@ -1169,6 +1171,13 @@ final class AutofillManagerServiceImpl 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/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 915c131ff0fb..ed459dbfc4eb 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1060,7 +1060,8 @@ public class ConnectivityService extends IConnectivityManager.Stub handleRegisterNetworkRequest(new NetworkRequestInfo( null, networkRequest, new Binder())); } else { - handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID); + handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID, + /* callOnUnavailable */ false); } } @@ -2641,11 +2642,25 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub int callingUid) { NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent); if (nri != null) { - handleReleaseNetworkRequest(nri.request, callingUid); + handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false); } } @@ -3066,7 +3085,8 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 0ed5beb57f82..4d39f9ab8d78 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -145,7 +145,7 @@ option java_package com.android.server # --------------------------- # 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/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index cd9d84cca250..a5eab8550e71 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2811,6 +2811,7 @@ class StorageManagerService extends IStorageManager.Stub @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 @@ class StorageManagerService extends IStorageManager.Stub @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 7c46f1d70cb6..375c5c4b7e5a 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.backup.IBackupManager; 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index 6899c3ffcbb1..647727f795da 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -62,6 +62,7 @@ public class GpuService extends SystemService { private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt"; + private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private final Context mContext; @@ -162,6 +163,25 @@ public class GpuService extends SystemService { } } + private static void assetToSettingsGlobal(Context context, Context driverContext, + String fileName, String settingsGlobal, CharSequence delimiter) { + try { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(driverContext.getAssets().open(fileName))); + final ArrayList<String> assetStrings = new ArrayList<>(); + for (String assetString; (assetString = reader.readLine()) != null; ) { + assetStrings.add(assetString); + } + Settings.Global.putString(context.getContentResolver(), + settingsGlobal, + String.join(delimiter, assetStrings)); + } catch (IOException e) { + if (DEBUG) { + Slog.w(TAG, "Failed to load " + fileName + ", abort."); + } + } + } + private void fetchGameDriverPackageProperties() { final ApplicationInfo driverInfo; try { @@ -186,29 +206,25 @@ public class GpuService extends SystemService { // Reset the whitelist. Settings.Global.putString(mContentResolver, Settings.Global.GAME_DRIVER_WHITELIST, ""); + // Reset the sphal libraries + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ""); mGameDriverVersionCode = driverInfo.longVersionCode; try { final Context driverContext = mContext.createPackageContext(mDriverPackageName, Context.CONTEXT_RESTRICTED); - final BufferedReader reader = new BufferedReader( - new InputStreamReader(driverContext.getAssets() - .open(GAME_DRIVER_WHITELIST_FILENAME))); - final ArrayList<String> whitelistedPackageNames = new ArrayList<>(); - for (String packageName; (packageName = reader.readLine()) != null; ) { - whitelistedPackageNames.add(packageName); - } - Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_WHITELIST, - String.join(",", whitelistedPackageNames)); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME, + Settings.Global.GAME_DRIVER_WHITELIST, ","); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_SPHAL_LIBRARIES_FILENAME, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ":"); + } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed"); } - } catch (IOException e) { - if (DEBUG) { - Slog.w(TAG, "Failed to load whitelist driver package, abort."); - } } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 924018ea3a5a..aa85c835a5fd 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -407,6 +407,10 @@ public class LockSettingsService extends ILockSettings.Stub { return new SyntheticPasswordManager(getContext(), storage, getUserManager()); } + public boolean hasBiometrics() { + return BiometricManager.hasBiometrics(mContext); + } + public int binderGetCallingUid() { return Binder.getCallingUid(); } @@ -2434,7 +2438,7 @@ public class LockSettingsService extends ILockSettings.Stub { 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 b221241c25e2..152cf7fe7d41 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 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { 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 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { 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 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @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 62d9b20b636d..b86328b92869 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 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { } 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 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { * 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 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { } 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 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { @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 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { 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 2aaa1edcfad9..26cc0c10ccb3 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { 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 @@ public class NotificationShellCmd extends ShellCommand { // 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 2c47ec03f9fa..660309cd578d 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 @@ public class PreferencesHelper implements RankingConfig { 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/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 62c4815a7de0..9e9128430e01 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.NonNull; 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 @@ public class LauncherAppsService extends SystemService { 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 f06da49f5b94..bd74174b2e88 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 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } - 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 1b719048bc89..56ef33ac4c31 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 class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } return; } - mPm.installStage(childSessions); + mPm.installStage(activeChildSessions); } else { mPm.installStage(committingSession); } @@ -1887,6 +1904,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 07d460edb2d2..4bca5e0897ff 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.Nullable; 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub @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 @@ public class PackageManagerService extends IPackageManager.Stub @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 @@ public class PackageManagerService extends IPackageManager.Stub "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); } @@ -19948,8 +20037,11 @@ public class PackageManagerService extends IPackageManager.Stub 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()); @@ -20104,13 +20196,9 @@ public class PackageManagerService extends IPackageManager.Stub } // 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) { @@ -22997,7 +23085,7 @@ public class PackageManagerService extends IPackageManager.Stub 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 d0f192d597c6..3744f68afbfe 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 @@ public class UserManagerService extends IUserManager.Stub { @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 636917921652..93a3d0af0272 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 @@ public final class DefaultPermissionGrantPolicy { // 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 @@ public final class DefaultPermissionGrantPolicy { 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 @@ public final class DefaultPermissionGrantPolicy { // 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 8df5a71de43e..03da962b6ac6 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_REVOKE_WHEN_REQU 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 @@ public class PermissionManagerService { updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); } - permissionsState.updatePermissionFlags(bp, userId, flags, flags); + permissionsState.updatePermissionFlags(bp, userId, + MASK_PERMISSION_FLAGS, flags); } } break; @@ -1081,7 +1083,8 @@ public class PermissionManagerService { updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); } - permissionsState.updatePermissionFlags(bp, userId, flags, flags); + permissionsState.updatePermissionFlags(bp, userId, + MASK_PERMISSION_FLAGS, flags); } } break; @@ -1198,29 +1201,23 @@ public class PermissionManagerService { 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 @@ public class PermissionManagerService { } } } + + ps.updatePermissionFlags(bp, userId, flagsToRemove, 0); + updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); } } } @@ -1935,7 +1935,7 @@ public class PermissionManagerService { 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 @@ public class PermissionManagerService { } 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 @@ public class PermissionManagerService { 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 @@ public class PermissionManagerService { } @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 1dd2408686c1..305f165ae85f 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 class PermissionManagerServiceInternal extends PermissionManager */ 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 c87a81db16e4..68dab3401a1b 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { // 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/role/TEST_MAPPING b/services/core/java/com/android/server/role/TEST_MAPPING index 0b967be5169f..0d7bc1476bd1 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/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index c14f1261cc76..11839a52d939 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -966,36 +966,45 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } getHandler().post(() -> { - final RollbackData rollbackData = getRollbackForPackage(packageName); - for (int userId : userIds) { - if (rollbackData == null || !rollbackData.inProgress) { - Log.e(TAG, "Request to restore userData for: " + packageName - + ", but no rollback in progress."); - continue; - } - 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); - } - } - } - + 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<>(); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 9ea819ea8e16..9f04166ea4c0 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_REORDER_TO_FRONT; 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 @@ class ActivityStarter { // 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/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 543f19655350..c6b7060fe649 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.DEBUG_ORIENTATION; 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.policy.WindowOrientationListener; 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 @@ public class DisplayRotation { 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 @@ public class DisplayRotation { 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 @@ public class DisplayRotation { } 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 @@ public class DisplayRotation { 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 @@ public class DisplayRotation { } 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 @@ public class DisplayRotation { * false} is when {@link #isFixedToUserRotation()} is {@code true}. */ boolean respectAppRequestedOrientation() { - return !mFixedToUserRotation; + return !isFixedToUserRotation(); } public int getLandscapeRotation() { @@ -461,7 +490,7 @@ public class DisplayRotation { * 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 @@ public class DisplayRotation { ); } - if (mFixedToUserRotation) { + if (isFixedToUserRotation()) { return mUserRotation; } @@ -739,7 +768,7 @@ public class DisplayRotation { // 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 @@ public class DisplayRotation { 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 5cfa7dec386e..4617890be722 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 android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; 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 @@ class DisplayWindowSettings { 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 @@ class DisplayWindowSettings { && !mShouldShowWithInsecureKeyguard && !mShouldShowSystemDecors && !mShouldShowIme - && !mFixedToUserRotation; + && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT; } } @@ -188,7 +190,8 @@ class DisplayWindowSettings { 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 @@ class DisplayWindowSettings { "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 @@ class DisplayWindowSettings { 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/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 84cd8d1632cf..2d5c97f9a3a5 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 @@ class ScreenRotationAnimation { 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 @@ class ScreenRotationAnimation { // 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/services/core/java/com/android/server/wm/SurfaceFactory.java b/services/core/java/com/android/server/wm/SurfaceFactory.java new file mode 100644 index 000000000000..076b7df63c46 --- /dev/null +++ b/services/core/java/com/android/server/wm/SurfaceFactory.java @@ -0,0 +1,27 @@ +/* + * 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.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/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 74fb3fa85f24..dddc6b755db0 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.SurfaceControl; 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 @@ class WallpaperController { mWallpaperTokens.remove(token); } - /** - * Take a screenshot of the wallpaper if it's visible. - * - * @return Bitmap of the wallpaper - */ - Bitmap screenshotWallpaperLocked() { + + @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 null; + return false; } - final WindowState wallpaperWindowState = getTopVisibleWallpaper(); 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() { + final WindowState wallpaperWindowState = getTopVisibleWallpaper(); + 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 39df0e42e27c..e19c7c66815c 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.IWindowSession; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 @@ public class WindowManagerService extends IWindowManager.Stub } } } + + @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 d13ee459c115..7384bb7e1587 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 @@ public class WindowManagerShellCommand extends ShellCommand { 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/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 2ee58fe3f574..cc7917879634 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 @@ class WindowSurfacePlacer { 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 d178c3abc906..fe941681a7be 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 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen 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 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen 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 ae48dad7b8f9..3070488cb713 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.ContentValues; 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.Handler; 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.UserManager; 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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); + } + + 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; + } + + 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); + }); } - 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; - - case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: { - packageManager.updatePermissionFlags(permission, packageName, - PackageManager.FLAG_PERMISSION_POLICY_FIXED, 0, user); - } break; - } - } 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 4700b9677a19..8d88c5a004a9 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -310,6 +310,7 @@ public final class SystemServer { private boolean mOnlyCore; private boolean mFirstBoot; + private final int mStartCount; private final boolean mRuntimeRestart; private final long mRuntimeStartElapsedTime; private final long mRuntimeStartUptime; @@ -317,6 +318,9 @@ public final class SystemServer { 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; @@ -346,16 +350,33 @@ public final class SystemServer { 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 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 5cb6cbb93b5b..26b122411c6b 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 @@ public class IPackageManagerStub implements IPackageManager { @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/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 74d473944779..bf71318cf50a 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -106,6 +106,11 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override + public boolean hasBiometrics() { + return false; + } + + @Override public int binderGetCallingUid() { return Process.SYSTEM_UID; } 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 2627ec762d7a..c072d4e28e81 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 class AppChangeTransitionTests extends WindowTestsBase { 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 afadc7978b47..b91f3ecd78c2 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 @@ public class AppTransitionTests extends WindowTestsBase { @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 108ee180b4b7..e007c8651454 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 @@ package com.android.server.wm; 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 static org.mockito.ArgumentMatchers.eq; 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.ArgumentCaptor; 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 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { private TestAppWindowToken mToken; @Mock - private Transaction mTransaction; - @Mock private AnimationAdapter mSpec; @Before @@ -65,7 +63,6 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { 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 1dd72ec4fd71..2c575f59a020 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 @@ import org.junit.Test; * Tests for the {@link AppWindowToken} class. * * Build/Install/Run: - * atest FrameworksServicesTests:AppWindowTokenTests + * atest WmTests:AppWindowTokenTests */ @SmallTest @Presubmit @@ -76,9 +76,9 @@ public class AppWindowTokenTests extends WindowTestsBase { 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 b1b8e8ca990c..69f7ced5d90c 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 @@ public class DisplayContentTests extends WindowTestsBase { @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 87336745568e..1c10ffb01f8e 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.same; 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 @@ public class DisplayRotationTests { @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 @@ public class DisplayRotationTests { @Test public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception { - mBuilder.mIsDefaultDisplay = false; - - mBuilder.build(); + mBuilder.setIsDefaultDisplay(false).build(); thawRotation(); @@ -203,14 +203,22 @@ public class DisplayRotationTests { 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,17 +363,15 @@ public class DisplayRotationTests { when(mMockDisplayPolicy.isAwake()).thenReturn(true); when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); - mTarget.setFixedToUserRotation(true); + mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); mTarget.updateOrientationListener(); verifyOrientationListenerRegistration(0); } @Test - public void testNotEnablesSensor_ForceDefaultRotation() throws Exception { + 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, false, false); + configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false); when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); when(mMockDisplayPolicy.isAwake()).thenReturn(true); @@ -376,11 +382,9 @@ public class DisplayRotationTests { } @Test - public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception { + 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, true, false); + configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); when(mMockDisplayPolicy.isAwake()).thenReturn(true); @@ -391,11 +395,9 @@ public class DisplayRotationTests { } @Test - public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception { + public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception { mBuilder.build(); - when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation)) - .thenReturn(true); - configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); + configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false); when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); when(mMockDisplayPolicy.isAwake()).thenReturn(true); @@ -513,33 +515,27 @@ public class DisplayRotationTests { // Tests for Policy based Rotation // ================================= @Test - public void testReturnsUserRotation_ForceDefaultRotation() throws Exception { + 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, false, false); + configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false); assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_180)); } @Test - public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception { + 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, true, false); + configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_180)); } @Test - public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception { + public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception { mBuilder.build(); - when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation)) - .thenReturn(true); - configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); + configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false); assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_180)); @@ -591,7 +587,7 @@ public class DisplayRotationTests { 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 @@ public class DisplayRotationTests { @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 @@ public class DisplayRotationTests { 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 @@ public class DisplayRotationTests { .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 @@ public class DisplayRotationTests { .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 992d01766344..2dad18708499 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.doReturn; 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 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { } @Test - public void testNotFixedToUserRotationByDefault() { + public void testFixedToUserRotationDefault() { mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_0); @@ -419,13 +422,14 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { 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 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { 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 000000000000..66139e6b483a --- /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 000000000000..d919fc80fe0b --- /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 712cd1e5fdfa..366aceafd7bf 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 @@ public class SystemServicesTestRule implements TestRule { 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/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index d07230ef2ca3..6249bde3cea6 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 android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 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 @@ import org.junit.Test; * Tests for the {@link WallpaperController} class. * * Build/Install/Run: - * atest FrameworksServicesTests:WallpaperControllerTests + * atest WmTests:WallpaperControllerTests */ @SmallTest @Presubmit @@ -49,34 +47,29 @@ public class WallpaperControllerTests extends WindowTestsBase { 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 5bfa0c6e0885..da1defabeaaf 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.Build; 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 @@ class WindowTestUtils { 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 @@ class WindowTestUtils { 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 0d7d085ab1b4..d202e16a5ff4 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 android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 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.util.Log; 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 @@ class WindowTestsBase { 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 @@ class WindowTestsBase { // 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 @@ class WindowTestsBase { // stable state to clean up for consistency. waitUntilHandlersIdle(); - mWm.mTransactionFactory = mOriginalTransactionFactory; final LinkedList<WindowState> nonCommonWindows = new LinkedList<>(); synchronized (mWm.mGlobalLock) { diff --git a/telecomm/java/android/telecom/CallIdentification.java b/telecomm/java/android/telecom/CallIdentification.java index 87834fd5109d..cde7f608fa6a 100644 --- a/telecomm/java/android/telecom/CallIdentification.java +++ b/telecomm/java/android/telecom/CallIdentification.java @@ -45,13 +45,13 @@ public final class CallIdentification implements Parcelable { * {@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 @@ public final class CallIdentification implements Parcelable { * @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 @@ public final class CallIdentification implements Parcelable { * @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 @@ public final class CallIdentification implements Parcelable { * @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 @@ public final class CallIdentification implements Parcelable { * @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 @@ public final class CallIdentification implements Parcelable { * 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 @@ public final class CallIdentification implements Parcelable { 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 @@ public final class CallIdentification implements Parcelable { @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 @@ public final class CallIdentification implements Parcelable { @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 @@ public final class CallIdentification implements Parcelable { * * @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 @@ public final class CallIdentification implements Parcelable { * * @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 @@ public final class CallIdentification implements Parcelable { * * @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 @@ public final class CallIdentification implements Parcelable { * * @return The nuisance confidence. */ - public final @NuisanceConfidence - int getNuisanceConfidence() { + public final @NuisanceConfidence int getNuisanceConfidence() { return mNuisanceConfidence; } @@ -387,7 +386,7 @@ public final class CallIdentification implements Parcelable { * * @return The name of the app. */ - public final @NonNull String getCallScreeningAppName() { + public final @NonNull CharSequence getCallScreeningAppName() { return mCallScreeningAppName; } @@ -407,7 +406,7 @@ public final class CallIdentification implements Parcelable { * @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 ad98e3676733..c0444bb17ac7 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2992,9 +2992,9 @@ public class CarrierConfigManager { /* 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 a1aee6d8217f..3dc119950a59 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1569,6 +1569,17 @@ public class ServiceState implements Parcelable { /** @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 94f26a8a8d61..c28d1fb6d43e 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -2081,7 +2081,7 @@ public class SubscriptionManager { 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 @@ public class SubscriptionManager { * * @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 @@ public class SubscriptionManager { 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 0b72679cdf2a..f1869b06e308 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -10306,24 +10306,25 @@ public class TelephonyManager { /** * 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 @@ public class TelephonyManager { @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 75a4d8227e23..79e0aa15b6ab 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -275,7 +275,7 @@ interface ISub { 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 c54a60629ecb..d1838370d023 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1834,10 +1834,12 @@ interface ITelephony { 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 603c4c2870d7..030c3f495d0f 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -188,18 +188,17 @@ public interface TelephonyProperties */ 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 0cb8f22d8070..6765316a304b 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/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a10fb4ee1305..ed524f61e3bc 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.test.mock.MockContentResolver; 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { } // Add the request. + mNetworkRequests.put(request.requestId, request); super.handleAddRequest(request, score, factorySerialNumber); mExpectations.notify(); } @@ -817,11 +823,17 @@ public class ConnectivityServiceTest { } // 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index af9fdfbd364d..089b59a2704c 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -137,6 +137,16 @@ public class WifiInfo implements Parcelable { 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 @@ public class WifiInfo implements Parcelable { setEphemeral(false); setOsuAp(false); setNetworkSuggestionOrSpecifierPackageName(null); + setFQDN(null); + setProviderFriendlyName(null); txBad = 0; txSuccess = 0; rxSuccess = 0; @@ -257,6 +269,8 @@ public class WifiInfo implements Parcelable { 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 @@ public class WifiInfo implements Parcelable { } /** {@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 @@ public class WifiInfo implements Parcelable { 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 @@ public class WifiInfo implements Parcelable { 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 7caace6ec854..6c645fc8ce5d 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1738,10 +1738,7 @@ public class WifiManager { * @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 948dcfa47f59..b3034965b5fc 100644 --- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java +++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java @@ -36,6 +36,8 @@ public class WifiInfoTest { 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 @@ public class WifiInfoTest { 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 @@ public class WifiInfoTest { 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()); } } |