Merge "Cleanup the resources parsing a bit"
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java
index 3bfffbcd..aff3204 100644
--- a/apex/media/framework/java/android/media/MediaTranscodingManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodingManager.java
@@ -949,6 +949,8 @@
*
* @return the video track format to be used if transcoding should be performed,
* and null otherwise.
+ * @throws IllegalArgumentException if the hinted source video format contains invalid
+ * parameters.
*/
@Nullable
public MediaFormat resolveVideoFormat() {
@@ -959,20 +961,19 @@
MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
- int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH);
- int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT);
+ int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1);
+ int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1);
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException(
"Source Width and height must be larger than 0");
}
- float frameRate = 30.0f; // default to 30fps.
- if (mSrcVideoFormatHint.containsKey(MediaFormat.KEY_FRAME_RATE)) {
- frameRate = mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE);
- if (frameRate <= 0) {
- throw new IllegalArgumentException(
- "frameRate must be larger than 0");
- }
+ float frameRate =
+ mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0)
+ .floatValue();
+ if (frameRate <= 0) {
+ throw new IllegalArgumentException(
+ "frameRate must be larger than 0");
}
int bitrate = getAVCBitrate(width, height, frameRate);
diff --git a/boot/hiddenapi/hiddenapi-unsupported.txt b/boot/hiddenapi/hiddenapi-unsupported.txt
index 002d42d..522e88f 100644
--- a/boot/hiddenapi/hiddenapi-unsupported.txt
+++ b/boot/hiddenapi/hiddenapi-unsupported.txt
@@ -124,10 +124,8 @@
Landroid/content/pm/IPackageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageManager$Stub$Proxy;->checkUidPermission(Ljava/lang/String;I)I
Landroid/content/pm/IPackageManager$Stub$Proxy;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getInstallLocation()I
Landroid/content/pm/IPackageManager$Stub$Proxy;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang/String;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
diff --git a/core/api/current.txt b/core/api/current.txt
index 6f58a38..b40a3e5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9037,11 +9037,15 @@
public final class BluetoothClass implements android.os.Parcelable {
method public int describeContents();
+ method public boolean doesClassMatch(int);
method public int getDeviceClass();
method public int getMajorDeviceClass();
method public boolean hasService(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR;
+ field public static final int PROFILE_A2DP = 1; // 0x1
+ field public static final int PROFILE_HEADSET = 0; // 0x0
+ field public static final int PROFILE_HID = 3; // 0x3
}
public static class BluetoothClass.Device {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 24ea184..dd1760c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -257,7 +257,7 @@
field public static final String REQUEST_COMPANION_PROFILE_APP_STREAMING = "android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING";
field public static final String REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION = "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION";
field public static final String REQUEST_COMPANION_SELF_MANAGED = "android.permission.REQUEST_COMPANION_SELF_MANAGED";
- field public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
+ field @Deprecated public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
field public static final String RESTART_WIFI_SUBSYSTEM = "android.permission.RESTART_WIFI_SUBSYSTEM";
@@ -268,7 +268,7 @@
field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final String ROTATE_SURFACE_FLINGER = "android.permission.ROTATE_SURFACE_FLINGER";
field public static final String SCHEDULE_PRIORITIZED_ALARM = "android.permission.SCHEDULE_PRIORITIZED_ALARM";
- field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
+ field @Deprecated public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
@@ -728,6 +728,10 @@
field public static final String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
}
+ public final class GameManager {
+ method @RequiresPermission("android.permission.MANAGE_GAME_MODE") public void setGameMode(@NonNull String, int);
+ }
+
public abstract class InstantAppResolverService extends android.app.Service {
ctor public InstantAppResolverService();
method public final void attachBaseContext(android.content.Context);
@@ -2020,6 +2024,13 @@
method public void onOobData(int, @NonNull android.bluetooth.OobData);
}
+ public final class BluetoothClass implements android.os.Parcelable {
+ field public static final int PROFILE_A2DP_SINK = 6; // 0x6
+ field public static final int PROFILE_NAP = 5; // 0x5
+ field public static final int PROFILE_OPP = 2; // 0x2
+ field public static final int PROFILE_PANU = 4; // 0x4
+ }
+
public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
@@ -2460,7 +2471,7 @@
field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
field public static final String NETD_SERVICE = "netd";
- field public static final String NETWORK_SCORE_SERVICE = "network_score";
+ field @Deprecated public static final String NETWORK_SCORE_SERVICE = "network_score";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_CONTROLLER_SERVICE = "permission_controller";
field public static final String PERMISSION_SERVICE = "permission";
@@ -7696,15 +7707,15 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
- public class NetworkKey implements android.os.Parcelable {
- ctor public NetworkKey(android.net.WifiKey);
- method @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
- field public static final int TYPE_WIFI = 1; // 0x1
- field public final int type;
- field public final android.net.WifiKey wifiKey;
+ @Deprecated public class NetworkKey implements android.os.Parcelable {
+ ctor @Deprecated public NetworkKey(android.net.WifiKey);
+ method @Deprecated @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
+ method @Deprecated public int describeContents();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
+ field @Deprecated public static final int TYPE_WIFI = 1; // 0x1
+ field @Deprecated public final int type;
+ field @Deprecated public final android.net.WifiKey wifiKey;
}
public abstract class NetworkRecommendationProvider {
@@ -7713,31 +7724,31 @@
method public abstract void onRequestScores(android.net.NetworkKey[]);
}
- public class NetworkScoreManager {
- method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
- method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
- method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage();
- method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
- method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(@NonNull java.util.Collection<android.net.NetworkKey>) throws java.lang.SecurityException;
- method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
- method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
+ @Deprecated public class NetworkScoreManager {
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(@NonNull java.util.Collection<android.net.NetworkKey>) throws java.lang.SecurityException;
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
- field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
- field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
- field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
+ field @Deprecated public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
+ field @Deprecated public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
+ field @Deprecated public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
- field public static final String EXTRA_NEW_SCORER = "newScorer";
+ field @Deprecated public static final String EXTRA_NEW_SCORER = "newScorer";
field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
- field public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
- field public static final int SCORE_FILTER_NONE = 0; // 0x0
- field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
+ field @Deprecated public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
+ field @Deprecated public static final int SCORE_FILTER_NONE = 0; // 0x0
+ field @Deprecated public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
}
- public abstract static class NetworkScoreManager.NetworkScoreCallback {
- ctor public NetworkScoreManager.NetworkScoreCallback();
- method public abstract void onScoresInvalidated();
- method public abstract void onScoresUpdated(@NonNull java.util.Collection<android.net.ScoredNetwork>);
+ @Deprecated public abstract static class NetworkScoreManager.NetworkScoreCallback {
+ ctor @Deprecated public NetworkScoreManager.NetworkScoreCallback();
+ method @Deprecated public abstract void onScoresInvalidated();
+ method @Deprecated public abstract void onScoresUpdated(@NonNull java.util.Collection<android.net.ScoredNetwork>);
}
public abstract class NetworkSpecifier {
@@ -7776,35 +7787,35 @@
ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
}
- public class RssiCurve implements android.os.Parcelable {
- ctor public RssiCurve(int, int, byte[]);
- ctor public RssiCurve(int, int, byte[], int);
- method public int describeContents();
- method public byte lookupScore(int);
- method public byte lookupScore(int, boolean);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.RssiCurve> CREATOR;
- field public final int activeNetworkRssiBoost;
- field public final int bucketWidth;
- field public final byte[] rssiBuckets;
- field public final int start;
+ @Deprecated public class RssiCurve implements android.os.Parcelable {
+ ctor @Deprecated public RssiCurve(int, int, byte[]);
+ ctor @Deprecated public RssiCurve(int, int, byte[], int);
+ method @Deprecated public int describeContents();
+ method @Deprecated public byte lookupScore(int);
+ method @Deprecated public byte lookupScore(int, boolean);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.RssiCurve> CREATOR;
+ field @Deprecated public final int activeNetworkRssiBoost;
+ field @Deprecated public final int bucketWidth;
+ field @Deprecated public final byte[] rssiBuckets;
+ field @Deprecated public final int start;
}
- public class ScoredNetwork implements android.os.Parcelable {
- ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
- ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
- ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, @Nullable android.os.Bundle);
- method public int calculateBadge(int);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
- field public static final String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
- field public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
- field @NonNull public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
- field @Nullable public final android.os.Bundle attributes;
- field public final boolean meteredHint;
- field public final android.net.NetworkKey networkKey;
- field public final android.net.RssiCurve rssiCurve;
+ @Deprecated public class ScoredNetwork implements android.os.Parcelable {
+ ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
+ ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
+ ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, @Nullable android.os.Bundle);
+ method @Deprecated public int calculateBadge(int);
+ method @Deprecated public int describeContents();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
+ field @Deprecated public static final String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
+ field @Deprecated public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+ field @Deprecated @Nullable public final android.os.Bundle attributes;
+ field @Deprecated public final boolean meteredHint;
+ field @Deprecated public final android.net.NetworkKey networkKey;
+ field @Deprecated public final android.net.RssiCurve rssiCurve;
}
public class TrafficStats {
@@ -7831,13 +7842,13 @@
ctor public WebAddress(String) throws android.net.ParseException;
}
- public class WifiKey implements android.os.Parcelable {
- ctor public WifiKey(String, String);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.WifiKey> CREATOR;
- field public final String bssid;
- field public final String ssid;
+ @Deprecated public class WifiKey implements android.os.Parcelable {
+ ctor @Deprecated public WifiKey(String, String);
+ method @Deprecated public int describeContents();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.WifiKey> CREATOR;
+ field @Deprecated public final String bssid;
+ field @Deprecated public final String ssid;
}
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 4b7a9df..c1ab070 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -267,10 +267,6 @@
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
}
- public final class GameManager {
- method @RequiresPermission("android.permission.MANAGE_GAME_MODE") public void setGameMode(@NonNull String, int);
- }
-
public abstract class HomeVisibilityListener {
ctor public HomeVisibilityListener();
method public abstract void onHomeVisibilityChanged(boolean);
@@ -1835,11 +1831,6 @@
method public int getAudioUsage();
}
- public static final class VibrationAttributes.Builder {
- ctor public VibrationAttributes.Builder(@NonNull android.media.AudioAttributes, @NonNull android.os.VibrationEffect);
- ctor public VibrationAttributes.Builder(@NonNull android.os.VibrationAttributes, @NonNull android.os.VibrationEffect);
- }
-
public abstract class VibrationEffect implements android.os.Parcelable {
method public static android.os.VibrationEffect get(int);
method public static android.os.VibrationEffect get(int, boolean);
@@ -1856,13 +1847,9 @@
}
public static final class VibrationEffect.Composed extends android.os.VibrationEffect {
- method @NonNull public android.os.VibrationEffect.Composed applyEffectStrength(int);
method public long getDuration();
method public int getRepeatIndex();
method @NonNull public java.util.List<android.os.vibrator.VibrationEffectSegment> getSegments();
- method @NonNull public android.os.VibrationEffect.Composed resolve(int);
- method @NonNull public android.os.VibrationEffect.Composed scale(float);
- method public void validate();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR;
}
@@ -2010,72 +1997,47 @@
package android.os.vibrator {
public final class PrebakedSegment extends android.os.vibrator.VibrationEffectSegment {
- method @NonNull public android.os.vibrator.PrebakedSegment applyEffectStrength(int);
method public int describeContents();
method public long getDuration();
method public int getEffectId();
method public int getEffectStrength();
- method public boolean hasNonZeroAmplitude();
- method @NonNull public android.os.vibrator.PrebakedSegment resolve(int);
- method @NonNull public android.os.vibrator.PrebakedSegment scale(float);
method public boolean shouldFallback();
- method public void validate();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.PrebakedSegment> CREATOR;
}
public final class PrimitiveSegment extends android.os.vibrator.VibrationEffectSegment {
- method @NonNull public android.os.vibrator.PrimitiveSegment applyEffectStrength(int);
method public int describeContents();
method public int getDelay();
method public long getDuration();
method public int getPrimitiveId();
method public float getScale();
- method public boolean hasNonZeroAmplitude();
- method @NonNull public android.os.vibrator.PrimitiveSegment resolve(int);
- method @NonNull public android.os.vibrator.PrimitiveSegment scale(float);
- method public void validate();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.PrimitiveSegment> CREATOR;
}
public final class RampSegment extends android.os.vibrator.VibrationEffectSegment {
- method @NonNull public android.os.vibrator.RampSegment applyEffectStrength(int);
method public int describeContents();
method public long getDuration();
method public float getEndAmplitude();
method public float getEndFrequency();
method public float getStartAmplitude();
method public float getStartFrequency();
- method public boolean hasNonZeroAmplitude();
- method @NonNull public android.os.vibrator.RampSegment resolve(int);
- method @NonNull public android.os.vibrator.RampSegment scale(float);
- method public void validate();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.RampSegment> CREATOR;
}
public final class StepSegment extends android.os.vibrator.VibrationEffectSegment {
- method @NonNull public android.os.vibrator.StepSegment applyEffectStrength(int);
method public int describeContents();
method public float getAmplitude();
method public long getDuration();
method public float getFrequency();
- method public boolean hasNonZeroAmplitude();
- method @NonNull public android.os.vibrator.StepSegment resolve(int);
- method @NonNull public android.os.vibrator.StepSegment scale(float);
- method public void validate();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.StepSegment> CREATOR;
}
public abstract class VibrationEffectSegment implements android.os.Parcelable {
- method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T applyEffectStrength(int);
method public abstract long getDuration();
- method public abstract boolean hasNonZeroAmplitude();
- method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T resolve(int);
- method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T scale(float);
- method public abstract void validate();
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.VibrationEffectSegment> CREATOR;
}
@@ -2195,7 +2157,7 @@
field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
field public static final String USER_PREFERRED_RESOLUTION_WIDTH = "user_preferred_resolution_width";
- field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
+ field @Deprecated public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java
index b324fb6..78759db 100644
--- a/core/java/android/app/GameManager.java
+++ b/core/java/android/app/GameManager.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.content.Context;
import android.os.Handler;
@@ -125,7 +125,7 @@
*
* @hide
*/
- @TestApi
+ @SystemApi
@UserHandleAware
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public void setGameMode(@NonNull String packageName, @GameMode int gameMode) {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0476307..089c269 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -200,6 +200,8 @@
import android.scheduling.SchedulingFrameworkInitializer;
import android.security.FileIntegrityManager;
import android.security.IFileIntegrityService;
+import android.security.attestationverification.AttestationVerificationManager;
+import android.security.attestationverification.IAttestationVerificationManagerService;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -1425,6 +1427,19 @@
return new FileIntegrityManager(ctx.getOuterContext(),
IFileIntegrityService.Stub.asInterface(b));
}});
+
+ registerService(Context.ATTESTATION_VERIFICATION_SERVICE,
+ AttestationVerificationManager.class,
+ new CachedServiceFetcher<AttestationVerificationManager>() {
+ @Override
+ public AttestationVerificationManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.ATTESTATION_VERIFICATION_SERVICE);
+ return new AttestationVerificationManager(ctx.getOuterContext(),
+ IAttestationVerificationManagerService.Stub.asInterface(b));
+ }});
+
//CHECKSTYLE:ON IndentationCheck
registerService(Context.APP_INTEGRITY_SERVICE, AppIntegrityManager.class,
new CachedServiceFetcher<AppIntegrityManager>() {
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 7fe18a0..69525b5 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -327,21 +328,26 @@
return Arrays.copyOfRange(bytes, 1, bytes.length);
}
- /** @hide */
- @UnsupportedAppUsage
public static final int PROFILE_HEADSET = 0;
- /** @hide */
- @UnsupportedAppUsage
+
public static final int PROFILE_A2DP = 1;
+
/** @hide */
+ @SystemApi
public static final int PROFILE_OPP = 2;
- /** @hide */
+
public static final int PROFILE_HID = 3;
+
/** @hide */
+ @SystemApi
public static final int PROFILE_PANU = 4;
+
/** @hide */
+ @SystemApi
public static final int PROFILE_NAP = 5;
+
/** @hide */
+ @SystemApi
public static final int PROFILE_A2DP_SINK = 6;
/**
@@ -350,11 +356,9 @@
* given class bits might support specified profile. It is not accurate for all
* devices. It tries to err on the side of false positives.
*
- * @param profile The profile to be checked
- * @return True if this device might support specified profile.
- * @hide
+ * @param profile the profile to be checked
+ * @return whether this device supports specified profile
*/
- @UnsupportedAppUsage
public boolean doesClassMatch(int profile) {
if (profile == PROFILE_A2DP) {
if (hasService(Service.RENDER)) {
diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java
index f70e662..3f02aa2 100644
--- a/core/java/android/companion/AssociationInfo.java
+++ b/core/java/android/companion/AssociationInfo.java
@@ -118,7 +118,7 @@
/** @hide */
public @Nullable String getDeviceMacAddressAsString() {
- return mDeviceMacAddress != null ? mDeviceMacAddress.toString() : null;
+ return mDeviceMacAddress != null ? mDeviceMacAddress.toString().toUpperCase() : null;
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 05e2e87..2b75022 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3842,6 +3842,7 @@
UWB_SERVICE,
MEDIA_METRICS_SERVICE,
SUPPLEMENTAL_PROCESS_SERVICE,
+ //@hide: ATTESTATION_VERIFICATION_SERVICE,
//@hide: SAFETY_CENTER_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
@@ -5355,9 +5356,12 @@
* {@link android.net.NetworkScoreManager} for managing network scoring.
* @see #getSystemService(String)
* @see android.net.NetworkScoreManager
+ * @deprecated see https://developer.android.com/guide/topics/connectivity/wifi-suggest for
+ * alternative API to propose WiFi networks.
* @hide
*/
@SystemApi
+ @Deprecated
public static final String NETWORK_SCORE_SERVICE = "network_score";
/**
@@ -5740,6 +5744,15 @@
/**
* Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.security.attestationverification.AttestationVerificationManager}.
+ * @see #getSystemService(String)
+ * @see android.security.attestationverification.AttestationVerificationManager
+ * @hide
+ */
+ public static final String ATTESTATION_VERIFICATION_SERVICE = "attestation_verification";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve an
* {@link android.security.FileIntegrityManager}.
* @see #getSystemService(String)
* @see android.security.FileIntegrityManager
@@ -5883,6 +5896,16 @@
public static final String SAFETY_CENTER_SERVICE = "safety_center";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.nearby.NearbyManager} to discover nearby devices.
+ *
+ * @see #getSystemService(String)
+ * @see android.nearby.NearbyManager
+ * @hide
+ */
+ public static final String NEARBY_SERVICE = "nearby";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 516156d..1c82b38 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -69,41 +69,34 @@
void checkPackageStartable(String packageName, int userId);
@UnsupportedAppUsage(trackingBug = 171933273)
boolean isPackageAvailable(String packageName, int userId);
- @UnsupportedAppUsage
- PackageInfo getPackageInfo(String packageName, int flags, int userId);
+ PackageInfo getPackageInfo(String packageName, long flags, int userId);
PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
- int flags, int userId);
- @UnsupportedAppUsage
- int getPackageUid(String packageName, int flags, int userId);
- int[] getPackageGids(String packageName, int flags, int userId);
+ long flags, int userId);
+ int getPackageUid(String packageName, long flags, int userId);
+ int[] getPackageGids(String packageName, long flags, int userId);
@UnsupportedAppUsage
String[] currentToCanonicalPackageNames(in String[] names);
@UnsupportedAppUsage
String[] canonicalToCurrentPackageNames(in String[] names);
- @UnsupportedAppUsage
- ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
+ ApplicationInfo getApplicationInfo(String packageName, long flags, int userId);
/**
* @return the target SDK for the given package name, or -1 if it cannot be retrieved
*/
int getTargetSdkVersion(String packageName);
- @UnsupportedAppUsage
- ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
+ ActivityInfo getActivityInfo(in ComponentName className, long flags, int userId);
boolean activitySupportsIntent(in ComponentName className, in Intent intent,
String resolvedType);
- @UnsupportedAppUsage
- ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
+ ActivityInfo getReceiverInfo(in ComponentName className, long flags, int userId);
- @UnsupportedAppUsage
- ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
+ ServiceInfo getServiceInfo(in ComponentName className, long flags, int userId);
- @UnsupportedAppUsage
- ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
+ ProviderInfo getProviderInfo(in ComponentName className, long flags, int userId);
boolean isProtectedBroadcast(String actionName);
@@ -133,33 +126,31 @@
@UnsupportedAppUsage
boolean isUidPrivileged(int uid);
- @UnsupportedAppUsage
- ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
+ ResolveInfo resolveIntent(in Intent intent, String resolvedType, long flags, int userId);
ResolveInfo findPersistentPreferredActivity(in Intent intent, int userId);
boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
ParceledListSlice queryIntentActivities(in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
ParceledListSlice queryIntentActivityOptions(
in ComponentName caller, in Intent[] specifics,
in String[] specificTypes, in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
ParceledListSlice queryIntentReceivers(in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
ResolveInfo resolveService(in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
ParceledListSlice queryIntentServices(in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
ParceledListSlice queryIntentContentProviders(in Intent intent,
- String resolvedType, int flags, int userId);
+ String resolvedType, long flags, int userId);
/**
* This implements getInstalledPackages via a "last returned row"
@@ -167,8 +158,7 @@
* limit that kicks in when flags are included that bloat up the data
* returned.
*/
- @UnsupportedAppUsage
- ParceledListSlice getInstalledPackages(int flags, in int userId);
+ ParceledListSlice getInstalledPackages(long flags, in int userId);
/**
* This implements getPackagesHoldingPermissions via a "last returned row"
@@ -177,7 +167,7 @@
* returned.
*/
ParceledListSlice getPackagesHoldingPermissions(in String[] permissions,
- int flags, int userId);
+ long flags, int userId);
/**
* This implements getInstalledApplications via a "last returned row"
@@ -185,18 +175,17 @@
* limit that kicks in when flags are included that bloat up the data
* returned.
*/
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- ParceledListSlice getInstalledApplications(int flags, int userId);
+ ParceledListSlice getInstalledApplications(long flags, int userId);
/**
* Retrieve all applications that are marked as persistent.
*
- * @return A List<applicationInfo> containing one entry for each persistent
+ * @return A List<ApplicationInfo> containing one entry for each persistent
* application.
*/
ParceledListSlice getPersistentApplications(int flags);
- ProviderInfo resolveContentProvider(String name, int flags, int userId);
+ ProviderInfo resolveContentProvider(String name, long flags, int userId);
/**
* Retrieve sync information for all content providers.
@@ -211,7 +200,7 @@
inout List<ProviderInfo> outInfo);
ParceledListSlice queryContentProviders(
- String processName, int uid, int flags, String metaDataKey);
+ String processName, int uid, long flags, String metaDataKey);
@UnsupportedAppUsage
InstrumentationInfo getInstrumentationInfo(
@@ -690,9 +679,9 @@
int getInstallReason(String packageName, int userId);
- ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId);
+ ParceledListSlice getSharedLibraries(in String packageName, long flags, int userId);
- ParceledListSlice getDeclaredSharedLibraries(in String packageName, int flags, int userId);
+ ParceledListSlice getDeclaredSharedLibraries(in String packageName, long flags, int userId);
boolean canRequestPackageInstalls(String packageName, int userId);
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index cc4782a..aa57806 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -10,6 +10,9 @@
"path": "frameworks/base/services/tests/PackageManagerComponentOverrideTests"
},
{
+ "path": "frameworks/base/services/tests/servicestests/src/com/android/server/pm"
+ },
+ {
"path": "cts/tests/tests/packageinstaller"
},
{
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index ef124c7..b11b38a 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -76,7 +76,7 @@
@Nullable
public static PackageInfo generate(ParsingPackageRead pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, FrameworkPackageUserState state, int userId) {
return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions,
state, userId, null);
@@ -90,7 +90,7 @@
@Nullable
private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, FrameworkPackageUserState state, int userId,
@Nullable ApexInfo apexInfo) {
ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
@@ -190,7 +190,7 @@
@Nullable
public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, FrameworkPackageUserState state, int userId,
@Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
if (!checkUseInstalled(pkg, state, flags)) {
@@ -210,9 +210,9 @@
*/
@NonNull
public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
- Set<String> grantedPermissions, FrameworkPackageUserState state, int userId,
- @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime,
+ long lastUpdateTime, Set<String> grantedPermissions, FrameworkPackageUserState state,
+ int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
PackageInfo pi = new PackageInfo();
pi.packageName = pkg.getPackageName();
pi.splitNames = pkg.getSplitNames();
@@ -365,7 +365,8 @@
@Nullable
public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,
- @PackageManager.ApplicationInfoFlags int flags, FrameworkPackageUserState state, int userId) {
+ @PackageManager.ApplicationInfoFlags long flags, FrameworkPackageUserState state,
+ int userId) {
if (pkg == null) {
return null;
}
@@ -392,8 +393,8 @@
*/
@NonNull
public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
- @PackageManager.ApplicationInfoFlags int flags, @NonNull FrameworkPackageUserState state,
- int userId, boolean assignUserFields) {
+ @PackageManager.ApplicationInfoFlags long flags,
+ @NonNull FrameworkPackageUserState state, int userId, boolean assignUserFields) {
// Make shallow copy so we can store the metadata/libraries safely
ApplicationInfo ai = ((ParsingPackageHidden) pkg).toAppInfoWithoutState();
@@ -406,7 +407,7 @@
return ai;
}
- private static void updateApplicationInfo(ApplicationInfo ai, int flags,
+ private static void updateApplicationInfo(ApplicationInfo ai, long flags,
FrameworkPackageUserState state) {
if ((flags & PackageManager.GET_META_DATA) == 0) {
ai.metaData = null;
@@ -452,8 +453,8 @@
@Nullable
public static ApplicationInfo generateDelegateApplicationInfo(@Nullable ApplicationInfo ai,
- @PackageManager.ApplicationInfoFlags int flags, @NonNull FrameworkPackageUserState state,
- int userId) {
+ @PackageManager.ApplicationInfoFlags long flags,
+ @NonNull FrameworkPackageUserState state, int userId) {
if (ai == null || !checkUseInstalledOrHidden(flags, state, ai)) {
return null;
}
@@ -469,7 +470,7 @@
@Nullable
public static ActivityInfo generateDelegateActivityInfo(@Nullable ActivityInfo a,
- @PackageManager.ComponentInfoFlags int flags, @NonNull FrameworkPackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, @NonNull FrameworkPackageUserState state,
int userId) {
if (a == null || !checkUseInstalledOrHidden(flags, state, a.applicationInfo)) {
return null;
@@ -484,7 +485,7 @@
@Nullable
public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId) {
if (a == null) return null;
if (!checkUseInstalled(pkg, state, flags)) {
@@ -504,12 +505,12 @@
* This bypasses critical checks that are necessary for usage with data passed outside of system
* server.
* <p>
- * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, int,
+ * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, long,
* FrameworkPackageUserState, ApplicationInfo, int)}.
*/
@NonNull
public static ActivityInfo generateActivityInfoUnchecked(@NonNull ParsedActivity a,
- @PackageManager.ComponentInfoFlags int flags,
+ @PackageManager.ComponentInfoFlags long flags,
@NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ActivityInfo ai = new ActivityInfo();
@@ -550,13 +551,14 @@
@Nullable
public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state, int userId) {
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
+ int userId) {
return generateActivityInfo(pkg, a, flags, state, null, userId);
}
@Nullable
public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId) {
if (s == null) return null;
if (!checkUseInstalled(pkg, state, flags)) {
@@ -576,12 +578,12 @@
* This bypasses critical checks that are necessary for usage with data passed outside of system
* server.
* <p>
- * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, int, FrameworkPackageUserState,
- * ApplicationInfo, int)}.
+ * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, long,
+ * FrameworkPackageUserState, ApplicationInfo, int)}.
*/
@NonNull
public static ServiceInfo generateServiceInfoUnchecked(@NonNull ParsedService s,
- @PackageManager.ComponentInfoFlags int flags,
+ @PackageManager.ComponentInfoFlags long flags,
@NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ServiceInfo si = new ServiceInfo();
@@ -600,13 +602,14 @@
@Nullable
public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state, int userId) {
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
+ int userId) {
return generateServiceInfo(pkg, s, flags, state, null, userId);
}
@Nullable
public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId) {
if (p == null) return null;
if (!checkUseInstalled(pkg, state, flags)) {
@@ -626,12 +629,12 @@
* This bypasses critical checks that are necessary for usage with data passed outside of system
* server.
* <p>
- * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, int,
+ * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, long,
* FrameworkPackageUserState, ApplicationInfo, int)}.
*/
@NonNull
public static ProviderInfo generateProviderInfoUnchecked(@NonNull ParsedProvider p,
- @PackageManager.ComponentInfoFlags int flags,
+ @PackageManager.ComponentInfoFlags long flags,
@NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ProviderInfo pi = new ProviderInfo();
@@ -661,17 +664,18 @@
@Nullable
public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
- @PackageManager.ComponentInfoFlags int flags, FrameworkPackageUserState state, int userId) {
+ @PackageManager.ComponentInfoFlags long flags, FrameworkPackageUserState state,
+ int userId) {
return generateProviderInfo(pkg, p, flags, state, null, userId);
}
/**
- * @param assignUserFields see {@link #generateApplicationInfoUnchecked(ParsingPackageRead, int,
- * FrameworkPackageUserState, int, boolean)}
+ * @param assignUserFields see {@link #generateApplicationInfoUnchecked(ParsingPackageRead,
+ * long, FrameworkPackageUserState, int, boolean)}
*/
@Nullable
public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
- ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId,
+ ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags long flags, int userId,
boolean assignUserFields) {
if (i == null) return null;
@@ -702,7 +706,7 @@
@Nullable
public static PermissionInfo generatePermissionInfo(ParsedPermission p,
- @PackageManager.ComponentInfoFlags int flags) {
+ @PackageManager.ComponentInfoFlags long flags) {
if (p == null) return null;
PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
@@ -725,7 +729,7 @@
@Nullable
public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
- @PackageManager.ComponentInfoFlags int flags) {
+ @PackageManager.ComponentInfoFlags long flags) {
if (pg == null) return null;
PermissionGroupInfo pgi = new PermissionGroupInfo(
@@ -753,8 +757,8 @@
return new Attribution(pa.getTag(), pa.getLabel());
}
- private static boolean checkUseInstalledOrHidden(int flags, @NonNull FrameworkPackageUserState state,
- @Nullable ApplicationInfo appInfo) {
+ private static boolean checkUseInstalledOrHidden(long flags,
+ @NonNull FrameworkPackageUserState state, @Nullable ApplicationInfo appInfo) {
// Returns false if the package is hidden system app until installed.
if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
&& !state.isInstalled()
@@ -882,8 +886,8 @@
return privateFlagsExt;
}
- private static boolean checkUseInstalled(ParsingPackageRead pkg, FrameworkPackageUserState state,
- @PackageManager.PackageInfoFlags int flags) {
+ private static boolean checkUseInstalled(ParsingPackageRead pkg,
+ FrameworkPackageUserState state, @PackageManager.PackageInfoFlags long flags) {
// If available for the target user
return PackageUserStateUtils.isAvailable(state, flags);
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index f07f382..d5957a2 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -334,7 +334,7 @@
@DataClass.ParcelWith(ForInternedString.class)
private String backupAgentName;
private int banner;
- private int category;
+ private int category = ApplicationInfo.CATEGORY_UNDEFINED;
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
private String classLoaderName;
diff --git a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
index 1ac9739..0334601 100644
--- a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
@@ -170,13 +170,13 @@
}
public static boolean isMatch(FrameworkPackageUserState state, boolean isSystem,
- boolean isPackageEnabled, ParsedMainComponent component, int flags) {
+ boolean isPackageEnabled, ParsedMainComponent component, long flags) {
return PackageUserStateUtils.isMatch(state, isSystem, isPackageEnabled,
component.isEnabled(), component.isDirectBootAware(), component.getName(), flags);
}
public static boolean isEnabled(FrameworkPackageUserState state, boolean isPackageEnabled,
- ParsedMainComponent parsedComponent, int flags) {
+ ParsedMainComponent parsedComponent, long flags) {
return PackageUserStateUtils.isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
parsedComponent.getName(), flags);
}
diff --git a/core/java/android/content/pm/pkg/PackageUserStateUtils.java b/core/java/android/content/pm/pkg/PackageUserStateUtils.java
index 9a800b0..468bff1 100644
--- a/core/java/android/content/pm/pkg/PackageUserStateUtils.java
+++ b/core/java/android/content/pm/pkg/PackageUserStateUtils.java
@@ -34,15 +34,15 @@
private static final boolean DEBUG = false;
private static final String TAG = "PackageUserStateUtils";
- public static boolean isMatch(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo,
- int flags) {
+ public static boolean isMatch(@NonNull FrameworkPackageUserState state,
+ ComponentInfo componentInfo, long flags) {
return isMatch(state, componentInfo.applicationInfo.isSystemApp(),
componentInfo.applicationInfo.enabled, componentInfo.enabled,
componentInfo.directBootAware, componentInfo.name, flags);
}
public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem,
- boolean isPackageEnabled, ParsedMainComponent component, int flags) {
+ boolean isPackageEnabled, ParsedMainComponent component, long flags) {
return isMatch(state, isSystem, isPackageEnabled, component.isEnabled(),
component.isDirectBootAware(), component.getName(), flags);
}
@@ -58,7 +58,7 @@
*/
public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem,
boolean isPackageEnabled, boolean isComponentEnabled,
- boolean isComponentDirectBootAware, String componentName, int flags) {
+ boolean isComponentDirectBootAware, String componentName, long flags) {
final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
if (!isAvailable(state, flags) && !(isSystem && matchUninstalled)) {
return reportIfDebug(false, flags);
@@ -81,7 +81,7 @@
return reportIfDebug(matchesUnaware || matchesAware, flags);
}
- public static boolean isAvailable(@NonNull FrameworkPackageUserState state, int flags) {
+ public static boolean isAvailable(@NonNull FrameworkPackageUserState state, long flags) {
// True if it is installed for this user and it is not hidden. If it is hidden,
// still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
@@ -91,7 +91,7 @@
&& (!state.isHidden() || matchUninstalled));
}
- public static boolean reportIfDebug(boolean result, int flags) {
+ public static boolean reportIfDebug(boolean result, long flags) {
if (DEBUG && !result) {
Slog.i(TAG, "No match!; flags: "
+ DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " "
@@ -101,13 +101,13 @@
}
public static boolean isEnabled(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo,
- int flags) {
+ long flags) {
return isEnabled(state, componentInfo.applicationInfo.enabled, componentInfo.enabled,
componentInfo.name, flags);
}
public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled,
- ParsedMainComponent parsedComponent, int flags) {
+ ParsedMainComponent parsedComponent, long flags) {
return isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
parsedComponent.getName(), flags);
}
@@ -115,8 +115,9 @@
/**
* Test if the given component is considered enabled.
*/
- public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled,
- boolean isComponentEnabled, String componentName, int flags) {
+ public static boolean isEnabled(@NonNull FrameworkPackageUserState state,
+ boolean isPackageEnabled, boolean isComponentEnabled, String componentName,
+ long flags) {
if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
return true;
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 83e1061..2985c75 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.graphics.Point;
import android.hardware.SensorManager;
+import android.media.projection.IMediaProjection;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
@@ -380,6 +381,31 @@
public abstract void onEarlyInteractivityChange(boolean interactive);
/**
+ * A special API for creates a virtual display with a DisplayPolicyController in system_server.
+ * <p>
+ * If this method is called without original calling uid, the caller must enforce the
+ * corresponding permissions according to the flags.
+ * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT}
+ * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT}
+ * {@link android.Manifest.permission#ADD_TRUSTED_DISPLAY}
+ * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}
+ * </p>
+ *
+ * @param virtualDisplayConfig The arguments for the virtual display configuration. See
+ * {@link VirtualDisplayConfig} for using it.
+ * @param callback Callback to call when the virtual display's state changes, or null if none.
+ * @param projection MediaProjection token.
+ * @param packageName The package name of the app.
+ * @param controller The DisplayWindowPolicyControl that can control what contents are
+ * allowed to be displayed.
+ * @return The newly created virtual display id , or {@link Display#INVALID_DISPLAY} if the
+ * virtual display cannot be created.
+ */
+ public abstract int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+ IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+ DisplayWindowPolicyController controller);
+
+ /**
* Get {@link DisplayWindowPolicyController} associated to the {@link DisplayInfo#displayId}
*
* @param displayId The id of the display.
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index e5d8620..6f0c944 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1016,9 +1016,8 @@
}
/**
- * Queries the framework about whether any physical keys exist on the
- * any keyboard attached to the device that are capable of producing the given
- * array of key codes.
+ * Queries the framework about whether any physical keys exist on any currently attached input
+ * devices that are capable of producing the given array of key codes.
*
* @param keyCodes The array of key codes to query.
* @return A new array of the same size as the key codes array whose elements
@@ -1032,11 +1031,10 @@
}
/**
- * Queries the framework about whether any physical keys exist on the
- * any keyboard attached to the device that are capable of producing the given
- * array of key codes.
+ * Queries the framework about whether any physical keys exist on the specified input device
+ * that are capable of producing the given array of key codes.
*
- * @param id The id of the device to query.
+ * @param id The id of the input device to query or -1 to consult all devices.
* @param keyCodes The array of key codes to query.
* @return A new array of the same size as the key codes array whose elements are set to true
* if the given device could produce the corresponding key code at the same index in the key
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index 5cd4eb5..5e0e1b7 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -35,8 +35,10 @@
/**
* Information which identifies a specific network.
*
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
* @hide
*/
+@Deprecated
@SystemApi
// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
// type, so that all networks appear the same and can be scored without concern to the network type
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 0ba2663..7b8b5c0 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -51,9 +51,13 @@
* permission.
* </ul>
*
+ * @deprecated No longer functional on {@link android.os.Build.VERSION_CODES#TIRAMISU} and above.
+ * See https://developer.android.com/guide/topics/connectivity/wifi-suggest for
+ * alternative APIs to suggest/configure Wi-Fi networks.
* @hide
*/
@SystemApi
+@Deprecated
@SystemService(Context.NETWORK_SCORE_SERVICE)
public class NetworkScoreManager {
private static final String TAG = "NetworkScoreManager";
@@ -245,7 +249,7 @@
* or {@link permission#REQUEST_NETWORK_SCORES} permissions.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
- android.Manifest.permission.REQUEST_NETWORK_SCORES})
+ android.Manifest.permission.REQUEST_NETWORK_SCORES})
public String getActiveScorerPackage() {
try {
return mService.getActiveScorerPackage();
@@ -322,7 +326,7 @@
* hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
- android.Manifest.permission.REQUEST_NETWORK_SCORES})
+ android.Manifest.permission.REQUEST_NETWORK_SCORES})
public boolean clearScores() throws SecurityException {
try {
return mService.clearScores();
@@ -344,7 +348,7 @@
*/
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
- android.Manifest.permission.REQUEST_NETWORK_SCORES})
+ android.Manifest.permission.REQUEST_NETWORK_SCORES})
public boolean setActiveScorer(String packageName) throws SecurityException {
try {
return mService.setActiveScorer(packageName);
@@ -362,7 +366,7 @@
* hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
- android.Manifest.permission.REQUEST_NETWORK_SCORES})
+ android.Manifest.permission.REQUEST_NETWORK_SCORES})
public void disableScoring() throws SecurityException {
try {
mService.disableScoring();
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 668e966..02cafb5 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -50,8 +50,10 @@
* the system.
*
* @see ScoredNetwork
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
* @hide
*/
+@Deprecated
@SystemApi
public class RssiCurve implements Parcelable {
private static final int DEFAULT_ACTIVE_NETWORK_RSSI_BOOST = 25;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 64b3bf1..a46bdd9a 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -29,8 +29,10 @@
/**
* A network identifier along with a score for the quality of that network.
*
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
* @hide
*/
+@Deprecated
@SystemApi
public class ScoredNetwork implements Parcelable {
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index bc9d8c5..2e4ea89 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -29,8 +29,10 @@
* Information identifying a Wi-Fi network.
* @see NetworkKey
*
+ * @deprecated as part of the {@link NetworkScore} deprecation.
* @hide
*/
+@Deprecated
@SystemApi
public class WifiKey implements Parcelable {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a4a76a8..53484d2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -7354,9 +7354,11 @@
pw.print(getHistoryTagPoolUid(i));
pw.print(",\"");
String str = getHistoryTagPoolString(i);
- str = str.replace("\\", "\\\\");
- str = str.replace("\"", "\\\"");
- pw.print(str);
+ if (str != null) {
+ str = str.replace("\\", "\\\\");
+ str = str.replace("\"", "\\\"");
+ pw.print(str);
+ }
pw.print("\"");
pw.println();
}
diff --git a/core/java/android/os/CombinedVibration.java b/core/java/android/os/CombinedVibration.java
index aff55af..5f2c113 100644
--- a/core/java/android/os/CombinedVibration.java
+++ b/core/java/android/os/CombinedVibration.java
@@ -110,6 +110,20 @@
@TestApi
public abstract long getDuration();
+ /**
+ * Returns true if this effect could represent a touch haptic feedback.
+ *
+ * <p>It is strongly recommended that an instance of {@link VibrationAttributes} is specified
+ * for each vibration, with the correct usage. When a vibration is played with usage UNKNOWN,
+ * then this method will be used to classify the most common use case and make sure they are
+ * covered by the user settings for "Touch feedback".
+ *
+ * @hide
+ */
+ public boolean isHapticFeedbackCandidate() {
+ return false;
+ }
+
/** @hide */
public abstract void validate();
@@ -314,6 +328,12 @@
/** @hide */
@Override
+ public boolean isHapticFeedbackCandidate() {
+ return mEffect.isHapticFeedbackCandidate();
+ }
+
+ /** @hide */
+ @Override
public void validate() {
mEffect.validate();
}
@@ -431,6 +451,17 @@
/** @hide */
@Override
+ public boolean isHapticFeedbackCandidate() {
+ for (int i = 0; i < mEffects.size(); i++) {
+ if (!mEffects.valueAt(i).isHapticFeedbackCandidate()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** @hide */
+ @Override
public void validate() {
Preconditions.checkArgument(mEffects.size() > 0,
"There should be at least one effect set for a combined effect");
@@ -513,6 +544,9 @@
*/
@TestApi
public static final class Sequential extends CombinedVibration {
+ // If a vibration is playing more than 3 effects, it's probably not haptic feedback
+ private static final long MAX_HAPTIC_FEEDBACK_SEQUENCE_SIZE = 3;
+
private final List<CombinedVibration> mEffects;
private final List<Integer> mDelays;
@@ -575,6 +609,21 @@
/** @hide */
@Override
+ public boolean isHapticFeedbackCandidate() {
+ final int effectCount = mEffects.size();
+ if (effectCount > MAX_HAPTIC_FEEDBACK_SEQUENCE_SIZE) {
+ return false;
+ }
+ for (int i = 0; i < effectCount; i++) {
+ if (!mEffects.get(i).isHapticFeedbackCandidate()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** @hide */
+ @Override
public void validate() {
Preconditions.checkArgument(mEffects.size() > 0,
"There should be at least one effect set for a combined effect");
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 8308e8e..3f42164 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -60,6 +60,7 @@
List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
List<UserInfo> getProfiles(int userId, boolean enabledOnly);
int[] getProfileIds(int userId, boolean enabledOnly);
+ boolean isUserTypeEnabled(in String userType);
boolean canAddMoreUsersOfType(in String userType);
boolean canAddMoreProfilesToUser(in String userType, int userId, boolean allowedToRemoveOne);
boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index a828268..d0d6cb7 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -196,9 +196,6 @@
return;
}
CombinedVibration combinedEffect = CombinedVibration.createParallel(effect);
- // TODO(b/185351540): move this into VibratorManagerService once the touch vibration
- // heuristics is fixed and works for CombinedVibration. Make sure it's always applied.
- attributes = new VibrationAttributes.Builder(attributes, effect).build();
mVibratorManager.vibrate(uid, opPkg, combinedEffect, reason, attributes);
}
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index e5622a3..c690df2 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -223,9 +223,6 @@
CombinedVibration combined = CombinedVibration.startParallel()
.addVibrator(mVibratorInfo.getId(), vibe)
.combine();
- // TODO(b/185351540): move this into VibratorManagerService once the touch vibration
- // heuristics is fixed and works for CombinedVibration. Make sure it's always applied.
- attributes = new VibrationAttributes.Builder(attributes, vibe).build();
SystemVibratorManager.this.vibrate(uid, opPkg, combined, reason, attributes);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 79553e0..bc6dbd8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3958,6 +3958,25 @@
}
/**
+ * Checks whether this device supports users of the given user type.
+ *
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_SECONDARY}.
+ * @return true if the creation of users of the given user type is enabled on this device.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.CREATE_USERS
+ })
+ public boolean isUserTypeEnabled(@NonNull String userType) {
+ try {
+ return mService.isUserTypeEnabled(userType);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns list of the profiles of userId including userId itself.
* Note that this returns both enabled and not enabled profiles. See
* {@link #getEnabledProfiles(int)} if you need only the enabled ones.
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 36cdfcc..9612ca6 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -21,9 +21,6 @@
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.media.AudioAttributes;
-import android.os.vibrator.PrebakedSegment;
-import android.os.vibrator.VibrationEffectSegment;
-import android.util.Slog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -156,9 +153,6 @@
*/
public static final int FLAG_ALL_SUPPORTED = FLAG_BYPASS_INTERRUPTION_POLICY;
- // If a vibration is playing for longer than 5s, it's probably not haptic feedback
- private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
-
/** Creates a new {@link VibrationAttributes} instance with given usage. */
public static @NonNull VibrationAttributes createForUsage(int usage) {
return new VibrationAttributes.Builder().setUsage(usage).build();
@@ -359,67 +353,6 @@
setFlags(audio);
}
- /**
- * Constructs a new Builder from AudioAttributes and a VibrationEffect to infer usage.
- * @hide
- */
- @TestApi
- public Builder(@NonNull AudioAttributes audio, @NonNull VibrationEffect effect) {
- this(audio);
- applyHapticFeedbackHeuristics(effect);
- }
-
- /**
- * Constructs a new Builder from VibrationAttributes and a VibrationEffect to infer usage.
- * @hide
- */
- @TestApi
- public Builder(@NonNull VibrationAttributes vib, @NonNull VibrationEffect effect) {
- this(vib);
- applyHapticFeedbackHeuristics(effect);
- }
-
- private void applyHapticFeedbackHeuristics(@Nullable VibrationEffect effect) {
- if (effect != null) {
- PrebakedSegment prebaked = extractPrebakedSegment(effect);
- if (mUsage == USAGE_UNKNOWN && prebaked != null) {
- switch (prebaked.getEffectId()) {
- case VibrationEffect.EFFECT_CLICK:
- case VibrationEffect.EFFECT_DOUBLE_CLICK:
- case VibrationEffect.EFFECT_HEAVY_CLICK:
- case VibrationEffect.EFFECT_TEXTURE_TICK:
- case VibrationEffect.EFFECT_TICK:
- case VibrationEffect.EFFECT_POP:
- case VibrationEffect.EFFECT_THUD:
- mUsage = USAGE_TOUCH;
- break;
- default:
- Slog.w(TAG, "Unknown prebaked vibration effect, assuming it isn't "
- + "haptic feedback");
- }
- }
- final long duration = effect.getDuration();
- if (mUsage == USAGE_UNKNOWN && duration >= 0
- && duration < MAX_HAPTIC_FEEDBACK_DURATION) {
- mUsage = USAGE_TOUCH;
- }
- }
- }
-
- @Nullable
- private PrebakedSegment extractPrebakedSegment(VibrationEffect effect) {
- if (effect instanceof VibrationEffect.Composed) {
- VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
- if (composed.getSegments().size() == 1) {
- VibrationEffectSegment segment = composed.getSegments().get(0);
- if (segment instanceof PrebakedSegment) {
- return (PrebakedSegment) segment;
- }
- }
- }
- return null;
- }
-
private void setUsage(@NonNull AudioAttributes audio) {
mOriginalAudioUsage = audio.getUsage();
switch (audio.getUsage()) {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index a0cbbfe..5758a4e 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -53,7 +53,10 @@
public abstract class VibrationEffect implements Parcelable {
// Stevens' coefficient to scale the perceived vibration intensity.
private static final float SCALE_GAMMA = 0.65f;
-
+ // If a vibration is playing for longer than 1s, it's probably not haptic feedback
+ private static final long MAX_HAPTIC_FEEDBACK_DURATION = 1000;
+ // If a vibration is playing more than 3 constants, it's probably not haptic feedback
+ private static final long MAX_HAPTIC_FEEDBACK_COMPOSITION_SIZE = 3;
/**
* The default vibration strength of the device.
@@ -439,6 +442,20 @@
public abstract long getDuration();
/**
+ * Returns true if this effect could represent a touch haptic feedback.
+ *
+ * <p>It is strongly recommended that an instance of {@link VibrationAttributes} is specified
+ * for each vibration, with the correct usage. When a vibration is played with usage UNKNOWN,
+ * then this method will be used to classify the most common use case and make sure they are
+ * covered by the user settings for "Touch feedback".
+ *
+ * @hide
+ */
+ public boolean isHapticFeedbackCandidate() {
+ return false;
+ }
+
+ /**
* Resolve default values into integer amplitude numbers.
*
* @param defaultAmplitude the default amplitude to apply, must be between 0 and
@@ -582,6 +599,7 @@
return mRepeatIndex;
}
+ /** @hide */
@Override
public void validate() {
int segmentCount = mSegments.size();
@@ -620,6 +638,37 @@
return totalDuration;
}
+ /** @hide */
+ @Override
+ public boolean isHapticFeedbackCandidate() {
+ long totalDuration = getDuration();
+ if (totalDuration > MAX_HAPTIC_FEEDBACK_DURATION) {
+ // Vibration duration is known and is longer than the max duration used to classify
+ // haptic feedbacks (or repeating indefinitely with duration == Long.MAX_VALUE).
+ return false;
+ }
+ int segmentCount = mSegments.size();
+ if (segmentCount > MAX_HAPTIC_FEEDBACK_COMPOSITION_SIZE) {
+ // Vibration has some prebaked or primitive constants, it should be limited to the
+ // max composition size used to classify haptic feedbacks.
+ return false;
+ }
+ totalDuration = 0;
+ for (int i = 0; i < segmentCount; i++) {
+ if (!mSegments.get(i).isHapticFeedbackCandidate()) {
+ // There is at least one segment that is not a candidate for a haptic feedback.
+ return false;
+ }
+ long segmentDuration = mSegments.get(i).getDuration();
+ if (segmentDuration > 0) {
+ totalDuration += segmentDuration;
+ }
+ }
+ // Vibration might still have some ramp or step segments, check the known duration.
+ return totalDuration <= MAX_HAPTIC_FEEDBACK_DURATION;
+ }
+
+ /** @hide */
@NonNull
@Override
public Composed resolve(int defaultAmplitude) {
@@ -636,6 +685,7 @@
return resolved;
}
+ /** @hide */
@NonNull
@Override
public Composed scale(float scaleFactor) {
@@ -652,6 +702,7 @@
return scaled;
}
+ /** @hide */
@NonNull
@Override
public Composed applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 75234db..c67c82e 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -493,7 +493,7 @@
vibrate(vibe,
attributes == null
? new VibrationAttributes.Builder().build()
- : new VibrationAttributes.Builder(attributes, vibe).build());
+ : new VibrationAttributes.Builder(attributes).build());
}
/**
diff --git a/core/java/android/os/vibrator/PrebakedSegment.java b/core/java/android/os/vibrator/PrebakedSegment.java
index 78b4346..30f5a5c 100644
--- a/core/java/android/os/vibrator/PrebakedSegment.java
+++ b/core/java/android/os/vibrator/PrebakedSegment.java
@@ -67,17 +67,38 @@
return -1;
}
+ /** @hide */
+ @Override
+ public boolean isHapticFeedbackCandidate() {
+ switch (mEffectId) {
+ case VibrationEffect.EFFECT_CLICK:
+ case VibrationEffect.EFFECT_DOUBLE_CLICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
+ case VibrationEffect.EFFECT_POP:
+ case VibrationEffect.EFFECT_TEXTURE_TICK:
+ case VibrationEffect.EFFECT_THUD:
+ case VibrationEffect.EFFECT_TICK:
+ return true;
+ default:
+ // VibrationEffect.RINGTONES are not segments that could represent a haptic feedback
+ return false;
+ }
+ }
+
+ /** @hide */
@Override
public boolean hasNonZeroAmplitude() {
return true;
}
+ /** @hide */
@NonNull
@Override
public PrebakedSegment resolve(int defaultAmplitude) {
return this;
}
+ /** @hide */
@NonNull
@Override
public PrebakedSegment scale(float scaleFactor) {
@@ -85,6 +106,7 @@
return this;
}
+ /** @hide */
@NonNull
@Override
public PrebakedSegment applyEffectStrength(int effectStrength) {
@@ -105,16 +127,17 @@
}
}
+ /** @hide */
@Override
public void validate() {
switch (mEffectId) {
case VibrationEffect.EFFECT_CLICK:
case VibrationEffect.EFFECT_DOUBLE_CLICK:
- case VibrationEffect.EFFECT_TICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
+ case VibrationEffect.EFFECT_POP:
case VibrationEffect.EFFECT_TEXTURE_TICK:
case VibrationEffect.EFFECT_THUD:
- case VibrationEffect.EFFECT_POP:
- case VibrationEffect.EFFECT_HEAVY_CLICK:
+ case VibrationEffect.EFFECT_TICK:
break;
default:
int[] ringtones = VibrationEffect.RINGTONES;
diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java
index 2ef29cb..58ca978 100644
--- a/core/java/android/os/vibrator/PrimitiveSegment.java
+++ b/core/java/android/os/vibrator/PrimitiveSegment.java
@@ -67,18 +67,27 @@
return -1;
}
+ /** @hide */
+ @Override
+ public boolean isHapticFeedbackCandidate() {
+ return true;
+ }
+
+ /** @hide */
@Override
public boolean hasNonZeroAmplitude() {
// Every primitive plays a vibration with a non-zero amplitude, even at scale == 0.
return true;
}
+ /** @hide */
@NonNull
@Override
public PrimitiveSegment resolve(int defaultAmplitude) {
return this;
}
+ /** @hide */
@NonNull
@Override
public PrimitiveSegment scale(float scaleFactor) {
@@ -86,12 +95,14 @@
mDelay);
}
+ /** @hide */
@NonNull
@Override
public PrimitiveSegment applyEffectStrength(int effectStrength) {
return this;
}
+ /** @hide */
@Override
public void validate() {
Preconditions.checkArgumentInRange(mPrimitiveId, VibrationEffect.Composition.PRIMITIVE_NOOP,
diff --git a/core/java/android/os/vibrator/RampSegment.java b/core/java/android/os/vibrator/RampSegment.java
index aad87c5..3ec5636 100644
--- a/core/java/android/os/vibrator/RampSegment.java
+++ b/core/java/android/os/vibrator/RampSegment.java
@@ -87,11 +87,19 @@
return mDuration;
}
+ /** @hide */
+ @Override
+ public boolean isHapticFeedbackCandidate() {
+ return true;
+ }
+
+ /** @hide */
@Override
public boolean hasNonZeroAmplitude() {
return mStartAmplitude > 0 || mEndAmplitude > 0;
}
+ /** @hide */
@Override
public void validate() {
Preconditions.checkArgumentNonnegative(mDuration,
@@ -100,7 +108,7 @@
Preconditions.checkArgumentInRange(mEndAmplitude, 0f, 1f, "endAmplitude");
}
-
+ /** @hide */
@NonNull
@Override
public RampSegment resolve(int defaultAmplitude) {
@@ -108,6 +116,7 @@
return this;
}
+ /** @hide */
@NonNull
@Override
public RampSegment scale(float scaleFactor) {
@@ -121,6 +130,7 @@
mDuration);
}
+ /** @hide */
@NonNull
@Override
public RampSegment applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java
index 11209e0..69a381f 100644
--- a/core/java/android/os/vibrator/StepSegment.java
+++ b/core/java/android/os/vibrator/StepSegment.java
@@ -73,12 +73,20 @@
return mDuration;
}
+ /** @hide */
+ @Override
+ public boolean isHapticFeedbackCandidate() {
+ return true;
+ }
+
+ /** @hide */
@Override
public boolean hasNonZeroAmplitude() {
// DEFAULT_AMPLITUDE == -1 is still a non-zero amplitude that will be resolved later.
return Float.compare(mAmplitude, 0) != 0;
}
+ /** @hide */
@Override
public void validate() {
Preconditions.checkArgumentNonnegative(mDuration,
@@ -88,6 +96,7 @@
}
}
+ /** @hide */
@NonNull
@Override
public StepSegment resolve(int defaultAmplitude) {
@@ -103,6 +112,7 @@
mDuration);
}
+ /** @hide */
@NonNull
@Override
public StepSegment scale(float scaleFactor) {
@@ -113,6 +123,7 @@
mDuration);
}
+ /** @hide */
@NonNull
@Override
public StepSegment applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/vibrator/VibrationEffectSegment.java b/core/java/android/os/vibrator/VibrationEffectSegment.java
index 5b42845..979c447 100644
--- a/core/java/android/os/vibrator/VibrationEffectSegment.java
+++ b/core/java/android/os/vibrator/VibrationEffectSegment.java
@@ -57,10 +57,26 @@
*/
public abstract long getDuration();
- /** Returns true if this segment plays at a non-zero amplitude at some point. */
+ /**
+ * Returns true if this segment could be a haptic feedback effect candidate.
+ *
+ * @see VibrationEffect#isHapticFeedbackCandidate()
+ * @hide
+ */
+ public abstract boolean isHapticFeedbackCandidate();
+
+ /**
+ * Returns true if this segment plays at a non-zero amplitude at some point.
+ *
+ * @hide
+ */
public abstract boolean hasNonZeroAmplitude();
- /** Validates the segment, throwing exceptions if any parameter is invalid. */
+ /**
+ * Validates the segment, throwing exceptions if any parameter is invalid.
+ *
+ * @hide
+ */
public abstract void validate();
/**
@@ -68,6 +84,8 @@
*
* <p>This might fail with {@link IllegalArgumentException} if value is non-positive or larger
* than {@link VibrationEffect#MAX_AMPLITUDE}.
+ *
+ * @hide
*/
@NonNull
public abstract <T extends VibrationEffectSegment> T resolve(int defaultAmplitude);
@@ -77,6 +95,8 @@
*
* @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
* scale down the intensity, values larger than 1 will scale up
+ *
+ * @hide
*/
@NonNull
public abstract <T extends VibrationEffectSegment> T scale(float scaleFactor);
@@ -86,6 +106,8 @@
*
* @param effectStrength new effect strength to be applied, one of
* VibrationEffect.EFFECT_STRENGTH_*.
+ *
+ * @hide
*/
@NonNull
public abstract <T extends VibrationEffectSegment> T applyEffectStrength(int effectStrength);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d3b1b40..7979256 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12014,8 +12014,10 @@
* Value to specify whether network quality scores and badging should be shown in the UI.
*
* Type: int (0 for false, 1 for true)
+ * @deprecated {@code NetworkScoreManager} is deprecated.
* @hide
*/
+ @Deprecated
@Readable
public static final String NETWORK_SCORING_UI_ENABLED = "network_scoring_ui_enabled";
@@ -12024,8 +12026,10 @@
* when generating SSID only bases score curves.
*
* Type: long
+ * @deprecated {@code NetworkScoreManager} is deprecated.
* @hide
*/
+ @Deprecated
@Readable
public static final String SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS =
"speed_label_cache_eviction_age_millis";
@@ -12058,8 +12062,10 @@
* {@link NetworkScoreManager#setActiveScorer(String)} to write it.
*
* Type: string - package name
+ * @deprecated {@code NetworkScoreManager} is deprecated.
* @hide
*/
+ @Deprecated
@Readable
public static final String NETWORK_RECOMMENDATIONS_PACKAGE =
"network_recommendations_package";
@@ -12069,8 +12075,10 @@
* networks automatically.
*
* Type: string package name or null if the feature is either not provided or disabled.
+ * @deprecated {@code NetworkScoreManager} is deprecated.
* @hide
*/
+ @Deprecated
@TestApi
@Readable
public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
@@ -12080,8 +12088,10 @@
* {@link com.android.server.wifi.RecommendedNetworkEvaluator}.
*
* Type: long
+ * @deprecated {@code NetworkScoreManager} is deprecated.
* @hide
*/
+ @Deprecated
@Readable
public static final String RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS =
"recommended_network_evaluator_cache_expiry_ms";
diff --git a/core/java/android/security/attestationverification/AttestationProfile.aidl b/core/java/android/security/attestationverification/AttestationProfile.aidl
new file mode 100644
index 0000000..51696a9
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationProfile.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+/**
+ * {@hide}
+ */
+parcelable AttestationProfile;
diff --git a/core/java/android/security/attestationverification/AttestationProfile.java b/core/java/android/security/attestationverification/AttestationProfile.java
new file mode 100644
index 0000000..7a43dac
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationProfile.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import static android.security.attestationverification.AttestationVerificationManager.PROFILE_APP_DEFINED;
+import static android.security.attestationverification.AttestationVerificationManager.PROFILE_UNKNOWN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.security.attestationverification.AttestationVerificationManager.AttestationProfileId;
+import android.util.Log;
+
+import com.android.internal.util.DataClass;
+
+
+/**
+ * An attestation profile defining the security requirements for verifying the attestation of a
+ * remote compute environment.
+ *
+ * <p>This class is immutable and thread-safe. When checking this profile against an expected
+ * profile, it is recommended to construct the expected profile and compare them with {@code
+ * equals()}.
+ *
+ * @hide
+ * @see AttestationVerificationManager
+ */
+@DataClass(
+ genConstructor = false,
+ genEqualsHashCode = true
+)
+public final class AttestationProfile implements Parcelable {
+
+ private static final String TAG = "AVF";
+
+ /**
+ * The ID of a system-defined attestation profile.
+ *
+ * See constants in {@link AttestationVerificationManager} prefixed with {@code PROFILE_}. If
+ * this has the value of {@link AttestationVerificationManager#PROFILE_APP_DEFINED}, then the
+ * packageName and profileName are non-null.
+ */
+ @AttestationProfileId
+ private final int mAttestationProfileId;
+
+ /**
+ * The package name of a app-defined attestation profile.
+ *
+ * This value will be null unless the value of attestationProfileId is {@link
+ * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+ */
+ @Nullable
+ private final String mPackageName;
+
+
+ /**
+ * The name of an app-defined attestation profile.
+ *
+ * This value will be null unless the value of attestationProfileId is {@link
+ * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+ */
+ @Nullable
+ private final String mProfileName;
+
+ private AttestationProfile(
+ @AttestationProfileId int attestationProfileId,
+ @Nullable String packageName,
+ @Nullable String profileName) {
+ mAttestationProfileId = attestationProfileId;
+ mPackageName = packageName;
+ mProfileName = profileName;
+ }
+
+ /**
+ * Create a profile with the given id.
+ *
+ * <p>This constructor is for specifying a profile which is defined by the system. These are
+ * available as constants in the {@link AttestationVerificationManager} class prefixed with
+ * {@code PROFILE_}.
+ *
+ * @param attestationProfileId the ID of the system-defined profile
+ * @throws IllegalArgumentException when called with
+ * {@link AttestationVerificationManager#PROFILE_APP_DEFINED}
+ * (use {@link #AttestationProfile(String, String)})
+ */
+ public AttestationProfile(@AttestationProfileId int attestationProfileId) {
+ this(attestationProfileId, null, null);
+ if (attestationProfileId == PROFILE_APP_DEFINED) {
+ throw new IllegalArgumentException("App-defined profiles must be specified with the "
+ + "constructor AttestationProfile#constructor(String, String)");
+ }
+ }
+
+ /**
+ * Create a profile with the given package name and profile name.
+ *
+ * <p>This constructor is for specifying a profile defined by an app. The packageName must
+ * match the package name of the app that defines the profile (as specified in the {@code
+ * package} attribute of the {@code
+ * <manifest>} tag in the app's manifest. The profile name matches the {@code name} attribute
+ * of the {@code <attestation-profile>} tag.
+ *
+ * <p>Apps must declare profiles in their manifest as an {@code <attestation-profile>} element.
+ * However, this constructor does not verify that such a profile exists. If the profile does not
+ * exist, verifications will fail.
+ *
+ * @param packageName the package name of the app defining the profile
+ * @param profileName the name of the profile
+ */
+ public AttestationProfile(@NonNull String packageName, @NonNull String profileName) {
+ this(PROFILE_APP_DEFINED, packageName, profileName);
+ if (packageName == null || profileName == null) {
+ throw new IllegalArgumentException("Both packageName and profileName must be non-null");
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (mAttestationProfileId == PROFILE_APP_DEFINED) {
+ return "AttestationProfile(package=" + mPackageName + ", name=" + mProfileName + ")";
+ } else {
+ String humanReadableProfileId;
+ switch (mAttestationProfileId) {
+ case PROFILE_UNKNOWN:
+ humanReadableProfileId = "PROFILE_UNKNOWN";
+ break;
+ default:
+ Log.e(TAG, "ERROR: Missing case in AttestationProfile#toString");
+ humanReadableProfileId = "ERROR";
+ }
+ return "AttestationProfile(" + humanReadableProfileId + "/" + mAttestationProfileId
+ + ")";
+ }
+ }
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/security
+ // /attestationverification/AttestationProfile.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * The ID of a system-defined attestation profile.
+ *
+ * See constants in {@link AttestationVerificationManager} prefixed with {@code PROFILE_}. If
+ * this has the value of {@link AttestationVerificationManager#PROFILE_APP_DEFINED}, then the
+ * packageName and profileName are non-null.
+ */
+ @DataClass.Generated.Member
+ public @AttestationProfileId int getAttestationProfileId() {
+ return mAttestationProfileId;
+ }
+
+ /**
+ * The package name of a app-defined attestation profile.
+ *
+ * This value will be null unless the value of attestationProfileId is {@link
+ * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * The name of an app-defined attestation profile.
+ *
+ * This value will be null unless the value of attestationProfileId is {@link
+ * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getProfileName() {
+ return mProfileName;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(AttestationProfile other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ AttestationProfile that = (AttestationProfile) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mAttestationProfileId == that.mAttestationProfileId
+ && java.util.Objects.equals(mPackageName, that.mPackageName)
+ && java.util.Objects.equals(mProfileName, that.mProfileName);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mAttestationProfileId;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mProfileName);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mPackageName != null) flg |= 0x2;
+ if (mProfileName != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeInt(mAttestationProfileId);
+ if (mPackageName != null) dest.writeString(mPackageName);
+ if (mProfileName != null) dest.writeString(mProfileName);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ AttestationProfile(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int attestationProfileId = in.readInt();
+ String packageName = (flg & 0x2) == 0 ? null : in.readString();
+ String profileName = (flg & 0x4) == 0 ? null : in.readString();
+
+ this.mAttestationProfileId = attestationProfileId;
+ com.android.internal.util.AnnotationValidations.validate(
+ AttestationProfileId.class, null, mAttestationProfileId);
+ this.mPackageName = packageName;
+ this.mProfileName = profileName;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<AttestationProfile> CREATOR
+ = new Parcelable.Creator<AttestationProfile>() {
+ @Override
+ public AttestationProfile[] newArray(int size) {
+ return new AttestationProfile[size];
+ }
+
+ @Override
+ public AttestationProfile createFromParcel(@NonNull android.os.Parcel in) {
+ return new AttestationProfile(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1633629498403L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/security/attestationverification/AttestationProfile.java",
+ inputSignatures = "private static final java.lang.String TAG\nprivate final @android.security.attestationverification.AttestationVerificationManager.AttestationProfileId int mAttestationProfileId\nprivate final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mProfileName\npublic @java.lang.Override java.lang.String toString()\nclass AttestationProfile extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/security/attestationverification/AttestationVerificationManager.java b/core/java/android/security/attestationverification/AttestationVerificationManager.java
new file mode 100644
index 0000000..db783ce
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationVerificationManager.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.CheckResult;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.ParcelDuration;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
+
+/**
+ * Provides methods for verifying that attestations from remote compute environments meet minimum
+ * security requirements specified by attestation profiles.
+ *
+ * @hide
+ */
+@SystemService(Context.ATTESTATION_VERIFICATION_SERVICE)
+public class AttestationVerificationManager {
+
+ private static final String TAG = "AVF";
+ private static final Duration MAX_TOKEN_AGE = Duration.ofHours(1);
+
+ private final Context mContext;
+ private final IAttestationVerificationManagerService mService;
+
+ /**
+ * Verifies that {@code attestation} describes a computing environment that meets the
+ * requirements of {@code profile}, {@code localBindingType}, and {@code requirements}.
+ *
+ * <p>This method verifies that at least one system-registered {@linkplain
+ * AttestationVerificationService attestation verifier} associated with {@code profile} and
+ * {@code localBindingType} has verified that {@code attestation} attests that the remote
+ * environment matching the local binding data (determined by {@code localBindingType}) in
+ * {@code requirements} meets the requirements of the profile.
+ *
+ * <p>For successful verification, the {@code requirements} bundle must contain locally-known
+ * data which must match {@code attestation}. The required data in the bundle is defined by the
+ * {@code localBindingType} (see documentation for the type). Verifiers will fail to verify the
+ * attestation if the bundle contains unsupported data.
+ *
+ * <p>The {@code localBindingType} specifies how {@code attestation} is bound to a local
+ * secure channel endpoint or similar connection with the target remote environment described by
+ * the attestation. The binding is expected to be related to a cryptographic protocol, and each
+ * binding type requires specific arguments to be present in the {@code requirements} bundle. It
+ * is this binding to something known locally that ensures an attestation is not only valid, but
+ * is also associated with a particular connection.
+ *
+ * <p>The {@code callback} is called with a result and {@link VerificationToken} (which may be
+ * null). The result is an integer (see constants in this class with the prefix {@code RESULT_}.
+ * The result is {@link #RESULT_SUCCESS} when at least one verifier has passed its checks. The
+ * token may be used in calls to other parts of the system.
+ *
+ * <p>It's expected that a verifier will be able to decode and understand the passed values,
+ * otherwise fail to verify. {@code attestation} should contain some type data to prevent parse
+ * errors.
+ *
+ * <p>The values put into the {@code requirements} Bundle depend on the {@code
+ * localBindingType} used.
+ *
+ * @param profile the attestation profile which defines the security requirements which
+ * must be met by the environment described by {@code attestation}
+ * @param localBindingType the type of the local binding data; see constants in this class with
+ * the prefix {@code TYPE_}
+ * @param requirements a {@link Bundle} containing locally-known data which must match
+ * {@code attestation}
+ * @param attestation attestation data which describes a remote computing environment
+ * @param executor {@code callback} will be executed on this executor
+ * @param callback will be called with the results of the verification
+ * @see AttestationVerificationService
+ */
+ @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE)
+ public void verifyAttestation(
+ @NonNull AttestationProfile profile,
+ @LocalBindingType int localBindingType,
+ @NonNull Bundle requirements,
+ @NonNull byte[] attestation,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull BiConsumer<@VerificationResult Integer, VerificationToken> callback) {
+ try {
+ AndroidFuture<IVerificationResult> resultCallback = new AndroidFuture<>();
+ resultCallback.thenAccept(result -> {
+ Log.d(TAG, "verifyAttestation result: " + result.resultCode + " / " + result.token);
+ executor.execute(() -> {
+ callback.accept(result.resultCode, result.token);
+ });
+ });
+
+ mService.verifyAttestation(profile, localBindingType, requirements, attestation,
+ resultCallback);
+
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Verifies that {@code token} is a valid token, returning the result contained in valid
+ * tokens.
+ *
+ * <p>This verifies that the token was issued by the platform and thus the system verified
+ * attestation data against the specified {@code profile}, {@code localBindingType}, and {@code
+ * requirements}. The value returned by this method is the same as the one originally returned
+ * when the token was generated. Callers of this method should not trust the provider of the
+ * token to also specify the profile, local binding type, or requirements, but instead have
+ * their own security requirements about these arguments.
+ *
+ * <p>This method, in contrast to {@code verifyAttestation}, executes synchronously and only
+ * checks that a previous verification succeeded. This allows callers to pass the token to
+ * others, including system APIs, without those components needing to re-verify the attestation
+ * data, an operation which can take several seconds.
+ *
+ * <p>When {@code maximumAge} is not specified (null), this method verifies the token was
+ * generated in the past hour. Otherwise, it verifies the token was generated between now and
+ * {@code maximumAge} ago. The maximum value of {@code maximumAge} is one hour; specifying a
+ * duration greater than one hour will result in an {@link IllegalArgumentException}.
+ *
+ * @param profile the attestation profile which must be in the token
+ * @param localBindingType the local binding type which must be in the token
+ * @param requirements the requirements which must be in the token
+ * @param token the token to be verified
+ * @param maximumAge the maximum age to accept for the token
+ */
+ @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE)
+ @CheckResult
+ @VerificationResult
+ public int verifyToken(
+ @NonNull AttestationProfile profile,
+ @LocalBindingType int localBindingType,
+ @NonNull Bundle requirements,
+ @NonNull VerificationToken token,
+ @Nullable Duration maximumAge) {
+ Duration usedMaximumAge;
+ if (maximumAge == null) {
+ usedMaximumAge = MAX_TOKEN_AGE;
+ } else {
+ if (maximumAge.compareTo(MAX_TOKEN_AGE) > 0) {
+ throw new IllegalArgumentException(
+ "maximumAge cannot be greater than " + MAX_TOKEN_AGE + "; was "
+ + maximumAge);
+ }
+ usedMaximumAge = maximumAge;
+ }
+
+ try {
+ AndroidFuture<Integer> resultCallback = new AndroidFuture<>();
+ resultCallback.orTimeout(5, TimeUnit.SECONDS);
+
+ mService.verifyToken(token, new ParcelDuration(usedMaximumAge), resultCallback);
+ return resultCallback.get(); // block on result callback
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (Throwable t) {
+ throw new RuntimeException("Error verifying token.", t);
+ }
+ }
+
+ /** @hide */
+ public AttestationVerificationManager(
+ @NonNull Context context,
+ @NonNull IAttestationVerificationManagerService service) {
+ this.mContext = context;
+ this.mService = service;
+ }
+
+ /** @hide */
+ @IntDef(
+ prefix = {"PROFILE_"},
+ value = {
+ PROFILE_UNKNOWN,
+ PROFILE_APP_DEFINED,
+ PROFILE_SELF_TRUSTED,
+ PROFILE_PEER_DEVICE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AttestationProfileId {
+ }
+
+ /**
+ * The profile is unknown because it is a profile unknown to this version of the SDK.
+ */
+ public static final int PROFILE_UNKNOWN = 0;
+
+ /** The profile is defined by an app. */
+ public static final int PROFILE_APP_DEFINED = 1;
+
+ /**
+ * A system-defined profile which verifies that the attesting environment can create an
+ * attestation with the same root certificate as the verifying device with a matching
+ * attestation challenge.
+ *
+ * This profile is intended to be used only for testing.
+ */
+ public static final int PROFILE_SELF_TRUSTED = 2;
+
+ /**
+ * A system-defined profile which verifies that the attesting environment environment is similar
+ * to the current device in terms of security model and security configuration. This category is
+ * fairly broad and most securely configured Android devices should qualify, along with a
+ * variety of non-Android devices.
+ */
+ public static final int PROFILE_PEER_DEVICE = 3;
+
+ /** @hide */
+ @IntDef(
+ prefix = {"TYPE_"},
+ value = {
+ TYPE_UNKNOWN,
+ TYPE_APP_DEFINED,
+ TYPE_PUBLIC_KEY,
+ TYPE_CHALLENGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LocalBindingType {
+ }
+
+ /**
+ * The type of the local binding data is unknown because it is a type unknown to this version of
+ * the SDK.
+ */
+ public static final int TYPE_UNKNOWN = 0;
+
+ /**
+ * A local binding type for app-defined profiles which use local binding data which does not
+ * match any of the existing system-defined types.
+ */
+ public static final int TYPE_APP_DEFINED = 1;
+
+ /**
+ * A local binding type where the attestation is bound to a public key negotiated and
+ * authenticated to a public key.
+ *
+ * <p>When using this type, the {@code requirements} bundle contains values for:
+ * <ul>
+ * <li>{@link #PARAM_PUBLIC_KEY}
+ * <li>{@link #PARAM_ID}: identifying the remote environment, optional
+ * </ul>
+ */
+ public static final int TYPE_PUBLIC_KEY = 2;
+
+ /**
+ * A local binding type where the attestation is bound to a challenge.
+ *
+ * <p>When using this type, the {@code requirements} bundle contains values for:
+ * <ul>
+ * <li>{@link #PARAM_CHALLENGE}: containing the challenge
+ * </ul>
+ */
+ public static final int TYPE_CHALLENGE = 3;
+
+ /** @hide */
+ @IntDef(
+ prefix = {"RESULT_"},
+ value = {
+ RESULT_UNKNOWN,
+ RESULT_SUCCESS,
+ RESULT_FAILURE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface VerificationResult {
+ }
+
+ /** The result of the verification is unknown because it has a value unknown to this SDK. */
+ public static final int RESULT_UNKNOWN = 0;
+
+ /** The result of the verification was successful. */
+ public static final int RESULT_SUCCESS = 1;
+
+ /**
+ * The result of the attestation verification was failure. The attestation could not be
+ * verified.
+ */
+ public static final int RESULT_FAILURE = 2;
+
+ /**
+ * Requirements bundle parameter key for a public key, a byte array.
+ *
+ * <p>This should contain the encoded key bytes according to the ASN.1 type
+ * {@code SubjectPublicKeyInfo} defined in the X.509 standard, the same as a call to {@link
+ * java.security.spec.X509EncodedKeySpec#getEncoded()} would produce.
+ *
+ * @see Bundle#putByteArray(String, byte[])
+ */
+ public static final String PARAM_PUBLIC_KEY = "localbinding.public_key";
+
+ /** Requirements bundle parameter key for an ID, String. */
+ public static final String PARAM_ID = "localbinding.id";
+
+ /** Requirements bundle parameter for a challenge. */
+ public static final String PARAM_CHALLENGE = "localbinding.challenge";
+}
diff --git a/core/java/android/security/attestationverification/AttestationVerificationService.java b/core/java/android/security/attestationverification/AttestationVerificationService.java
new file mode 100644
index 0000000..26c3051
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationVerificationService.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.app.Service;
+import android.os.Bundle;
+import android.security.attestationverification.AttestationVerificationManager.VerificationResult;
+
+/**
+ * A verifier which can be implemented by apps to verify an attestation (as described in {@link
+ * AttestationVerificationManager}).
+ *
+ * In the manifest for this service, specify the profile and local binding type this verifier
+ * supports. Create a new service for each combination of profile & local binding type that your app
+ * supports. Each service must declare an {@code intent-filter} action of {@link #SERVICE_INTERFACE}
+ * and permission of {@link android.Manifest.permission#BIND_ATTESTATION_VERIFICATION_SERVICE}.
+ *
+ * <p>Example:
+ * {@code
+ * <pre>
+ * <service android:name=".MyAttestationVerificationService"
+ * android:permission="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
+ * android:exported="true">
+ * <intent-filter>
+ * <action
+ * android:name="android.security.attestationverification.AttestationVerificationService" />
+ * </intent-filter>
+ * <meta-data android:name="android.security.attestationverification.PROFILE_ID"
+ * android:value="PROFILE_PLACEHOLDER_0" />
+ * <meta-data android:name="android.security.attestationverification.LOCAL_BINDING_TYPE"
+ * android:value="TYPE_PLACEHOLDER_0" />
+ * </service>
+ * </pre>
+ * }
+ *
+ * <p>For app-defined profiles, an example of the {@code <meta-data>}:
+ * {@code
+ * <pre>
+ * <meta-data android:name="android.security.attestation.PROFILE_PACKAGE_NAME"
+ * android:value="com.example" />
+ * <meta-data android:name="android.security.attestation.PROFILE_NAME"
+ * android:value="com.example.profile.PROFILE_FOO" />
+ * </pre>
+ * }
+ *
+ * @hide
+ */
+public abstract class AttestationVerificationService extends Service {
+
+ /**
+ * An intent action for a service to be bound and act as an attestation verifier.
+ *
+ * <p>The app will be kept alive for a short duration between verification calls after which
+ * the system will unbind from this service making the app eligible for cleanup.
+ *
+ * <p>The service must also require permission
+ * {@link android.Manifest.permission#BIND_ATTESTATION_VERIFICATION_SERVICE}.
+ */
+ public static final String SERVICE_INTERFACE =
+ "android.security.attestationverification.AttestationVerificationService";
+
+ /**
+ * Verifies that {@code attestation} attests that the device identified by the local binding
+ * data in {@code requirements} meets the minimum requirements of this verifier for this
+ * verifier's profile.
+ *
+ * <p>Called by the system to verify an attestation.
+ *
+ * <p>The data passed into this method comes directly from apps and should be treated as
+ * potentially dangerous user input.
+ *
+ * @param requirements a {@link Bundle} containing locally-known data which must match {@code
+ * attestation}
+ * @param attestation the attestation to verify
+ * @return whether the verification passed
+ * @see AttestationVerificationManager#verifyAttestation(AttestationProfile, int, Bundle,
+ * byte[], java.util.concurrent.Executor, java.util.function.BiConsumer)
+ */
+ @CheckResult
+ @VerificationResult
+ public abstract int onVerifyPeerDeviceAttestation(
+ @NonNull Bundle requirements,
+ @NonNull byte[] attestation);
+}
diff --git a/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl b/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl
new file mode 100644
index 0000000..2fb328c
--- /dev/null
+++ b/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 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.security.attestationverification;
+
+import android.os.Bundle;
+import android.os.ParcelDuration;
+import android.security.attestationverification.AttestationProfile;
+import android.security.attestationverification.VerificationToken;
+import com.android.internal.infra.AndroidFuture;
+
+
+/**
+ * Binder interface to communicate with AttestationVerificationManagerService.
+ * @hide
+ */
+oneway interface IAttestationVerificationManagerService {
+
+ void verifyAttestation(
+ in AttestationProfile profile,
+ in int localBindingType,
+ in Bundle requirements,
+ in byte[] attestation,
+ in AndroidFuture resultCallback);
+
+ void verifyToken(
+ in VerificationToken token,
+ in ParcelDuration maximumTokenAge,
+ in AndroidFuture resultCallback);
+}
diff --git a/core/java/android/security/attestationverification/IAttestationVerificationService.aidl b/core/java/android/security/attestationverification/IAttestationVerificationService.aidl
new file mode 100644
index 0000000..082ad32
--- /dev/null
+++ b/core/java/android/security/attestationverification/IAttestationVerificationService.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import android.os.Bundle;
+import com.android.internal.infra.AndroidFuture;
+
+
+/**
+ * Binder interface for the system server to communicate with app implementations of
+ * AttestationVerificationService.
+ * @hide
+ */
+oneway interface IAttestationVerificationService {
+ void onVerifyAttestation(
+ in Bundle requirements,
+ in byte[] attestation,
+ in AndroidFuture callback);
+}
diff --git a/core/java/android/security/attestationverification/IVerificationResult.aidl b/core/java/android/security/attestationverification/IVerificationResult.aidl
new file mode 100644
index 0000000..f61c456
--- /dev/null
+++ b/core/java/android/security/attestationverification/IVerificationResult.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import android.security.attestationverification.VerificationToken;
+
+
+/**
+ * The result of an attestation verification.
+ *
+ * {@hide}
+ */
+parcelable IVerificationResult {
+ /** The result code corresponding to @VerificationResult. */
+ int resultCode;
+ /** The token for the verification or null. */
+ VerificationToken token;
+}
diff --git a/core/java/android/security/attestationverification/VerificationToken.aidl b/core/java/android/security/attestationverification/VerificationToken.aidl
new file mode 100644
index 0000000..666a8b0
--- /dev/null
+++ b/core/java/android/security/attestationverification/VerificationToken.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+/**
+ * {@hide}
+ */
+parcelable VerificationToken;
diff --git a/core/java/android/security/attestationverification/VerificationToken.java b/core/java/android/security/attestationverification/VerificationToken.java
new file mode 100644
index 0000000..ae26823
--- /dev/null
+++ b/core/java/android/security/attestationverification/VerificationToken.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2021 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.security.attestationverification;
+
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.security.attestationverification.AttestationVerificationManager.LocalBindingType;
+import android.security.attestationverification.AttestationVerificationManager.VerificationResult;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInstant;
+
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+
+/**
+ * Token representing the result of an attestation verification, which can be passed to other parts
+ * of the OS or other apps as proof of the verification.
+ *
+ * Tokens are only valid within the same UID (which means within a single app unless the deprecated
+ * android:sharedUserId manifest value is used).
+ *
+ * @hide
+ * @see Bundle#putParcelable(String, Parcelable)
+ */
+@DataClass(
+ genConstructor = false,
+ genHiddenBuilder = true
+)
+public final class VerificationToken implements Parcelable {
+
+ /**
+ * The attestation profile which was used to perform the verification.
+ * @hide
+ */
+ @NonNull
+ private final AttestationProfile mAttestationProfile;
+
+ /**
+ * The local binding type of the local binding data used to perform the verification.
+ * @hide
+ */
+ @LocalBindingType
+ private final int mLocalBindingType;
+
+ /**
+ * The requirements used to perform the verification.
+ * @hide
+ */
+ @NonNull
+ private final Bundle mRequirements;
+
+ /**
+ * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+ * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+ * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+ * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+ * Duration)} to verify a valid token and it will return this value.
+ *
+ * If the token is valid, this value is returned directly by {#verifyToken}.
+ *
+ * @hide
+ */
+ @VerificationResult
+ private final int mVerificationResult;
+
+ /**
+ * Time when the token was generated, set by the system.
+ */
+ @NonNull
+ @DataClass.ParcelWith(ForInstant.class)
+ private final java.time.Instant mVerificationTime;
+
+ /**
+ * A Hash-based message authentication code used to verify the contents and authenticity of the
+ * rest of the token. The hash is created using a secret key known only to the system server.
+ * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+ * the same.
+ *
+ * @hide
+ */
+ @NonNull
+ private final byte[] mHmac;
+
+ /**
+ * The UID of the process which called {@code verifyAttestation} to create the token, as
+ * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+ * of calling process does not match this value. This ensures that tokens cannot be shared
+ * between UIDs.
+ *
+ * @hide
+ */
+ private int mUid;
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/security/attestationverification/VerificationToken.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ VerificationToken(
+ @NonNull AttestationProfile attestationProfile,
+ @LocalBindingType int localBindingType,
+ @NonNull Bundle requirements,
+ @VerificationResult int verificationResult,
+ @NonNull java.time.Instant verificationTime,
+ @NonNull byte[] hmac,
+ int uid) {
+ this.mAttestationProfile = attestationProfile;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAttestationProfile);
+ this.mLocalBindingType = localBindingType;
+ com.android.internal.util.AnnotationValidations.validate(
+ LocalBindingType.class, null, mLocalBindingType);
+ this.mRequirements = requirements;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mRequirements);
+ this.mVerificationResult = verificationResult;
+ com.android.internal.util.AnnotationValidations.validate(
+ VerificationResult.class, null, mVerificationResult);
+ this.mVerificationTime = verificationTime;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mVerificationTime);
+ this.mHmac = hmac;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHmac);
+ this.mUid = uid;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The attestation profile which was used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @NonNull AttestationProfile getAttestationProfile() {
+ return mAttestationProfile;
+ }
+
+ /**
+ * The local binding type of the local binding data used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @LocalBindingType int getLocalBindingType() {
+ return mLocalBindingType;
+ }
+
+ /**
+ * The requirements used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Bundle getRequirements() {
+ return mRequirements;
+ }
+
+ /**
+ * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+ * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+ * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+ * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+ * Duration)} to verify a valid token and it will return this value.
+ *
+ * If the token is valid, this value is returned directly by {#verifyToken}.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @VerificationResult int getVerificationResult() {
+ return mVerificationResult;
+ }
+
+ /**
+ * Time when the token was generated, set by the system.
+ */
+ @DataClass.Generated.Member
+ public @NonNull java.time.Instant getVerificationTime() {
+ return mVerificationTime;
+ }
+
+ /**
+ * A Hash-based message authentication code used to verify the contents and authenticity of the
+ * rest of the token. The hash is created using a secret key known only to the system server.
+ * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+ * the same.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull byte[] getHmac() {
+ return mHmac;
+ }
+
+ /**
+ * The UID of the process which called {@code verifyAttestation} to create the token, as
+ * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+ * of calling process does not match this value. This ensures that tokens cannot be shared
+ * between UIDs.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public int getUid() {
+ return mUid;
+ }
+
+ @DataClass.Generated.Member
+ static Parcelling<java.time.Instant> sParcellingForVerificationTime =
+ Parcelling.Cache.get(
+ ForInstant.class);
+ static {
+ if (sParcellingForVerificationTime == null) {
+ sParcellingForVerificationTime = Parcelling.Cache.put(
+ new ForInstant());
+ }
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeTypedObject(mAttestationProfile, flags);
+ dest.writeInt(mLocalBindingType);
+ dest.writeBundle(mRequirements);
+ dest.writeInt(mVerificationResult);
+ sParcellingForVerificationTime.parcel(mVerificationTime, dest, flags);
+ dest.writeByteArray(mHmac);
+ dest.writeInt(mUid);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ VerificationToken(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ AttestationProfile attestationProfile = (AttestationProfile) in.readTypedObject(AttestationProfile.CREATOR);
+ int localBindingType = in.readInt();
+ Bundle requirements = in.readBundle();
+ int verificationResult = in.readInt();
+ java.time.Instant verificationTime = sParcellingForVerificationTime.unparcel(in);
+ byte[] hmac = in.createByteArray();
+ int uid = in.readInt();
+
+ this.mAttestationProfile = attestationProfile;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAttestationProfile);
+ this.mLocalBindingType = localBindingType;
+ com.android.internal.util.AnnotationValidations.validate(
+ LocalBindingType.class, null, mLocalBindingType);
+ this.mRequirements = requirements;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mRequirements);
+ this.mVerificationResult = verificationResult;
+ com.android.internal.util.AnnotationValidations.validate(
+ VerificationResult.class, null, mVerificationResult);
+ this.mVerificationTime = verificationTime;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mVerificationTime);
+ this.mHmac = hmac;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHmac);
+ this.mUid = uid;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<VerificationToken> CREATOR
+ = new Parcelable.Creator<VerificationToken>() {
+ @Override
+ public VerificationToken[] newArray(int size) {
+ return new VerificationToken[size];
+ }
+
+ @Override
+ public VerificationToken createFromParcel(@NonNull android.os.Parcel in) {
+ return new VerificationToken(in);
+ }
+ };
+
+ /**
+ * A builder for {@link VerificationToken}
+ * @hide
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @NonNull AttestationProfile mAttestationProfile;
+ private @LocalBindingType int mLocalBindingType;
+ private @NonNull Bundle mRequirements;
+ private @VerificationResult int mVerificationResult;
+ private @NonNull java.time.Instant mVerificationTime;
+ private @NonNull byte[] mHmac;
+ private int mUid;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param attestationProfile
+ * The attestation profile which was used to perform the verification.
+ * @param localBindingType
+ * The local binding type of the local binding data used to perform the verification.
+ * @param requirements
+ * The requirements used to perform the verification.
+ * @param verificationResult
+ * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+ * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+ * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+ * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+ * Duration)} to verify a valid token and it will return this value.
+ *
+ * If the token is valid, this value is returned directly by {#verifyToken}.
+ * @param verificationTime
+ * Time when the token was generated, set by the system.
+ * @param hmac
+ * A Hash-based message authentication code used to verify the contents and authenticity of the
+ * rest of the token. The hash is created using a secret key known only to the system server.
+ * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+ * the same.
+ * @param uid
+ * The UID of the process which called {@code verifyAttestation} to create the token, as
+ * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+ * of calling process does not match this value. This ensures that tokens cannot be shared
+ * between UIDs.
+ */
+ public Builder(
+ @NonNull AttestationProfile attestationProfile,
+ @LocalBindingType int localBindingType,
+ @NonNull Bundle requirements,
+ @VerificationResult int verificationResult,
+ @NonNull java.time.Instant verificationTime,
+ @NonNull byte[] hmac,
+ int uid) {
+ mAttestationProfile = attestationProfile;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAttestationProfile);
+ mLocalBindingType = localBindingType;
+ com.android.internal.util.AnnotationValidations.validate(
+ LocalBindingType.class, null, mLocalBindingType);
+ mRequirements = requirements;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mRequirements);
+ mVerificationResult = verificationResult;
+ com.android.internal.util.AnnotationValidations.validate(
+ VerificationResult.class, null, mVerificationResult);
+ mVerificationTime = verificationTime;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mVerificationTime);
+ mHmac = hmac;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHmac);
+ mUid = uid;
+ }
+
+ /**
+ * The attestation profile which was used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttestationProfile(@NonNull AttestationProfile value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mAttestationProfile = value;
+ return this;
+ }
+
+ /**
+ * The local binding type of the local binding data used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setLocalBindingType(@LocalBindingType int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mLocalBindingType = value;
+ return this;
+ }
+
+ /**
+ * The requirements used to perform the verification.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setRequirements(@NonNull Bundle value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mRequirements = value;
+ return this;
+ }
+
+ /**
+ * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+ * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+ * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+ * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+ * Duration)} to verify a valid token and it will return this value.
+ *
+ * If the token is valid, this value is returned directly by {#verifyToken}.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setVerificationResult(@VerificationResult int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mVerificationResult = value;
+ return this;
+ }
+
+ /**
+ * Time when the token was generated, set by the system.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setVerificationTime(@NonNull java.time.Instant value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mVerificationTime = value;
+ return this;
+ }
+
+ /**
+ * A Hash-based message authentication code used to verify the contents and authenticity of the
+ * rest of the token. The hash is created using a secret key known only to the system server.
+ * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+ * the same.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setHmac(@NonNull byte... value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mHmac = value;
+ return this;
+ }
+
+ /**
+ * The UID of the process which called {@code verifyAttestation} to create the token, as
+ * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+ * of calling process does not match this value. This ensures that tokens cannot be shared
+ * between UIDs.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUid(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mUid = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull VerificationToken build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x80; // Mark builder used
+
+ VerificationToken o = new VerificationToken(
+ mAttestationProfile,
+ mLocalBindingType,
+ mRequirements,
+ mVerificationResult,
+ mVerificationTime,
+ mHmac,
+ mUid);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1633629747234L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/security/attestationverification/VerificationToken.java",
+ inputSignatures = "private final @android.annotation.NonNull android.security.attestationverification.AttestationProfile mAttestationProfile\nprivate final @android.security.attestationverification.AttestationVerificationManager.LocalBindingType int mLocalBindingType\nprivate final @android.annotation.NonNull android.os.Bundle mRequirements\nprivate final @android.security.attestationverification.AttestationVerificationManager.VerificationResult int mVerificationResult\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) java.time.Instant mVerificationTime\nprivate final @android.annotation.NonNull byte[] mHmac\nprivate int mUid\nclass VerificationToken extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genHiddenBuilder=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/security/attestationverification/package.html b/core/java/android/security/attestationverification/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/security/attestationverification/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index ece6b35..bab2089 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -242,35 +242,49 @@
*
* @hide
*/
- public static String flagsToString(Class<?> clazz, String prefix, int flags) {
+ public static String flagsToString(Class<?> clazz, String prefix, long flags) {
final StringBuilder res = new StringBuilder();
boolean flagsWasZero = flags == 0;
for (Field field : clazz.getDeclaredFields()) {
final int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
- && field.getType().equals(int.class) && field.getName().startsWith(prefix)) {
- try {
- final int value = field.getInt(null);
- if (value == 0 && flagsWasZero) {
- return constNameWithoutPrefix(prefix, field);
- }
- if (value != 0 && (flags & value) == value) {
- flags &= ~value;
- res.append(constNameWithoutPrefix(prefix, field)).append('|');
- }
- } catch (IllegalAccessException ignored) {
+ && (field.getType().equals(int.class) || field.getType().equals(long.class))
+ && field.getName().startsWith(prefix)) {
+ final long value = getFieldValue(field);
+ if (value == 0 && flagsWasZero) {
+ return constNameWithoutPrefix(prefix, field);
+ }
+ if (value != 0 && (flags & value) == value) {
+ flags &= ~value;
+ res.append(constNameWithoutPrefix(prefix, field)).append('|');
}
}
}
if (flags != 0 || res.length() == 0) {
- res.append(Integer.toHexString(flags));
+ res.append(Long.toHexString(flags));
} else {
res.deleteCharAt(res.length() - 1);
}
return res.toString();
}
+ private static long getFieldValue(Field field) {
+ // Field could be int or long
+ try {
+ final long longValue = field.getLong(null);
+ if (longValue != 0) {
+ return longValue;
+ }
+ final int intValue = field.getInt(null);
+ if (intValue != 0) {
+ return intValue;
+ }
+ } catch (IllegalAccessException ignored) {
+ }
+ return 0;
+ }
+
/**
* Gets human-readable representation of constants (static final values).
*
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index aa1acc1..a6f88a7 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -709,8 +709,8 @@
}
/**
- * Queries the framework about whether any physical keys exist on the
- * any keyboard attached to the device that are capable of producing the given key code.
+ * Queries the framework about whether any physical keys exist on any currently attached input
+ * devices that are capable of producing the given key code.
*
* @param keyCode The key code to query.
* @return True if at least one attached keyboard supports the specified key code.
@@ -720,9 +720,8 @@
}
/**
- * Queries the framework about whether any physical keys exist on the
- * any keyboard attached to the device that are capable of producing the given
- * array of key codes.
+ * Queries the framework about whether any physical keys exist on any currently attached input
+ * devices that are capable of producing the given array of key codes.
*
* @param keyCodes The array of key codes to query.
* @return A new array of the same size as the key codes array whose elements
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 7af77ca..00754af 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -613,7 +613,10 @@
// If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
// If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
// dump the summary information
- int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
+ if (args == null || args.length == 0) {
+ return FLAG_DUMP_ALL;
+ }
+ int flags = 0;
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "framestats":
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
index ddf68fc..67d9667 100644
--- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
@@ -38,9 +38,14 @@
* or {@link Float#NaN} to leave unchanged.
* @param centerY the screen-relative Y coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
+ * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset between
+ * frame position X and centerX
+ * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset between
+ * frame position Y and centerY
* @param callback The callback called when the animation is completed or interrupted.
*/
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
in IRemoteMagnificationAnimationCallback callback);
/**
diff --git a/core/java/android/widget/RemoteViewsListAdapter.java b/core/java/android/widget/RemoteViewsListAdapter.java
index 827d033..46f80f3 100644
--- a/core/java/android/widget/RemoteViewsListAdapter.java
+++ b/core/java/android/widget/RemoteViewsListAdapter.java
@@ -89,8 +89,7 @@
RemoteViews rv = mRemoteViewsList.get(position);
rv.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
View v;
- if (convertView != null && rv != null &&
- convertView.getId() == rv.getLayoutId()) {
+ if (convertView != null && convertView.getId() == rv.getLayoutId()) {
v = convertView;
rv.reapply(mContext, v, null /* handler */, null /* size */, mColorResources);
} else {
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index bff813e..6a6f60e 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -512,6 +512,11 @@
*/
public static final String DEFAULT_QR_CODE_SCANNER = "default_qr_code_scanner";
+ /**
+ * (boolean) Whether the task manager entrypoint is enabled.
+ */
+ public static final String TASK_MANAGER_ENABLED = "task_manager_enabled";
+
private SystemUiDeviceConfigFlags() {
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 06d68e0..3aac0b1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3522,6 +3522,10 @@
* <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
*/
private int writeHistoryTag(HistoryTag tag) {
+ if (tag.string == null) {
+ Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+ }
+
Integer idxObj = mHistoryTagPool.get(tag);
int idx;
if (idxObj != null) {
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
index 1ab316d..3147c34 100644
--- a/core/java/com/android/internal/util/Parcelling.java
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -23,6 +23,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -306,5 +307,33 @@
return string == null ? null : UUID.fromString(string);
}
}
+
+ /**
+ * A {@link Parcelling} for {@link Instant}.
+ *
+ * The minimum value of an instant uses a millisecond offset of about -3.15e19 which is
+ * larger than Long.MIN_VALUE, so we can use Long.MIN_VALUE as a sentinel value to indicate
+ * a null Instant.
+ */
+ class ForInstant implements Parcelling<Instant> {
+
+ @Override
+ public void parcel(Instant item, Parcel dest, int parcelFlags) {
+ dest.writeLong(item == null ? Long.MIN_VALUE : item.getEpochSecond());
+ dest.writeInt(item == null ? Integer.MIN_VALUE : item.getNano());
+ }
+
+ @Override
+ public Instant unparcel(Parcel source) {
+ long epochSecond = source.readLong();
+ int afterNano = source.readInt();
+
+ if (epochSecond == Long.MIN_VALUE) {
+ return null;
+ } else {
+ return Instant.ofEpochSecond(epochSecond, afterNano);
+ }
+ }
+ }
}
}
diff --git a/core/proto/android/app/location_time_zone_manager.proto b/core/proto/android/app/location_time_zone_manager.proto
index 891e9fc..5fdcfdf 100644
--- a/core/proto/android/app/location_time_zone_manager.proto
+++ b/core/proto/android/app/location_time_zone_manager.proto
@@ -23,6 +23,19 @@
option java_multiple_files = true;
option java_outer_classname = "LocationTimeZoneManagerProto";
+// A state enum that matches states for LocationTimeZoneProviderController. See that class for
+// details.
+enum ControllerStateEnum {
+ CONTROLLER_STATE_UNKNOWN = 0;
+ CONTROLLER_STATE_PROVIDERS_INITIALIZING = 1;
+ CONTROLLER_STATE_STOPPED = 2;
+ CONTROLLER_STATE_INITIALIZING = 3;
+ CONTROLLER_STATE_UNCERTAIN = 4;
+ CONTROLLER_STATE_CERTAIN = 5;
+ CONTROLLER_STATE_FAILED = 6;
+ CONTROLLER_STATE_DESTROYED = 7;
+}
+
// Represents the state of the LocationTimeZoneManagerService for use in tests.
message LocationTimeZoneManagerServiceStateProto {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -30,6 +43,7 @@
optional GeolocationTimeZoneSuggestionProto last_suggestion = 1;
repeated TimeZoneProviderStateProto primary_provider_states = 2;
repeated TimeZoneProviderStateProto secondary_provider_states = 3;
+ repeated ControllerStateEnum controller_states = 4;
}
// The state tracked for a LocationTimeZoneProvider.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d926f98..85ae7a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1840,11 +1840,11 @@
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
android:protectionLevel="signature|privileged" />
- <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+ <!-- @deprecated Allows applications to act as network scorers. @hide @SystemApi-->
<permission android:name="android.permission.SCORE_NETWORKS"
android:protectionLevel="signature|privileged" />
- <!-- Allows applications to request network
+ <!-- @deprecated Allows applications to request network
recommendations and scores from the NetworkScoreService.
@SystemApi
<p>Not for use by third-party applications. @hide -->
@@ -3470,6 +3470,23 @@
<permission android:name="android.permission.UPDATE_FONTS"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to use the AttestationVerificationService.
+ @hide -->
+ <permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to export a AttestationVerificationService to verify attestations on
+ behalf of AttestationVerificationManager for system-defined attestation profiles.
+ @hide -->
+ <permission android:name="android.permission.VERIFY_ATTESTATION"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by any AttestationVerificationService to ensure that only the system can
+ bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- ========================================= -->
<!-- Permissions for special development tools -->
<!-- ========================================= -->
diff --git a/core/res/res/layout-watch/preference_list_fragment_material.xml b/core/res/res/layout-watch/preference_list_fragment_material.xml
index 22e66d5..8f2658b 100644
--- a/core/res/res/layout-watch/preference_list_fragment_material.xml
+++ b/core/res/res/layout-watch/preference_list_fragment_material.xml
@@ -43,7 +43,7 @@
android:paddingStart="@dimen/dialog_padding_material"
android:paddingEnd="@dimen/dialog_padding_material"
android:paddingBottom="8dp"
- android:textAppearance="@style/TextAppearance.Material.Title"
+ android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_horizontal|top" />
</com.android.internal.widget.WatchHeaderListView>
</FrameLayout>
diff --git a/core/tests/coretests/src/android/os/CombinedVibrationTest.java b/core/tests/coretests/src/android/os/CombinedVibrationTest.java
index 06b5d18..508856b 100644
--- a/core/tests/coretests/src/android/os/CombinedVibrationTest.java
+++ b/core/tests/coretests/src/android/os/CombinedVibrationTest.java
@@ -125,6 +125,12 @@
VibrationEffect.createOneShot(1, 1)).getDuration());
assertEquals(-1, CombinedVibration.createParallel(
VibrationEffect.get(VibrationEffect.EFFECT_CLICK)).getDuration());
+ assertEquals(-1, CombinedVibration.createParallel(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+ .compose())
+ .getDuration());
assertEquals(Long.MAX_VALUE, CombinedVibration.createParallel(
VibrationEffect.createWaveform(
new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0)).getDuration());
@@ -175,6 +181,83 @@
}
@Test
+ public void testIsHapticFeedbackCandidateMono() {
+ assertTrue(CombinedVibration.createParallel(
+ VibrationEffect.createOneShot(1, 1)).isHapticFeedbackCandidate());
+ assertTrue(CombinedVibration.createParallel(
+ VibrationEffect.get(VibrationEffect.EFFECT_CLICK)).isHapticFeedbackCandidate());
+ assertTrue(CombinedVibration.createParallel(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+ .compose())
+ .isHapticFeedbackCandidate());
+ // Too long to be classified as a haptic feedback.
+ assertFalse(CombinedVibration.createParallel(
+ VibrationEffect.createOneShot(10_000, 1)).isHapticFeedbackCandidate());
+ // Repeating vibrations should not be classified as a haptic feedback.
+ assertFalse(CombinedVibration.createParallel(
+ VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidateStereo() {
+ assertTrue(CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(1, 1))
+ .addVibrator(2, VibrationEffect.createWaveform(new long[]{6}, new int[]{1}, -1))
+ .combine()
+ .isHapticFeedbackCandidate());
+ assertTrue(CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addVibrator(2,
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+ .compose())
+ .combine()
+ .isHapticFeedbackCandidate());
+ // Repeating vibrations should not be classified as a haptic feedback.
+ assertFalse(CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addVibrator(2, VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+ .combine()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidateSequential() {
+ assertTrue(CombinedVibration.startSequential()
+ .addNext(1, VibrationEffect.createOneShot(10, 10), 10)
+ .addNext(2, VibrationEffect.createWaveform(new long[]{5}, new int[]{1}, -1))
+ .combine()
+ .isHapticFeedbackCandidate());
+ assertTrue(CombinedVibration.startSequential()
+ .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addNext(2,
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+ .compose())
+ .combine()
+ .isHapticFeedbackCandidate());
+ // Repeating vibrations should not be classified as a haptic feedback.
+ assertFalse(CombinedVibration.startSequential()
+ .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addNext(2, VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+ .combine()
+ .isHapticFeedbackCandidate());
+ // Too many effects to be classified as a haptic feedback.
+ assertFalse(CombinedVibration.startSequential()
+ .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addNext(2, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
+ .addNext(3, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK))
+ .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_THUD))
+ .combine()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
public void testHasVibratorMono_returnsTrueForAnyVibrator() {
CombinedVibration effect = CombinedVibration.createParallel(
VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 6cbfffc..781564b 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -17,6 +17,7 @@
package android.os;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -312,8 +313,106 @@
assertTrue(100 / 255f > ((StepSegment) scaledDown.getSegments().get(1)).getAmplitude());
}
+
+ @Test
+ public void testDuration() {
+ assertEquals(1, VibrationEffect.createOneShot(1, 1).getDuration());
+ assertEquals(-1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK).getDuration());
+ assertEquals(-1,
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+ .compose()
+ .getDuration());
+ assertEquals(6, VibrationEffect.createWaveform(
+ new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1).getDuration());
+ assertEquals(Long.MAX_VALUE, VibrationEffect.createWaveform(
+ new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0).getDuration());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_repeatingEffects_notCandidates() {
+ assertFalse(VibrationEffect.createWaveform(
+ new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0).isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_longEffects_notCandidates() {
+ assertFalse(VibrationEffect.createOneShot(1500, 255).isHapticFeedbackCandidate());
+ assertFalse(VibrationEffect.createWaveform(
+ new long[]{200, 200, 700}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
+ assertFalse(VibrationEffect.startWaveform()
+ .addRamp(1, 500)
+ .addStep(1, 200)
+ .addRamp(0, 500)
+ .build()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_shortEffects_areCandidates() {
+ assertTrue(VibrationEffect.createOneShot(500, 255).isHapticFeedbackCandidate());
+ assertTrue(VibrationEffect.createWaveform(
+ new long[]{100, 200, 300}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
+ assertTrue(VibrationEffect.startWaveform()
+ .addRamp(1, 300)
+ .addStep(1, 200)
+ .addRamp(0, 300)
+ .build()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_longCompositions_notCandidates() {
+ assertFalse(VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+ .compose()
+ .isHapticFeedbackCandidate());
+
+ assertFalse(VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createOneShot(1500, 255))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .compose()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_shortCompositions_areCandidates() {
+ assertTrue(VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose()
+ .isHapticFeedbackCandidate());
+
+ assertTrue(VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createOneShot(100, 255))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .compose()
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_prebakedRingtones_notCandidates() {
+ assertFalse(VibrationEffect.get(
+ VibrationEffect.RINGTONES[1]).isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_prebakedNotRingtoneConstants_areCandidates() {
+ assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_CLICK).isHapticFeedbackCandidate());
+ assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_THUD).isHapticFeedbackCandidate());
+ assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_TICK).isHapticFeedbackCandidate());
+ }
+
private Resources mockRingtoneResources() {
- return mockRingtoneResources(new String[] {
+ return mockRingtoneResources(new String[]{
RINGTONE_URI_1,
RINGTONE_URI_2,
RINGTONE_URI_3
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index 6b69b3f..bdd76a5 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -250,17 +250,4 @@
VibrationAttributes vibrationAttributes = captor.getValue();
assertEquals(new VibrationAttributes.Builder().build(), vibrationAttributes);
}
-
- @Test
- public void vibrate_withoutAudioAttributesAndLongEffect_hasUnknownUsage() {
- mVibratorSpy.vibrate(VibrationEffect.createOneShot(10_000, 255));
-
- ArgumentCaptor<VibrationAttributes> captor = ArgumentCaptor.forClass(
- VibrationAttributes.class);
- verify(mVibratorSpy).vibrate(anyInt(), anyString(), any(), isNull(), captor.capture());
-
- VibrationAttributes vibrationAttributes = captor.getValue();
- assertEquals(VibrationAttributes.USAGE_UNKNOWN, vibrationAttributes.getUsage());
- assertEquals(AudioAttributes.USAGE_UNKNOWN, vibrationAttributes.getAudioUsage());
- }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
index de80812..a0e1f43 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
@@ -17,6 +17,7 @@
package android.os.vibrator;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
@@ -105,4 +106,49 @@
VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
assertSame(prebaked, prebaked.scale(0.5f));
}
+
+ @Test
+ public void testDuration() {
+ assertEquals(-1, new PrebakedSegment(
+ VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .getDuration());
+ assertEquals(-1, new PrebakedSegment(
+ VibrationEffect.EFFECT_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .getDuration());
+ assertEquals(-1, new PrebakedSegment(
+ VibrationEffect.EFFECT_DOUBLE_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .getDuration());
+ assertEquals(-1, new PrebakedSegment(
+ VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .getDuration());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_prebakedConstants_areCandidates() {
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_DOUBLE_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_HEAVY_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ assertTrue(new PrebakedSegment(
+ VibrationEffect.EFFECT_TEXTURE_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_prebakedRingtones_notCandidates() {
+ assertFalse(new PrebakedSegment(
+ VibrationEffect.RINGTONES[1], true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+ .isHapticFeedbackCandidate());
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
index 538655b..a690553 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
@@ -127,4 +127,28 @@
assertEquals(0f, initial.scale(1.5f).scale(2 / 3f).getScale(), TOLERANCE);
assertEquals(0f, initial.scale(0.8f).scale(1.25f).getScale(), TOLERANCE);
}
+
+ @Test
+ public void testDuration() {
+ assertEquals(-1, new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_NOOP, 1, 10).getDuration());
+ assertEquals(-1, new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100).getDuration());
+ assertEquals(-1, new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_SPIN, 1, 0).getDuration());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_returnsTrue() {
+ assertTrue(new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_NOOP, 1, 10).isHapticFeedbackCandidate());
+ assertTrue(new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 10).isHapticFeedbackCandidate());
+ assertTrue(new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10).isHapticFeedbackCandidate());
+ assertTrue(new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_THUD, 1, 10).isHapticFeedbackCandidate());
+ assertTrue(new PrimitiveSegment(
+ VibrationEffect.Composition.PRIMITIVE_SPIN, 1, 10).isHapticFeedbackCandidate());
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
index 174b4a7..5f80d2a 100644
--- a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
@@ -125,4 +125,16 @@
assertEquals(0.35f, initial.scale(0.8f).getStartAmplitude(), TOLERANCE);
assertEquals(0.5f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE);
}
+
+ @Test
+ public void testDuration() {
+ assertEquals(10, new RampSegment(0.5f, 1, 0, 0, 10).getDuration());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_returnsTrue() {
+ // A single ramp segment duration is not checked here, but contributes to the effect known
+ // duration checked in VibrationEffect implementations.
+ assertTrue(new RampSegment(0.5f, 1, 0, 0, 5_000).isHapticFeedbackCandidate());
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
index 79529b8..fdce86a 100644
--- a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
@@ -141,4 +141,16 @@
assertEquals(VibrationEffect.DEFAULT_AMPLITUDE, initial.scale(1.5f).getAmplitude(),
TOLERANCE);
}
+
+ @Test
+ public void testDuration() {
+ assertEquals(5, new StepSegment(0, 0, 5).getDuration());
+ }
+
+ @Test
+ public void testIsHapticFeedbackCandidate_returnsTrue() {
+ // A single step segment duration is not checked here, but contributes to the effect known
+ // duration checked in VibrationEffect implementations.
+ assertTrue(new StepSegment(0, 0, 5_000).isHapticFeedbackCandidate());
+ }
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 7354c90..b843589 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -79,7 +79,7 @@
* mask using {@code setId(..., android.R.id.mask)} or an existing mask layer
* may be replaced using {@code setDrawableByLayerId(android.R.id.mask, ...)}.
* <pre>
- * <code><!-- A red ripple masked against an opaque rectangle. --/>
+ * <code><!-- A red ripple masked against an opaque rectangle. -->
* <ripple android:color="#ffff0000">
* <item android:id="@android:id/mask"
* android:drawable="@android:color/white" />
@@ -92,12 +92,12 @@
* If no mask layer is set, the ripple effect is masked against the composite
* of the child layers.
* <pre>
- * <code><!-- A green ripple drawn atop a black rectangle. --/>
+ * <code><!-- A green ripple drawn atop a black rectangle. -->
* <ripple android:color="#ff00ff00">
* <item android:drawable="@android:color/black" />
* </ripple>
*
- * <!-- A blue ripple drawn atop a drawable resource. --/>
+ * <!-- A blue ripple drawn atop a drawable resource. -->
* <ripple android:color="#ff0000ff">
* <item android:drawable="@drawable/my_drawable" />
* </ripple></code>
@@ -108,7 +108,7 @@
* background within the View's hierarchy. In this case, the drawing region
* may extend outside of the Drawable bounds.
* <pre>
- * <code><!-- An unbounded red ripple. --/>
+ * <code><!-- An unbounded red ripple. -->
* <ripple android:color="#ffff0000" /></code>
* </pre>
*
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index df5b3f5..a34d0ab 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -287,7 +287,7 @@
*
* @param computeHyphenation true if you want to use automatic hyphenations.
*/
- public @NonNull Builder setComputeHyphenation(boolean computeHyphenation) {
+ public @NonNull @Deprecated Builder setComputeHyphenation(boolean computeHyphenation) {
setComputeHyphenation(
computeHyphenation ? HYPHENATION_MODE_NORMAL : HYPHENATION_MODE_NONE);
return this;
@@ -331,8 +331,6 @@
*
* {@link #HYPHENATION_MODE_NONE} is by default.
*
- * @see #setComputeHyphenation(boolean)
- *
* @param mode a hyphenation mode.
*/
public @NonNull Builder setComputeHyphenation(@HyphenationMode int mode) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 7f37036..8e98b82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -216,6 +216,14 @@
}
}
+ @Override
+ public void unregisterOrganizer() {
+ super.unregisterOrganizer();
+ if (mStartingWindow != null) {
+ mStartingWindow.clearAllWindows();
+ }
+ }
+
public void createRootTask(int displayId, int windowingMode, TaskListener listener) {
ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s",
displayId, windowingMode, listener.toString());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index c2ebc30..854fc60e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -1255,11 +1255,7 @@
} else if (isOutPipDirection(direction)) {
// If we are animating to fullscreen or split screen, then we need to reset the
// override bounds on the task to ensure that the task "matches" the parent's bounds.
- if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
- taskBounds = destinationBounds;
- } else {
- taskBounds = null;
- }
+ taskBounds = null;
applyWindowingModeChangeOnExit(wct, direction);
} else {
// Just a resize in PIP
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 6280f76..a5579ae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -781,6 +781,7 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
// Make the stages adjacent to each other so they occlude what's behind them.
wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
+ wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
mTaskOrganizer.applyTransaction(wct);
}
}
@@ -788,6 +789,7 @@
private void onStageRootTaskVanished(StageListenerImpl stageListener) {
if (stageListener == mMainStageListener || stageListener == mSideStageListener) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
// Deactivate the main stage if it no longer has a root task.
mMainStage.deactivate(wct);
mTaskOrganizer.applyTransaction(wct);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index a9c81b3..73f65b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -134,7 +134,8 @@
mDisplayManager.getDisplay(DEFAULT_DISPLAY);
}
- private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
+ @VisibleForTesting
+ final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
/**
* Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
@@ -459,8 +460,23 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"Task start finish, remove starting surface for task: %d",
removalInfo.taskId);
- removeWindowSynced(removalInfo);
+ removeWindowSynced(removalInfo, false /* immediately */);
+ }
+ /**
+ * Clear all starting windows immediately.
+ */
+ public void clearAllWindows() {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Clear all starting windows immediately");
+ final int taskSize = mStartingWindowRecords.size();
+ final int[] taskIds = new int[taskSize];
+ for (int i = taskSize - 1; i >= 0; --i) {
+ taskIds[i] = mStartingWindowRecords.keyAt(i);
+ }
+ for (int i = taskSize - 1; i >= 0; --i) {
+ removeWindowNoAnimate(taskIds[i]);
+ }
}
/**
@@ -542,7 +558,8 @@
return shouldSaveView;
}
- private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
+ @VisibleForTesting
+ void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
@StartingWindowType int suggestType) {
final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
null/* TaskSnapshotWindow */, suggestType);
@@ -551,19 +568,18 @@
private void removeWindowNoAnimate(int taskId) {
mTmpRemovalInfo.taskId = taskId;
- removeWindowSynced(mTmpRemovalInfo);
+ removeWindowSynced(mTmpRemovalInfo, true /* immediately */);
}
void onImeDrawnOnTask(int taskId) {
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
if (record != null && record.mTaskSnapshotWindow != null
&& record.mTaskSnapshotWindow.hasImeSurface()) {
- record.mTaskSnapshotWindow.removeImmediately();
+ removeWindowNoAnimate(taskId);
}
- mStartingWindowRecords.remove(taskId);
}
- protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) {
+ protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) {
final int taskId = removalInfo.taskId;
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
if (record != null) {
@@ -571,7 +587,8 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"Removing splash screen window for task: %d", taskId);
if (record.mContentView != null) {
- if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ if (immediately
+ || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
removeWindowInner(record.mDecorView, false);
} else {
if (removalInfo.playRevealAnimation) {
@@ -594,8 +611,12 @@
if (record.mTaskSnapshotWindow != null) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"Removing task snapshot window for %d", taskId);
- record.mTaskSnapshotWindow.scheduleRemove(
- () -> mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme);
+ if (immediately) {
+ record.mTaskSnapshotWindow.removeImmediately();
+ } else {
+ record.mTaskSnapshotWindow.scheduleRemove(() ->
+ mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme);
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index b62360e..487eb70 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -194,6 +194,18 @@
}
/**
+ * Clear all starting window immediately, called this method when releasing the task organizer.
+ */
+ public void clearAllWindows() {
+ mSplashScreenExecutor.execute(() -> {
+ mStartingSurfaceDrawer.clearAllWindows();
+ synchronized (mTaskBackgroundColors) {
+ mTaskBackgroundColors.clear();
+ }
+ });
+ }
+
+ /**
* The interface for calls from outside the Shell, within the host process.
*/
private class StartingSurfaceImpl implements StartingSurface {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 70b7c67..d92b12e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -31,6 +31,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -117,16 +118,19 @@
WindowManager.LayoutParams params, int suggestType) {
// listen for addView
mAddWindowForTask = taskId;
+ saveSplashScreenRecord(appToken, taskId, view, suggestType);
// Do not wait for background color
return false;
}
@Override
- protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) {
+ protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo,
+ boolean immediately) {
// listen for removeView
if (mAddWindowForTask == removalInfo.taskId) {
mAddWindowForTask = 0;
}
+ mStartingWindowRecords.remove(removalInfo.taskId);
}
}
@@ -179,7 +183,7 @@
removalInfo.taskId = windowInfo.taskInfo.taskId;
mStartingSurfaceDrawer.removeStartingWindow(removalInfo);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer).removeWindowSynced(any());
+ verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false));
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
}
@@ -267,11 +271,32 @@
// Verify the task snapshot with IME snapshot will be removed when received the real IME
// drawn callback.
+ // makeTaskSnapshotWindow shall call removeWindowSynced before there add a new
+ // StartingWindowRecord for the task.
mStartingSurfaceDrawer.onImeDrawnOnTask(1);
- verify(mockSnapshotWindow).removeImmediately();
+ verify(mStartingSurfaceDrawer, times(2))
+ .removeWindowSynced(any(), eq(true));
}
}
+ @Test
+ public void testClearAllWindows() {
+ final int taskId = 1;
+ final StartingWindowInfo windowInfo =
+ createWindowInfo(taskId, android.R.style.Theme);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
+ waitHandlerIdle(mTestHandler);
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+ eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+ assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
+
+ mStartingSurfaceDrawer.clearAllWindows();
+ waitHandlerIdle(mTestHandler);
+ verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true));
+ assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0);
+ }
+
private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
StartingWindowInfo windowInfo = new StartingWindowInfo();
final ActivityInfo info = new ActivityInfo();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
index b8ad321..0b436a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
@@ -16,6 +16,7 @@
package com.android.settingslib.bluetooth;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
@@ -118,8 +119,8 @@
return true;
}
} else if (btClass != null) {
- if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
- btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+ if (doesClassMatch(btClass, BluetoothClass.PROFILE_A2DP)
+ || doesClassMatch(btClass, BluetoothClass.PROFILE_HEADSET)) {
return true;
}
}
@@ -137,7 +138,7 @@
}
}
return btClass != null
- && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
+ && doesClassMatch(btClass, BluetoothClass.PROFILE_OPP);
}
}
@@ -151,7 +152,7 @@
}
}
return btClass != null
- && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
+ && doesClassMatch(btClass, BluetoothClass.PROFILE_PANU);
}
}
@@ -165,7 +166,12 @@
}
}
return btClass != null
- && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
+ && doesClassMatch(btClass, BluetoothClass.PROFILE_NAP);
}
}
+
+ @SuppressLint("NewApi") // Hidden API made public
+ private static boolean doesClassMatch(BluetoothClass btClass, int classId) {
+ return btClass.doesClassMatch(classId);
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 253629c..c9af4d5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -2,6 +2,7 @@
import static com.android.settingslib.widget.AdaptiveOutlineDrawable.ICON_TYPE_ADVANCED;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
@@ -70,6 +71,12 @@
void onShowError(Context context, String name, int messageResId);
}
+ /**
+ * @param context to access resources from
+ * @param cachedDevice to get class from
+ * @return pair containing the drawable and the description of the Bluetooth class
+ * of the device.
+ */
public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
CachedBluetoothDevice cachedDevice) {
BluetoothClass btClass = cachedDevice.getBtClass();
@@ -110,13 +117,13 @@
}
}
if (btClass != null) {
- if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+ if (doesClassMatch(btClass, BluetoothClass.PROFILE_HEADSET)) {
return new Pair<>(
getBluetoothDrawable(context,
com.android.internal.R.drawable.ic_bt_headset_hfp),
context.getString(R.string.bluetooth_talkback_headset));
}
- if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
+ if (doesClassMatch(btClass, BluetoothClass.PROFILE_A2DP)) {
return new Pair<>(
getBluetoothDrawable(context,
com.android.internal.R.drawable.ic_bt_headphones_a2dp),
@@ -376,4 +383,9 @@
}
return Uri.parse(data);
}
+
+ @SuppressLint("NewApi") // Hidden API made public
+ private static boolean doesClassMatch(BluetoothClass btClass, int classId) {
+ return btClass.doesClassMatch(classId);
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 9d4669a..cd5c78d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -62,7 +62,7 @@
if (!(drawable instanceof BitmapDrawable)) {
setColorFilter(drawable);
}
- return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ return drawable;
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 949b245..c34f65c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -29,7 +29,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.R;
-import com.android.settingslib.bluetooth.BluetoothUtils;
import java.util.List;
@@ -61,7 +60,7 @@
public Drawable getIcon() {
final Drawable drawable = getIconWithoutBackground();
setColorFilter(drawable);
- return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ return drawable;
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index b6c0b30..1139d33 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -32,7 +32,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.R;
-import com.android.settingslib.bluetooth.BluetoothUtils;
/**
* PhoneMediaDevice extends MediaDevice to represents Phone device.
@@ -87,7 +86,7 @@
public Drawable getIcon() {
final Drawable drawable = getIconWithoutBackground();
setColorFilter(drawable);
- return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ return drawable;
}
@Override
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 8c70112..ee9d430 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -150,6 +150,7 @@
// Internal intents used on notification actions.
static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
static final String INTENT_BUGREPORT_SHARE = "android.intent.action.BUGREPORT_SHARE";
+ static final String INTENT_BUGREPORT_DONE = "android.intent.action.BUGREPORT_DONE";
static final String INTENT_BUGREPORT_INFO_LAUNCH =
"android.intent.action.BUGREPORT_INFO_LAUNCH";
static final String INTENT_BUGREPORT_SCREENSHOT =
@@ -555,6 +556,8 @@
case INTENT_BUGREPORT_SHARE:
shareBugreport(id, (BugreportInfo) intent.getParcelableExtra(EXTRA_INFO));
break;
+ case INTENT_BUGREPORT_DONE:
+ maybeShowWarningMessageAndCloseNotification(id);
case INTENT_BUGREPORT_CANCEL:
cancel(id);
break;
@@ -809,10 +812,30 @@
}
/**
+ * Creates a {@link PendingIntent} for a notification action used to show warning about the
+ * sensitivity of bugreport data and then close bugreport notification.
+ *
+ * Note that, the warning message may not be shown if the user has chosen not to see the
+ * message anymore.
+ */
+ private static PendingIntent newBugreportDoneIntent(Context context, BugreportInfo info) {
+ final Intent intent = new Intent(INTENT_BUGREPORT_DONE);
+ intent.setClass(context, BugreportProgressService.class);
+ intent.putExtra(EXTRA_ID, info.id);
+ return PendingIntent.getService(context, info.id, intent,
+ PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ @GuardedBy("mLock")
+ private void stopProgressLocked(int id) {
+ stopProgressLocked(id, /* cancelNotification */ true);
+ }
+
+ /**
* Finalizes the progress on a given bugreport and cancel its notification.
*/
@GuardedBy("mLock")
- private void stopProgressLocked(int id) {
+ private void stopProgressLocked(int id, boolean cancelNotification) {
if (mBugreportInfos.indexOfKey(id) < 0) {
Log.w(TAG, "ID not watched: " + id);
} else {
@@ -821,8 +844,13 @@
}
// Must stop foreground service first, otherwise notif.cancel() will fail below.
stopForegroundWhenDoneLocked(id);
- Log.d(TAG, "stopProgress(" + id + "): cancel notification");
- NotificationManager.from(mContext).cancel(id);
+
+ if (cancelNotification) {
+ Log.d(TAG, "stopProgress(" + id + "): cancel notification");
+ NotificationManager.from(mContext).cancel(id);
+ } else {
+ Log.d(TAG, "stopProgress(" + id + ")");
+ }
stopSelfWhenDoneLocked();
}
@@ -1039,7 +1067,8 @@
}
/**
- * Wraps up bugreport generation and triggers a notification to share the bugreport.
+ * Wraps up bugreport generation and triggers a notification to either share the bugreport or
+ * just notify the ending of the bugreport generation, according to the device type.
*/
private void onBugreportFinished(BugreportInfo info) {
if (!TextUtils.isEmpty(info.shareTitle)) {
@@ -1054,25 +1083,46 @@
stopForegroundWhenDoneLocked(info.id);
}
- triggerLocalNotification(mContext, info);
- }
-
- /**
- * Responsible for triggering a notification that allows the user to start a "share" intent with
- * the bugreport. On watches we have other methods to allow the user to start this intent
- * (usually by triggering it on another connected device); we don't need to display the
- * notification in this case.
- */
- private void triggerLocalNotification(final Context context, final BugreportInfo info) {
if (!info.bugreportFile.exists() || !info.bugreportFile.canRead()) {
Log.e(TAG, "Could not read bugreport file " + info.bugreportFile);
- Toast.makeText(context, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
+ Toast.makeText(mContext, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
synchronized (mLock) {
stopProgressLocked(info.id);
}
return;
}
+ if (mIsWatch) {
+ // Wear wants to send the notification directly and not wait for the user to tap on the
+ // notification.
+ triggerShareBugreportAndLocalNotification(info);
+ } else {
+ triggerLocalNotification(info);
+ }
+ }
+
+ /**
+ * Responsible for starting the bugerport sharing process and posting a notification which
+ * shows that the bugreport has been taken and that the sharing process has kicked-off.
+ */
+ private void triggerShareBugreportAndLocalNotification(final BugreportInfo info) {
+ boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
+ if (!isPlainText) {
+ // Already zipped, share it right away.
+ shareBugreport(info.id, info, /* showWarning */ false,
+ /* cancelNotificationWhenStoppingProgress */ false);
+ sendBugreportNotification(info, mTakingScreenshot);
+ } else {
+ // Asynchronously zip the file first, then share it.
+ shareAndPostNotificationForZippedBugreport(info, mTakingScreenshot);
+ }
+ }
+
+ /**
+ * Responsible for triggering a notification that allows the user to start a "share" intent with
+ * the bugreport.
+ */
+ private void triggerLocalNotification(final BugreportInfo info) {
boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
if (!isPlainText) {
// Already zipped, send it right away.
@@ -1083,9 +1133,11 @@
}
}
- private static Intent buildWarningIntent(Context context, Intent sendIntent) {
+ private static Intent buildWarningIntent(Context context, @Nullable Intent sendIntent) {
final Intent intent = new Intent(context, BugreportWarningActivity.class);
- intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
+ if (sendIntent != null) {
+ intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
+ }
return intent;
}
@@ -1163,11 +1215,30 @@
return intent;
}
+ private boolean hasUserDecidedNotToGetWarningMessage() {
+ return getWarningState(mContext, STATE_UNKNOWN) == STATE_HIDE;
+ }
+
+ private void maybeShowWarningMessageAndCloseNotification(int id) {
+ if (!hasUserDecidedNotToGetWarningMessage()) {
+ Intent warningIntent = buildWarningIntent(mContext, /* sendIntent */ null);
+ warningIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(warningIntent);
+ }
+ NotificationManager.from(mContext).cancel(id);
+ }
+
+ private void shareBugreport(int id, BugreportInfo sharedInfo) {
+ shareBugreport(id, sharedInfo, !hasUserDecidedNotToGetWarningMessage(),
+ /* cancelNotificationWhenStoppingProgress */ true);
+ }
+
/**
* Shares the bugreport upon user's request by issuing a {@link Intent#ACTION_SEND_MULTIPLE}
* intent, but issuing a warning dialog the first time.
*/
- private void shareBugreport(int id, BugreportInfo sharedInfo) {
+ private void shareBugreport(int id, BugreportInfo sharedInfo, boolean showWarning,
+ boolean cancelNotificationWhenStoppingProgress) {
MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE);
BugreportInfo info;
synchronized (mLock) {
@@ -1199,7 +1270,7 @@
boolean useChooser = true;
// Send through warning dialog by default
- if (getWarningState(mContext, STATE_UNKNOWN) != STATE_HIDE) {
+ if (showWarning) {
notifIntent = buildWarningIntent(mContext, sendIntent);
// No need to show a chooser in this case.
useChooser = false;
@@ -1216,7 +1287,7 @@
}
synchronized (mLock) {
// ... and stop watching this process.
- stopProgressLocked(id);
+ stopProgressLocked(id, cancelNotificationWhenStoppingProgress);
}
}
@@ -1240,12 +1311,6 @@
// Since adding the details can take a while, do it before notifying user.
addDetailsToZipFile(info);
- final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE);
- shareIntent.setClass(mContext, BugreportProgressService.class);
- shareIntent.setAction(INTENT_BUGREPORT_SHARE);
- shareIntent.putExtra(EXTRA_ID, info.id);
- shareIntent.putExtra(EXTRA_INFO, info);
-
String content;
content = takingScreenshot ?
mContext.getString(R.string.bugreport_finished_pending_screenshot_text)
@@ -1263,11 +1328,32 @@
final Notification.Builder builder = newBaseNotification(mContext)
.setContentTitle(title)
.setTicker(title)
- .setContentText(content)
- .setContentIntent(PendingIntent.getService(mContext, info.id, shareIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
.setOnlyAlertOnce(false)
- .setDeleteIntent(newCancelIntent(mContext, info));
+ .setContentText(content);
+
+ if (!mIsWatch) {
+ final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE);
+ shareIntent.setClass(mContext, BugreportProgressService.class);
+ shareIntent.setAction(INTENT_BUGREPORT_SHARE);
+ shareIntent.putExtra(EXTRA_ID, info.id);
+ shareIntent.putExtra(EXTRA_INFO, info);
+
+ builder.setContentIntent(PendingIntent.getService(mContext, info.id, shareIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
+ .setDeleteIntent(newCancelIntent(mContext, info));
+ } else {
+ // Device is a watch.
+ if (hasUserDecidedNotToGetWarningMessage()) {
+ // No action button needed for the notification. User can swipe to dimiss.
+ builder.setActions(new Action[0]);
+ } else {
+ // Add action button to lead user to the warning screen.
+ builder.setActions(
+ new Action.Builder(
+ null, mContext.getString(R.string.bugreport_info_action),
+ newBugreportDoneIntent(mContext, info)).build());
+ }
+ }
if (!TextUtils.isEmpty(info.getName())) {
builder.setSubText(info.getName());
@@ -1327,6 +1413,24 @@
}
/**
+ * Zips a bugreport, shares it, and sends for it a bugreport notification.
+ */
+ private void shareAndPostNotificationForZippedBugreport(final BugreportInfo info,
+ final boolean takingScreenshot) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ Looper.prepare();
+ zipBugreport(info);
+ shareBugreport(info.id, info, /* showWarning */ false,
+ /* cancelNotificationWhenStoppingProgress */ false);
+ sendBugreportNotification(info, mTakingScreenshot);
+ return null;
+ }
+ }.execute();
+ }
+
+ /**
* Zips a bugreport file, returning the path to the new file (or to the
* original in case of failure).
*/
diff --git a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
index ecd1369..a44e236 100644
--- a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
+++ b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
@@ -54,9 +54,11 @@
mSendIntent = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
- // We need to touch the extras to unpack them so they get migrated to
- // ClipData correctly.
- mSendIntent.hasExtra(Intent.EXTRA_STREAM);
+ if (mSendIntent != null) {
+ // We need to touch the extras to unpack them so they get migrated to
+ // ClipData correctly.
+ mSendIntent.hasExtra(Intent.EXTRA_STREAM);
+ }
final AlertController.AlertParams ap = mAlertParams;
ap.mView = LayoutInflater.from(this).inflate(R.layout.confirm_repeat, null);
@@ -84,7 +86,9 @@
if (which == AlertDialog.BUTTON_POSITIVE) {
// Remember confirm state, and launch target
setWarningState(this, mConfirmRepeat.isChecked() ? STATE_HIDE : STATE_SHOW);
- sendShareIntent(this, mSendIntent);
+ if (mSendIntent != null) {
+ sendShareIntent(this, mSendIntent);
+ }
}
finish();
diff --git a/packages/SystemUI/res/drawable/ic_list.xml b/packages/SystemUI/res/drawable/ic_list.xml
new file mode 100644
index 0000000..7ef5299
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_list.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+
+<!-- Remove when Fgs manager tile is removed -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M2,4h4v4h-4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M8,4h14v4h-14z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M2,10h4v4h-4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M8,10h14v4h-14z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M2,16h4v4h-4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M8,16h14v4h-14z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml b/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml
new file mode 100644
index 0000000..3a228d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background">
+ <shape>
+ <corners android:radius="28dp" />
+ <solid android:color="@android:color/transparent" />
+ <size
+ android:height="64dp"/>
+ </shape>
+ </item>
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape>
+ <corners
+ android:radius="28dp"/>
+ <size
+ android:height="64dp"/>
+ <solid android:color="@*android:color/system_accent1_200" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml b/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml
new file mode 100644
index 0000000..86f8b42
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <stroke
+ android:color="@android:color/transparent"
+ android:width="1dp"/>
+ <corners android:radius="20dp"/>
+ <padding
+ android:left="@dimen/media_output_dialog_button_padding_horizontal"
+ android:right="@dimen/media_output_dialog_button_padding_horizontal"
+ android:top="@dimen/media_output_dialog_button_padding_vertical"
+ android:bottom="@dimen/media_output_dialog_button_padding_vertical" />
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/media_output_item_background.xml b/packages/SystemUI/res/drawable/media_output_item_background.xml
new file mode 100644
index 0000000..8c23659
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_item_background.xml
@@ -0,0 +1,23 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <corners
+ android:radius="16dp"/>
+ <solid android:color="?androidprv:attr/colorAccentSecondary" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/media_output_item_background_active.xml b/packages/SystemUI/res/drawable/media_output_item_background_active.xml
new file mode 100644
index 0000000..09dee95
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_item_background_active.xml
@@ -0,0 +1,23 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <corners
+ android:radius="50dp"/>
+ <solid android:color="?androidprv:attr/colorAccentSecondary" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/media_output_status_check.xml b/packages/SystemUI/res/drawable/media_output_status_check.xml
new file mode 100644
index 0000000..4e17e48
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_check.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
+ android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_failed.xml b/packages/SystemUI/res/drawable/media_output_status_failed.xml
new file mode 100644
index 0000000..81fb92c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_failed.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
+ android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/fgs_manager_app_item.xml b/packages/SystemUI/res/layout/fgs_manager_app_item.xml
new file mode 100644
index 0000000..d034f4e
--- /dev/null
+++ b/packages/SystemUI/res/layout/fgs_manager_app_item.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="32dp"
+ android:orientation="horizontal"
+ android:gravity="center">
+
+ <ImageView
+ android:id="@+id/fgs_manager_app_item_icon"
+ android:layout_width="28dp"
+ android:layout_height="28dp"
+ android:layout_marginRight="12dp" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/fgs_manager_app_item_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ style="@style/TextAppearance.Dialog.Body" />
+ <TextView
+ android:id="@+id/fgs_manager_app_item_duration"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ style="@style/FgsManagerAppDuration" />
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/fgs_manager_app_item_stop_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:text="@string/fgs_manager_app_item_stop_button_label"
+ android:layout_marginLeft="12dp"
+ style="?android:attr/buttonBarNeutralButtonStyle" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index cfba83b..8f8993f 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -17,7 +17,6 @@
<com.android.systemui.statusbar.phone.KeyguardBottomAreaView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/keyguard_bottom_area"
android:layout_height="match_parent"
android:layout_width="match_parent"
@@ -128,7 +127,8 @@
android:layout_height="match_parent">
<include layout="@layout/keyguard_bottom_area_overlay" />
-
</FrameLayout>
+ <include layout="@layout/ambient_indication"
+ android:id="@+id/ambient_indication_container" />
</com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index a64ef3e..4e2b4a6 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -24,24 +24,30 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="96dp"
+ android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:paddingStart="16dp"
+ android:paddingTop="16dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="24dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/header_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="72dp"
+ android:layout_height="72dp"
android:importantForAccessibility="no"/>
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="16dp"
- android:paddingTop="20dp"
- android:paddingBottom="24dp"
- android:paddingEnd="24dp"
+ android:layout_height="wrap_content"
+ android:paddingStart="12dp"
android:orientation="vertical">
+ <ImageView
+ android:id="@+id/app_source_icon"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:gravity="center_vertical"
+ android:importantForAccessibility="no"/>
<TextView
android:id="@+id/header_title"
android:layout_width="wrap_content"
@@ -51,7 +57,7 @@
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- android:textSize="20sp"/>
+ android:textSize="16sp"/>
<TextView
android:id="@+id/header_subtitle"
android:layout_width="wrap_content"
@@ -59,17 +65,12 @@
android:gravity="center_vertical"
android:ellipsize="end"
android:maxLines="1"
- android:textColor="?android:attr/textColorTertiary"
+ android:textColor="?android:attr/textColorSecondary"
android:fontFamily="roboto-regular"
- android:textSize="16sp"/>
+ android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/listDivider"/>
-
<LinearLayout
android:id="@+id/device_list"
android:layout_width="match_parent"
@@ -88,10 +89,10 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginStart="24dp"
- android:layout_marginBottom="18dp"
- android:layout_marginEnd="24dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginBottom="24dp"
+ android:layout_marginEnd="16dp"
android:orientation="horizontal">
<Button
@@ -110,7 +111,7 @@
<Button
android:id="@+id/done"
- style="@style/MediaOutputRoundedOutlinedButton"
+ style="@style/MediaOutputRoundedButton"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:minWidth="0dp"
diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml
index a5a7efa..2f5f8d6 100644
--- a/packages/SystemUI/res/layout/media_output_list_item.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item.xml
@@ -17,26 +17,43 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/device_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="88dp"
- android:paddingTop="24dp"
- android:paddingBottom="16dp"
- android:paddingStart="24dp"
- android:paddingEnd="8dp">
+ android:layout_height="64dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="12dp">
+ <FrameLayout
+ android:id="@+id/item_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/media_output_item_background"
+ android:layout_gravity="center_vertical|start">
+ <SeekBar
+ android:id="@+id/volume_seekbar"
+ android:splitTrack="false"
+ android:visibility="gone"
+ android:paddingStart="0dp"
+ android:paddingEnd="0dp"
+ android:progressDrawable="@drawable/media_output_dialog_seekbar_background"
+ android:thumb="@null"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </FrameLayout>
<FrameLayout
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="56dp"
+ android:layout_height="64dp"
android:layout_gravity="center_vertical|start">
<ImageView
android:id="@+id/title_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
android:layout_gravity="center"/>
</FrameLayout>
@@ -45,55 +62,46 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
- android:layout_marginStart="64dp"
+ android:layout_marginStart="56dp"
android:ellipsize="end"
android:maxLines="1"
- android:textColor="?android:attr/textColorPrimary"
+ android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="16sp"/>
<RelativeLayout
android:id="@+id/two_line_layout"
android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical|start"
android:layout_height="48dp"
- android:layout_marginStart="48dp">
+ android:layout_marginStart="56dp">
<TextView
android:id="@+id/two_line_title"
+ android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="48dp"
android:ellipsize="end"
android:maxLines="1"
- android:textColor="?android:attr/textColorPrimary"
+ android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="16sp"/>
<TextView
android:id="@+id/subtitle"
+ android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="15dp"
android:layout_marginTop="4dp"
android:layout_alignParentBottom="true"
android:ellipsize="end"
android:maxLines="1"
- android:textColor="?android:attr/textColorSecondary"
+ android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="14sp"
android:fontFamily="roboto-regular"
android:visibility="gone"/>
- <SeekBar
- android:id="@+id/volume_seekbar"
- android:layout_marginTop="16dp"
- android:layout_marginEnd="8dp"
- style="@*android:style/Widget.DeviceDefault.SeekBar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"/>
<ImageView
android:id="@+id/add_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
- android:layout_marginEnd="24dp"
+ android:layout_marginEnd="16dp"
android:layout_alignParentRight="true"
android:src="@drawable/ic_add"
android:tint="?android:attr/colorAccent"
@@ -103,30 +111,33 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
- android:layout_marginEnd="24dp"
+ android:layout_marginEnd="16dp"
android:layout_alignParentRight="true"
android:button="@drawable/ic_check_box"
android:visibility="gone"
- />
+ />
</RelativeLayout>
<ProgressBar
android:id="@+id/volume_indeterminate_progress"
- style="@*android:style/Widget.Material.ProgressBar.Horizontal"
- android:layout_width="258dp"
- android:layout_height="18dp"
- android:layout_marginStart="64dp"
- android:layout_marginTop="28dp"
+ style="?android:attr/progressBarStyleSmallTitle"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="16dp"
android:indeterminate="true"
+ android:layout_gravity="right|center"
android:indeterminateOnly="true"
android:visibility="gone"/>
- </FrameLayout>
- <View
- android:id="@+id/bottom_divider"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_gravity="bottom"
- android:background="?android:attr/listDivider"
- android:visibility="gone"/>
+ <ImageView
+ android:id="@+id/media_output_item_status"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="16dp"
+ android:indeterminate="true"
+ android:layout_gravity="right|center"
+ android:indeterminateOnly="true"
+ android:importantForAccessibility="no"
+ android:visibility="gone"/>
+ </FrameLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index b4c9a93..2290964 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -128,9 +128,6 @@
systemui:layout_constraintEnd_toEndOf="parent"
/>
- <include layout="@layout/ambient_indication"
- android:id="@+id/ambient_indication_container" />
-
<include layout="@layout/photo_preview_overlay" />
<include
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index c5b47d0..2b16ec2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -16,7 +16,8 @@
* limitations under the License.
*/
-->
-<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<drawable name="notification_number_text_color">#ffffffff</drawable>
<drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
<color name="system_bar_background_opaque">#ff000000</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1bf2cd8..8b59d86 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -82,7 +82,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded
+ internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,fgsmanager
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2ab4c0a..a437ae6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1085,11 +1085,13 @@
<!-- Output switcher panel related dimensions -->
<dimen name="media_output_dialog_list_margin">12dp</dimen>
<dimen name="media_output_dialog_list_max_height">364dp</dimen>
- <dimen name="media_output_dialog_header_album_icon_size">48dp</dimen>
+ <dimen name="media_output_dialog_header_album_icon_size">72dp</dimen>
<dimen name="media_output_dialog_header_back_icon_size">32dp</dimen>
<dimen name="media_output_dialog_header_icon_padding">16dp</dimen>
- <dimen name="media_output_dialog_icon_corner_radius">8dp</dimen>
+ <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
+ <dimen name="media_output_dialog_button_padding_horizontal">16dp</dimen>
+ <dimen name="media_output_dialog_button_padding_vertical">8dp</dimen>
<!-- Distance that the full shade transition takes in order for qs to fully transition to the
shade -->
@@ -1293,4 +1295,6 @@
<!-- ************************************************************************* -->
<dimen name="keyguard_unfold_translation_x">16dp</dimen>
+
+ <dimen name="fgs_manager_min_width_minor">100%</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 21b4a42..300cb2d3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2203,7 +2203,7 @@
<!-- Summary for disconnected status [CHAR LIMIT=50] -->
<string name="media_output_dialog_disconnected">(disconnected)</string>
<!-- Summary for connecting error message [CHAR LIMIT=NONE] -->
- <string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
+ <string name="media_output_dialog_connect_failed">Can\'t switch. Tap to try again.</string>
<!-- Title for pairing item [CHAR LIMIT=60] -->
<string name="media_output_dialog_pairing_new">Pair new device</string>
@@ -2358,4 +2358,9 @@
<!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
<string name="qs_user_switch_dialog_title">Select user</string>
+
+ <!-- Title for dialog listing applications currently running in the backing [CHAR LIMIT=NONE]-->
+ <string name="fgs_manager_dialog_title">Apps running in the background</string>
+ <!-- Label of the button to stop the app from running in the background [CHAR LIMIT=12]-->
+ <string name="fgs_manager_app_item_stop_button_label">Stop</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 94f1548..12a022d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -454,6 +454,12 @@
<item name="android:background">@drawable/media_output_dialog_button_background</item>
</style>
+ <style name="MediaOutputRoundedButton" parent="@android:style/Widget.Material.Button">
+ <item name="android:background">@drawable/media_output_dialog_solid_button_background</item>
+ <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
<style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="android:windowActionBar">false</item>
<item name="preferenceTheme">@style/TunerPreferenceTheme</item>
@@ -847,7 +853,6 @@
<style name="Widget.SliceView.Panel">
<item name="titleSize">16sp</item>
<item name="rowStyle">@style/SliceRow</item>
- <item name="android:background">?android:attr/colorBackgroundFloating</item>
</style>
<style name="SliceRow">
@@ -984,4 +989,14 @@
<style name="InternetDialog.Divider.Active"/>
+ <style name="FgsManagerDialogTitle">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textDirection">locale</item>
+ </style>
+
+ <style name="FgsManagerAppDuration">
+ <item name="android:fontFamily">?android:attr/textAppearanceSmall</item>
+ <item name="android:textDirection">locale</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values/tiles_states_strings.xml b/packages/SystemUI/res/values/tiles_states_strings.xml
index ed29bc7..5fdb497 100644
--- a/packages/SystemUI/res/values/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values/tiles_states_strings.xml
@@ -298,4 +298,14 @@
<item>Off</item>
<item>On</item>
</string-array>
+
+ <!-- State names for fgsmanager tile: unavailable, off, on.
+ This subtitle is shown when the tile is in that particular state but does not set its own
+ subtitle, so some of these may never appear on screen. They should still be translated as
+ if they could appear.[CHAR LIMIT=32] -->
+ <string-array name="tile_states_fgsmanager">
+ <item>Unavailable</item>
+ <item>Off</item>
+ <item>On</item>
+ </string-array>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
index c941d66..e4e0da6 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
@@ -71,7 +71,9 @@
public void addListener(@NonNull T listener) {
Objects.requireNonNull(listener, "listener must be non-null");
- mListeners.add(listener);
+ if (!mListeners.contains(listener)) {
+ mListeners.add(listener);
+ }
if (mListeners.size() == 1) {
mContentResolver.registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 794b9dd5..a10efa9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -158,12 +158,13 @@
@MainThread
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
@Nullable IRemoteMagnificationAnimationCallback callback) {
final WindowMagnificationController windowMagnificationController =
mMagnificationControllerSupplier.get(displayId);
if (windowMagnificationController != null) {
- windowMagnificationController.enableWindowMagnification(scale, centerX,
- centerY, callback);
+ windowMagnificationController.enableWindowMagnification(scale, centerX, centerY,
+ magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, callback);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
index 1bfa9c1..dc1e005 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
@@ -62,6 +62,8 @@
private final ValueAnimator mValueAnimator;
private final AnimationSpec mStartSpec = new AnimationSpec();
private final AnimationSpec mEndSpec = new AnimationSpec();
+ private float mMagnificationFrameOffsetRatioX = 0f;
+ private float mMagnificationFrameOffsetRatioY = 0f;
private final Context mContext;
// Called when the animation is ended successfully without cancelling or mStartSpec and
// mEndSpec are equal.
@@ -88,7 +90,8 @@
}
/**
- * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)}
+ * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float,
+ * float, float, IRemoteMagnificationAnimationCallback)}
* with transition animation. If the window magnification is not enabled, the scale will start
* from 1.0 and the center won't be changed during the animation. If {@link #mState} is
* {@code STATE_DISABLING}, the animation runs in reverse.
@@ -106,16 +109,48 @@
*/
void enableWindowMagnification(float scale, float centerX, float centerY,
@Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+ enableWindowMagnification(scale, centerX, centerY, 0f, 0f, animationCallback);
+ }
+
+ /**
+ * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float,
+ * float, float, IRemoteMagnificationAnimationCallback)}
+ * with transition animation. If the window magnification is not enabled, the scale will start
+ * from 1.0 and the center won't be changed during the animation. If {@link #mState} is
+ * {@code STATE_DISABLING}, the animation runs in reverse.
+ *
+ * @param scale The target scale, or {@link Float#NaN} to leave unchanged.
+ * @param centerX The screen-relative X coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param centerY The screen-relative Y coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset between
+ * frame position X and centerX
+ * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset between
+ * frame position Y and centerY
+ * @param animationCallback Called when the transition is complete, the given arguments
+ * are as same as current values, or the transition is interrupted
+ * due to the new transition request.
+ *
+ * @see #onAnimationUpdate(ValueAnimator)
+ */
+ void enableWindowMagnification(float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
+ @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
if (mController == null) {
return;
}
sendAnimationCallback(false);
+ mMagnificationFrameOffsetRatioX = magnificationFrameOffsetRatioX;
+ mMagnificationFrameOffsetRatioY = magnificationFrameOffsetRatioY;
+
// Enable window magnification without animation immediately.
if (animationCallback == null) {
if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
mValueAnimator.cancel();
}
- mController.enableWindowMagnification(scale, centerX, centerY);
+ mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+ mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
setState(STATE_ENABLED);
return;
}
@@ -123,7 +158,8 @@
setupEnableAnimationSpecs(scale, centerX, centerY);
if (mEndSpec.equals(mStartSpec)) {
if (mState == STATE_DISABLED) {
- mController.enableWindowMagnification(scale, centerX, centerY);
+ mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+ mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
} else if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
mValueAnimator.cancel();
}
@@ -273,7 +309,8 @@
mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract;
final float centerY =
mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract;
- mController.enableWindowMagnification(sentScale, centerX, centerY);
+ mController.enableWindowMagnificationInternal(sentScale, centerX, centerY,
+ mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
}
private static ValueAnimator newValueAnimator(Resources resources) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
index 92cd8b1..2133da2 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
@@ -49,11 +49,13 @@
}
@Override
- public void enableWindowMagnification(int displayId, float scale, float centerX,
- float centerY, IRemoteMagnificationAnimationCallback callback) {
+ public void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
+ IRemoteMagnificationAnimationCallback callback) {
mHandler.post(
() -> mWindowMagnification.enableWindowMagnification(displayId, scale, centerX,
- centerY, callback));
+ centerY, magnificationFrameOffsetRatioX,
+ magnificationFrameOffsetRatioY, callback));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 2507004..b064ba9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -95,17 +95,46 @@
@Surface.Rotation
@VisibleForTesting
int mRotation;
- private final Rect mMagnificationFrame = new Rect();
private final SurfaceControl.Transaction mTransaction;
private final WindowManager mWm;
private float mScale;
+ /**
+ * MagnificationFrame represents the bound of {@link #mMirrorSurface} and is constrained
+ * by the {@link #mMagnificationFrameBoundary}.
+ * We use MagnificationFrame to calculate the position of {@link #mMirrorView}.
+ * We combine MagnificationFrame with {@link #mMagnificationFrameOffsetX} and
+ * {@link #mMagnificationFrameOffsetY} to calculate the position of {@link #mSourceBounds}.
+ */
+ private final Rect mMagnificationFrame = new Rect();
private final Rect mTmpRect = new Rect();
+
+ /**
+ * MirrorViewBounds is the bound of the {@link #mMirrorView} which displays the magnified
+ * content.
+ * {@link #mMirrorView}'s center is equal to {@link #mMagnificationFrame}'s center.
+ */
private final Rect mMirrorViewBounds = new Rect();
+
+ /**
+ * SourceBound is the bound of the magnified region which projects the magnified content.
+ * SourceBound's center is equal to the parameters centerX and centerY in
+ * {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float, float)}}
+ * but it is calculated from {@link #mMagnificationFrame}'s center in the runtime.
+ */
private final Rect mSourceBounds = new Rect();
+ /**
+ * The relation of centers between {@link #mSourceBounds} and {@link #mMagnificationFrame} is
+ * calculated in {@link #calculateSourceBounds(Rect, float)} and the equations are as following:
+ * MagnificationFrame = SourceBound (e.g., centerX & centerY) + MagnificationFrameOffset
+ * SourceBound = MagnificationFrame - MagnificationFrameOffset
+ */
+ private int mMagnificationFrameOffsetX = 0;
+ private int mMagnificationFrameOffsetY = 0;
+
// The root of the mirrored content
private SurfaceControl mMirrorSurface;
@@ -123,6 +152,7 @@
private final Runnable mMirrorViewRunnable;
private final Runnable mUpdateStateDescriptionRunnable;
private final Runnable mWindowInsetChangeRunnable;
+ // MirrorView is the mirror window which displays the magnified content.
private View mMirrorView;
private SurfaceView mMirrorSurfaceView;
private int mMirrorSurfaceMargin;
@@ -339,7 +369,7 @@
// window size changed not caused by rotation.
if (isWindowVisible() && reCreateWindow) {
deleteWindowMagnification();
- enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
+ enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
}
}
@@ -633,6 +663,26 @@
int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale));
int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale));
mSourceBounds.set(left, top, right, bottom);
+
+ // SourceBound's center is equal to center[X,Y] but calculated from MagnificationFrame's
+ // center. The relation between SourceBound and MagnificationFrame is as following:
+ // MagnificationFrame = SourceBound (center[X,Y]) + MagnificationFrameOffset
+ // SourceBound = MagnificationFrame - MagnificationFrameOffset
+ mSourceBounds.offset(-mMagnificationFrameOffsetX, -mMagnificationFrameOffsetY);
+
+ if (mSourceBounds.left < 0) {
+ mSourceBounds.offsetTo(0, mSourceBounds.top);
+ } else if (mSourceBounds.right > mWindowBounds.width()) {
+ mSourceBounds.offsetTo(mWindowBounds.width() - mSourceBounds.width(),
+ mSourceBounds.top);
+ }
+
+ if (mSourceBounds.top < 0) {
+ mSourceBounds.offsetTo(mSourceBounds.left, 0);
+ } else if (mSourceBounds.bottom > mWindowBounds.height()) {
+ mSourceBounds.offsetTo(mSourceBounds.left,
+ mWindowBounds.height() - mSourceBounds.height());
+ }
}
private void calculateMagnificationFrameBoundary() {
@@ -646,11 +696,31 @@
final int scaledWidth = (int) (halfWidth / mScale);
// The scaled half height of magnified region.
final int scaledHeight = (int) (halfHeight / mScale);
- final int exceededWidth = halfWidth - scaledWidth;
- final int exceededHeight = halfHeight - scaledHeight;
- mMagnificationFrameBoundary.set(-exceededWidth, -exceededHeight,
- mWindowBounds.width() + exceededWidth, mWindowBounds.height() + exceededHeight);
+ // MagnificationFrameBoundary constrain the space of MagnificationFrame, and it also has
+ // to leave enough space for SourceBound to magnify the whole screen space.
+ // However, there is an offset between SourceBound and MagnificationFrame.
+ // The relation between SourceBound and MagnificationFrame is as following:
+ // SourceBound = MagnificationFrame - MagnificationFrameOffset
+ // Therefore, we have to adjust the exceededBoundary based on the offset.
+ //
+ // We have to increase the offset space for the SourceBound edges which are located in
+ // the MagnificationFrame. For example, if the offsetX and offsetY are negative, which
+ // means SourceBound is at right-bottom size of MagnificationFrame, the left and top
+ // edges of SourceBound are located in MagnificationFrame. So, we have to leave extra
+ // offset space at left and top sides and don't have to leave extra space at right and
+ // bottom sides.
+ final int exceededLeft = Math.max(halfWidth - scaledWidth - mMagnificationFrameOffsetX, 0);
+ final int exceededRight = Math.max(halfWidth - scaledWidth + mMagnificationFrameOffsetX, 0);
+ final int exceededTop = Math.max(halfHeight - scaledHeight - mMagnificationFrameOffsetY, 0);
+ final int exceededBottom = Math.max(halfHeight - scaledHeight + mMagnificationFrameOffsetY,
+ 0);
+
+ mMagnificationFrameBoundary.set(
+ -exceededLeft,
+ -exceededTop,
+ mWindowBounds.width() + exceededRight,
+ mWindowBounds.height() + exceededBottom);
}
/**
@@ -711,24 +781,30 @@
}
/**
- * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)}
+ * Wraps {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float,
+ * float, float, float)}
* with transition animation. If the window magnification is not enabled, the scale will start
* from 1.0 and the center won't be changed during the animation. If animator is
* {@code STATE_DISABLING}, the animation runs in reverse.
*
* @param scale The target scale, or {@link Float#NaN} to leave unchanged.
- * @param centerX The screen-relative X coordinate around which to center,
+ * @param centerX The screen-relative X coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
- * @param centerY The screen-relative Y coordinate around which to center,
+ * @param centerY The screen-relative Y coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
+ * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset
+ * between frame position X and centerX
+ * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset
+ * between frame position Y and centerY
* @param animationCallback Called when the transition is complete, the given arguments
* are as same as current values, or the transition is interrupted
* due to the new transition request.
*/
void enableWindowMagnification(float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
@Nullable IRemoteMagnificationAnimationCallback animationCallback) {
- mAnimationController.enableWindowMagnification(scale, centerX,
- centerY, animationCallback);
+ mAnimationController.enableWindowMagnification(scale, centerX, centerY,
+ magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, animationCallback);
}
/**
@@ -738,21 +814,56 @@
* be consistent with the behavior of display magnification.
*
* @param scale the target scale, or {@link Float#NaN} to leave unchanged
- * @param centerX the screen-relative X coordinate around which to center,
+ * @param centerX the screen-relative X coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
- * @param centerY the screen-relative Y coordinate around which to center,
+ * @param centerY the screen-relative Y coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
*/
- void enableWindowMagnification(float scale, float centerX, float centerY) {
+ void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
+ enableWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN);
+ }
+
+ /**
+ * Enables window magnification with specified parameters. If the given scale is <strong>less
+ * than or equal to 1.0f<strong>, then
+ * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
+ * be consistent with the behavior of display magnification.
+ *
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
+ * @param centerX the screen-relative X coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param centerY the screen-relative Y coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset
+ * between frame position X and centerX,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset
+ * between frame position Y and centerY,
+ * or {@link Float#NaN} to leave unchanged.
+ */
+ void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) {
if (Float.compare(scale, 1.0f) <= 0) {
deleteWindowMagnification();
return;
}
+ mMagnificationFrameOffsetX = Float.isNaN(magnificationFrameOffsetRatioX)
+ ? mMagnificationFrameOffsetX
+ : (int) (mMagnificationFrame.width() / 2 * magnificationFrameOffsetRatioX);
+ mMagnificationFrameOffsetY = Float.isNaN(magnificationFrameOffsetRatioY)
+ ? mMagnificationFrameOffsetY
+ : (int) (mMagnificationFrame.height() / 2 * magnificationFrameOffsetRatioY);
+
+ // The relation of centers between SourceBound and MagnificationFrame is as following:
+ // MagnificationFrame = SourceBound (e.g., centerX & centerY) + MagnificationFrameOffset
+ final float newMagnificationFrameCenterX = centerX + mMagnificationFrameOffsetX;
+ final float newMagnificationFrameCenterY = centerY + mMagnificationFrameOffsetY;
+
final float offsetX = Float.isNaN(centerX) ? 0
- : centerX - mMagnificationFrame.exactCenterX();
+ : newMagnificationFrameCenterX - mMagnificationFrame.exactCenterX();
final float offsetY = Float.isNaN(centerY) ? 0
- : centerY - mMagnificationFrame.exactCenterY();
+ : newMagnificationFrameCenterY - mMagnificationFrame.exactCenterY();
mScale = Float.isNaN(scale) ? mScale : scale;
calculateMagnificationFrameBoundary();
@@ -774,7 +885,7 @@
if (mAnimationController.isAnimating() || !isWindowVisible() || mScale == scale) {
return;
}
- enableWindowMagnification(scale, Float.NaN, Float.NaN);
+ enableWindowMagnificationInternal(scale, Float.NaN, Float.NaN);
mHandler.removeCallbacks(mUpdateStateDescriptionRunnable);
mHandler.postDelayed(mUpdateStateDescriptionRunnable, UPDATE_STATE_DESCRIPTION_DELAY_MS);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index cff6cf1..cc5a792 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -98,7 +98,8 @@
mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
- init();
+ mIsKeyguardVisible = false;
+ mIsAccessibilityManagerServiceReady = false;
}
/**
@@ -124,9 +125,8 @@
handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets);
}
- private void init() {
- mIsKeyguardVisible = false;
- mIsAccessibilityManagerServiceReady = false;
+ /** Initializes the AccessibilityFloatingMenuController configurations. */
+ public void init() {
mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
registerContentObservers();
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt
new file mode 100644
index 0000000..42f3512
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.Context
+import android.os.Bundle
+import android.text.format.DateUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.GuardedBy
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.fgsmanager.FgsManagerDialogController.RunningApp
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+
+/**
+ * Dialog which shows a list of running foreground services and offers controls to them
+ */
+class FgsManagerDialog(
+ context: Context,
+ private val executor: Executor,
+ @Background private val backgroundExecutor: Executor,
+ private val systemClock: SystemClock,
+ private val fgsManagerDialogController: FgsManagerDialogController
+) : SystemUIDialog(context, R.style.Theme_SystemUI_Dialog) {
+
+ private val appListRecyclerView: RecyclerView = RecyclerView(this.context)
+ private val adapter: AppListAdapter = AppListAdapter()
+
+ init {
+ setTitle(R.string.fgs_manager_dialog_title)
+ setView(appListRecyclerView)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ appListRecyclerView.layoutManager = LinearLayoutManager(context)
+ fgsManagerDialogController.registerDialogForChanges(
+ object : FgsManagerDialogController.FgsManagerDialogCallback {
+ override fun onRunningAppsChanged(apps: List<RunningApp>) {
+ executor.execute {
+ adapter.setData(apps)
+ }
+ }
+ }
+ )
+ appListRecyclerView.adapter = adapter
+ backgroundExecutor.execute { adapter.setData(fgsManagerDialogController.runningAppList) }
+ }
+
+ private inner class AppListAdapter : RecyclerView.Adapter<AppItemViewHolder>() {
+ private val lock = Any()
+
+ @GuardedBy("lock")
+ private val data: MutableList<RunningApp> = ArrayList()
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppItemViewHolder {
+ return AppItemViewHolder(LayoutInflater.from(context)
+ .inflate(R.layout.fgs_manager_app_item, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: AppItemViewHolder, position: Int) {
+ var runningApp: RunningApp
+ synchronized(lock) {
+ runningApp = data[position]
+ }
+ with(holder) {
+ iconView.setImageDrawable(runningApp.mIcon)
+ appLabelView.text = runningApp.mAppLabel
+ durationView.text = DateUtils.formatDuration(
+ Math.max(systemClock.elapsedRealtime() - runningApp.mTimeStarted, 60000),
+ DateUtils.LENGTH_MEDIUM)
+ stopButton.setOnClickListener {
+ fgsManagerDialogController
+ .stopAllFgs(runningApp.mUserId, runningApp.mPackageName)
+ }
+ }
+ }
+
+ override fun getItemCount(): Int {
+ synchronized(lock) { return data.size }
+ }
+
+ fun setData(newData: List<RunningApp>) {
+ var oldData: List<RunningApp>
+ synchronized(lock) {
+ oldData = ArrayList(data)
+ data.clear()
+ data.addAll(newData)
+ }
+
+ DiffUtil.calculateDiff(object : DiffUtil.Callback() {
+ override fun getOldListSize(): Int {
+ return oldData.size
+ }
+
+ override fun getNewListSize(): Int {
+ return newData.size
+ }
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int):
+ Boolean {
+ return oldData[oldItemPosition] == newData[newItemPosition]
+ }
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int):
+ Boolean {
+ return true // TODO, look into updating the time subtext
+ }
+ }).dispatchUpdatesTo(this)
+ }
+ }
+
+ private class AppItemViewHolder(parent: View) : RecyclerView.ViewHolder(parent) {
+ val appLabelView: TextView = parent.requireViewById(R.id.fgs_manager_app_item_label)
+ val durationView: TextView = parent.requireViewById(R.id.fgs_manager_app_item_duration)
+ val iconView: ImageView = parent.requireViewById(R.id.fgs_manager_app_item_icon)
+ val stopButton: Button = parent.requireViewById(R.id.fgs_manager_app_item_stop_button)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt
new file mode 100644
index 0000000..159ed39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.NameNotFoundException
+import android.graphics.drawable.Drawable
+import android.os.Handler
+import android.os.UserHandle
+import android.util.ArrayMap
+import android.util.Log
+import androidx.annotation.GuardedBy
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.policy.RunningFgsController
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import javax.inject.Inject
+
+/**
+ * Controls events relevant to FgsManagerDialog
+ */
+class FgsManagerDialogController @Inject constructor(
+ private val packageManager: PackageManager,
+ @Background private val backgroundHandler: Handler,
+ private val runningFgsController: RunningFgsController
+) : RunningFgsController.Callback {
+ private val lock = Any()
+ private val clearCacheToken = Any()
+
+ @GuardedBy("lock")
+ private var runningApps: Map<UserPackageTime, RunningApp>? = null
+ @GuardedBy("lock")
+ private var listener: FgsManagerDialogCallback? = null
+
+ interface FgsManagerDialogCallback {
+ fun onRunningAppsChanged(apps: List<RunningApp>)
+ }
+
+ data class RunningApp(
+ val mUserId: Int,
+ val mPackageName: String,
+ val mAppLabel: CharSequence,
+ val mIcon: Drawable,
+ val mTimeStarted: Long
+ )
+
+ val runningAppList: List<RunningApp>
+ get() {
+ synchronized(lock) {
+ if (runningApps == null) {
+ onFgsPackagesChangedLocked(runningFgsController.getPackagesWithFgs())
+ }
+ return convertToRunningAppList(runningApps!!)
+ }
+ }
+
+ fun registerDialogForChanges(callback: FgsManagerDialogCallback) {
+ synchronized(lock) {
+ runningFgsController.addCallback(this)
+ listener = callback
+ backgroundHandler.removeCallbacksAndMessages(clearCacheToken)
+ }
+ }
+
+ fun onFinishDialog() {
+ synchronized(lock) {
+ listener = null
+ // Keep data such as icons cached for some time since loading can be slow
+ backgroundHandler.postDelayed(
+ {
+ synchronized(lock) {
+ runningFgsController.removeCallback(this)
+ runningApps = null
+ }
+ }, clearCacheToken, RUNNING_APP_CACHE_TIMEOUT_MILLIS)
+ }
+ }
+
+ private fun onRunningAppsChanged(apps: ArrayMap<UserPackageTime, RunningApp>) {
+ listener?.let {
+ backgroundHandler.post { it.onRunningAppsChanged(convertToRunningAppList(apps)) }
+ }
+ }
+
+ override fun onFgsPackagesChanged(packages: List<UserPackageTime>) {
+ backgroundHandler.post {
+ synchronized(lock) { onFgsPackagesChangedLocked(packages) }
+ }
+ }
+
+ /**
+ * Run on background thread
+ */
+ private fun onFgsPackagesChangedLocked(packages: List<UserPackageTime>) {
+ val newRunningApps = ArrayMap<UserPackageTime, RunningApp>()
+ for (packageWithFgs in packages) {
+ val ra = runningApps?.get(packageWithFgs)
+ if (ra == null) {
+ val userId = packageWithFgs.userId
+ val packageName = packageWithFgs.packageName
+ try {
+ val ai = packageManager.getApplicationInfo(packageName, 0)
+ var icon = packageManager.getApplicationIcon(ai)
+ icon = packageManager.getUserBadgedIcon(icon,
+ UserHandle.of(userId))
+ val label = packageManager.getApplicationLabel(ai)
+ newRunningApps[packageWithFgs] = RunningApp(userId, packageName,
+ label, icon, packageWithFgs.startTimeMillis)
+ } catch (e: NameNotFoundException) {
+ Log.e(LOG_TAG,
+ "Application info not found: $packageName", e)
+ }
+ } else {
+ newRunningApps[packageWithFgs] = ra
+ }
+ }
+ runningApps = newRunningApps
+ onRunningAppsChanged(newRunningApps)
+ }
+
+ fun stopAllFgs(userId: Int, packageName: String) {
+ runningFgsController.stopFgs(userId, packageName)
+ }
+
+ companion object {
+ private val LOG_TAG = FgsManagerDialogController::class.java.simpleName
+ private const val RUNNING_APP_CACHE_TIMEOUT_MILLIS: Long = 20_000
+
+ private fun convertToRunningAppList(apps: Map<UserPackageTime, RunningApp>):
+ List<RunningApp> {
+ val result = mutableListOf<RunningApp>()
+ result.addAll(apps.values)
+ result.sortWith { a: RunningApp, b: RunningApp ->
+ b.mTimeStarted.compareTo(a.mTimeStarted)
+ }
+ return result
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt
new file mode 100644
index 0000000..2874929
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.animation.DialogLaunchAnimator
+import android.content.DialogInterface
+import android.view.View
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Factory to create [FgsManagerDialog] instances
+ */
+@SysUISingleton
+class FgsManagerDialogFactory
+@Inject constructor(
+ private val context: Context,
+ @Main private val executor: Executor,
+ @Background private val backgroundExecutor: Executor,
+ private val systemClock: SystemClock,
+ private val dialogLaunchAnimator: DialogLaunchAnimator,
+ private val fgsManagerDialogController: FgsManagerDialogController
+) {
+
+ val lock = Any()
+
+ companion object {
+ private var fgsManagerDialog: FgsManagerDialog? = null
+ }
+
+ /**
+ * Creates the dialog if it doesn't exist
+ */
+ fun create(viewLaunchedFrom: View?) {
+ if (fgsManagerDialog == null) {
+ fgsManagerDialog = FgsManagerDialog(context, executor, backgroundExecutor,
+ systemClock, fgsManagerDialogController)
+ fgsManagerDialog!!.setOnDismissListener { i: DialogInterface? ->
+ fgsManagerDialogController.onFinishDialog()
+ fgsManagerDialog = null
+ }
+ dialogLaunchAnimator.showFromView(fgsManagerDialog!!, viewLaunchedFrom!!)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 113ba59..5fa66cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -40,6 +40,8 @@
private static final String TAG = "MediaOutputAdapter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
+ private static final float DEVICE_CONNECTED_ALPHA = 1f;
private final MediaOutputDialog mMediaOutputDialog;
private ViewGroup mConnectedItem;
@@ -109,8 +111,8 @@
if (currentlyConnected) {
mConnectedItem = mContainerLayout;
}
- mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.GONE);
+ mStatusIcon.setVisibility(View.GONE);
if (currentlyConnected && mController.isActiveRemoteDevice(device)
&& mController.getSelectableMediaDevice().size() > 0) {
// Init active device layout
@@ -124,35 +126,42 @@
if (mCurrentActivePosition == position) {
mCurrentActivePosition = -1;
}
+ if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
+ && !device.isConnected()) {
+ mTitleText.setAlpha(DEVICE_DISCONNECTED_ALPHA);
+ mTitleIcon.setAlpha(DEVICE_DISCONNECTED_ALPHA);
+ } else {
+ mTitleText.setAlpha(DEVICE_CONNECTED_ALPHA);
+ mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA);
+ }
+
if (mController.isTransferring()) {
if (device.getState() == MediaDeviceState.STATE_CONNECTING
&& !mController.hasAdjustVolumeUserRestriction()) {
- setTwoLineLayout(device, true /* bFocused */, false /* showSeekBar*/,
- true /* showProgressBar */, false /* showSubtitle */);
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ false /* showSeekBar*/,
+ true /* showProgressBar */, false /* showStatus */);
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
}
} else {
// Set different layout for each device
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
+ mStatusIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_status_failed));
setTwoLineLayout(device, false /* bFocused */,
false /* showSeekBar */, false /* showProgressBar */,
- true /* showSubtitle */);
+ true /* showSubtitle */, true /* showStatus */);
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
- setTwoLineLayout(device, true /* bFocused */, true /* showSeekBar */,
- false /* showProgressBar */, false /* showSubtitle */);
+ mStatusIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_status_check));
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ true /* showSeekBar */,
+ false /* showProgressBar */, true /* showStatus */);
initSeekbar(device);
mCurrentActivePosition = position;
- } else if (
- device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
- && !device.isConnected()) {
- setTwoLineLayout(device, false /* bFocused */,
- false /* showSeekBar */, false /* showProgressBar */,
- true /* showSubtitle */);
- mSubTitleText.setText(R.string.media_output_dialog_disconnected);
- mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
@@ -165,7 +174,6 @@
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
mCheckBox.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
- mBottomDivider.setVisibility(View.GONE);
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
false /* bFocused */);
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
@@ -175,7 +183,6 @@
mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
} else if (customizedItem == CUSTOMIZED_ITEM_DYNAMIC_GROUP) {
mConnectedItem = mContainerLayout;
- mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.GONE);
if (mController.getSelectableMediaDevice().size() > 0) {
mAddIcon.setVisibility(View.VISIBLE);
@@ -200,7 +207,6 @@
}
mCurrentActivePosition = -1;
- playSwitchingAnim(mConnectedItem, view);
mController.connectDevice(device);
device.setState(MediaDeviceState.STATE_CONNECTING);
if (!isAnimating()) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 54e40f1..dc4aaa9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -30,6 +30,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -40,7 +41,6 @@
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
@@ -113,6 +113,7 @@
private static final int ANIM_DURATION = 200;
final LinearLayout mContainerLayout;
+ final FrameLayout mItemLayout;
final TextView mTitleText;
final TextView mTwoLineTitleText;
final TextView mSubTitleText;
@@ -121,13 +122,14 @@
final ProgressBar mProgressBar;
final SeekBar mSeekBar;
final RelativeLayout mTwoLineLayout;
- final View mBottomDivider;
+ final ImageView mStatusIcon;
final CheckBox mCheckBox;
private String mDeviceId;
MediaDeviceBaseViewHolder(View view) {
super(view);
mContainerLayout = view.requireViewById(R.id.device_container);
+ mItemLayout = view.requireViewById(R.id.item_layout);
mTitleText = view.requireViewById(R.id.title);
mSubTitleText = view.requireViewById(R.id.subtitle);
mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
@@ -135,8 +137,8 @@
mTitleIcon = view.requireViewById(R.id.title_icon);
mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
mSeekBar = view.requireViewById(R.id.volume_seekbar);
- mBottomDivider = view.requireViewById(R.id.bottom_divider);
mAddIcon = view.requireViewById(R.id.add_icon);
+ mStatusIcon = view.requireViewById(R.id.media_output_item_status);
mCheckBox = view.requireViewById(R.id.check_box);
}
@@ -156,11 +158,26 @@
abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
void setSingleLineLayout(CharSequence title, boolean bFocused) {
+ setSingleLineLayout(title, bFocused, false, false, false);
+ }
+
+ void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
+ boolean showProgressBar, boolean showStatus) {
mTwoLineLayout.setVisibility(View.GONE);
- mProgressBar.setVisibility(View.GONE);
+ final Drawable backgroundDrawable =
+ showSeekBar
+ ? mContext.getDrawable(R.drawable.media_output_item_background_active)
+ .mutate() : mContext.getDrawable(
+ R.drawable.media_output_item_background)
+ .mutate();
+ mItemLayout.setBackground(backgroundDrawable);
+ mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
+ mSeekBar.setAlpha(1);
+ mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
+ mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
+ mTitleText.setText(title);
mTitleText.setVisibility(View.VISIBLE);
mTitleText.setTranslationY(0);
- mTitleText.setText(title);
if (bFocused) {
mTitleText.setTypeface(Typeface.create(mContext.getString(
com.android.internal.R.string.config_headlineFontFamilyMedium),
@@ -173,20 +190,32 @@
void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showSubtitle) {
- setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle);
+ setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
+ false);
+ }
+
+ void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
+ boolean showProgressBar, boolean showSubtitle, boolean showStatus) {
+ setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
+ showStatus);
}
void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showSubtitle) {
- setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle);
+ setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle,
+ false);
}
private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
- boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
+ boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
+ boolean showStatus) {
mTitleText.setVisibility(View.GONE);
mTwoLineLayout.setVisibility(View.VISIBLE);
+ mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
+ mItemLayout.setBackground(mContext.getDrawable(R.drawable.media_output_item_background)
+ .mutate());
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
mTwoLineTitleText.setTranslationY(0);
@@ -334,7 +363,7 @@
R.color.advanced_icon_color, mContext.getTheme());
drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
PorterDuff.Mode.SRC_IN));
- return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ return drawable;
}
private void disableSeekBar() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 26ce645..91d0b49 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -20,6 +20,7 @@
import static android.view.WindowInsets.Type.statusBars;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -64,6 +65,7 @@
private TextView mHeaderTitle;
private TextView mHeaderSubtitle;
private ImageView mHeaderIcon;
+ private ImageView mAppResourceIcon;
private RecyclerView mDevicesRecyclerView;
private LinearLayout mDeviceListLayout;
private Button mDoneButton;
@@ -112,6 +114,7 @@
mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
mDoneButton = mDialogView.requireViewById(R.id.done);
mStopButton = mDialogView.requireViewById(R.id.stop);
+ mAppResourceIcon = mDialogView.requireViewById(R.id.app_source_icon);
mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
mDeviceListLayoutListener);
@@ -145,6 +148,12 @@
// Update header icon
final int iconRes = getHeaderIconRes();
final IconCompat iconCompat = getHeaderIcon();
+ final Drawable appSourceDrawable = getAppSourceIcon();
+ if (appSourceDrawable != null) {
+ mAppResourceIcon.setImageDrawable(appSourceDrawable);
+ } else {
+ mAppResourceIcon.setVisibility(View.GONE);
+ }
if (iconRes != 0) {
mHeaderIcon.setVisibility(View.VISIBLE);
mHeaderIcon.setImageResource(iconRes);
@@ -183,6 +192,8 @@
mStopButton.setVisibility(getStopButtonVisibility());
}
+ abstract Drawable getAppSourceIcon();
+
abstract int getHeaderIconRes();
abstract IconCompat getHeaderIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 6da4d48..eef5fb0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -19,6 +19,7 @@
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -181,6 +182,20 @@
mMetricLogger.logOutputFailure(mMediaDevices, reason);
}
+ Drawable getAppSourceIcon() {
+ if (mPackageName.isEmpty()) {
+ return null;
+ }
+ try {
+ Log.d(TAG, "try to get app icon");
+ return mContext.getPackageManager()
+ .getApplicationIcon(mPackageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.d(TAG, "icon not found");
+ return null;
+ }
+ }
+
CharSequence getHeaderTitle() {
if (mMediaController != null) {
final MediaMetadata metadata = mMediaController.getMetadata();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index eca8ac9..7696a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
@@ -79,6 +80,11 @@
}
@Override
+ Drawable getAppSourceIcon() {
+ return mMediaOutputController.getAppSourceIcon();
+ }
+
+ @Override
int getStopButtonVisibility() {
return mMediaOutputController.isActiveRemoteDevice(
mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE;
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
index a201c07..104ddf9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -97,7 +97,6 @@
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
super.onBind(device, topMargin, bottomMargin, position);
mAddIcon.setVisibility(View.GONE);
- mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.VISIBLE);
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
onCheckBoxClicked(isChecked, device);
@@ -131,7 +130,6 @@
true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
false /* showSubtitle*/);
mTitleIcon.setImageDrawable(getSpeakerDrawable());
- mBottomDivider.setVisibility(View.VISIBLE);
mCheckBox.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
initSessionSeekbar();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
index 1300400..f1c6601 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
@@ -28,6 +29,7 @@
/**
* Dialog for media output group.
*/
+// TODO(b/203073091): Remove this class once group logic been implemented.
public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController
@@ -76,6 +78,11 @@
}
@Override
+ Drawable getAppSourceIcon() {
+ return null;
+ }
+
+ @Override
int getStopButtonVisibility() {
return View.VISIBLE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 23062d8..25337b6 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -24,12 +24,15 @@
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.view.View;
+import android.view.WindowInsets;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
@@ -42,12 +45,14 @@
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import javax.inject.Inject;
@@ -69,6 +74,7 @@
Dumpable {
private final AccessibilityManager mAccessibilityManager;
private final Lazy<AssistManager> mAssistManagerLazy;
+ private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
private final UserTracker mUserTracker;
private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>();
@@ -98,12 +104,14 @@
AccessibilityButtonModeObserver accessibilityButtonModeObserver,
OverviewProxyService overviewProxyService,
Lazy<AssistManager> assistManagerLazy,
+ Lazy<Optional<StatusBar>> statusBarOptionalLazy,
NavigationModeController navigationModeController,
UserTracker userTracker,
DumpManager dumpManager) {
mContext = context;
mAccessibilityManager = accessibilityManager;
mAssistManagerLazy = assistManagerLazy;
+ mStatusBarOptionalLazy = statusBarOptionalLazy;
mUserTracker = userTracker;
accessibilityManagerWrapper.addCallback(
accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate());
@@ -232,6 +240,19 @@
}
/**
+ * @return Whether the IME is shown on top of the screen given the {@code vis} flag of
+ * {@link InputMethodService} and the keyguard states.
+ */
+ public boolean isImeShown(int vis) {
+ View shadeWindowView = mStatusBarOptionalLazy.get().get().getNotificationShadeWindowView();
+ boolean isKeyguardShowing = mStatusBarOptionalLazy.get().get().isKeyguardShowing();
+ boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow()
+ && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
+ return imeVisibleOnShade
+ || (!isKeyguardShowing && (vis & InputMethodService.IME_VISIBLE) != 0);
+ }
+
+ /**
* Callbacks will get fired once immediately after registering via
* {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)}
*/
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 75ef8de..8026df7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -71,7 +71,6 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.inputmethodservice.InputMethodService;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -93,7 +92,6 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
import android.view.WindowManager;
@@ -884,17 +882,8 @@
if (displayId != mDisplayId) {
return;
}
- boolean imeVisibleOnShade = mStatusBarOptionalLazy.get().map(statusBar -> {
- View shadeWindowView = statusBar.getNotificationShadeWindowView();
- return shadeWindowView.isAttachedToWindow()
- && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
- }).orElse(false);
- boolean isKeyguardShowing = mStatusBarOptionalLazy.get().map(
- StatusBar::isKeyguardShowing).orElse(false);
- boolean imeShown = imeVisibleOnShade
- || (!isKeyguardShowing && (vis & InputMethodService.IME_VISIBLE) != 0);
+ boolean imeShown = mNavBarHelper.isImeShown(vis);
showImeSwitcher = imeShown && showImeSwitcher;
-
int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
imeShown, showImeSwitcher);
if (hints == mNavigationIconHints) return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index fb9b8eb..8fb394c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -41,7 +41,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
-import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -265,7 +264,8 @@
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
boolean showImeSwitcher) {
- boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+ boolean imeShown = mNavBarHelper.isImeShown(vis);
+ showImeSwitcher = imeShown && showImeSwitcher;
int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
imeShown, showImeSwitcher);
if (hints != mNavigationIconHints) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 6d1bbee..48255b5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -34,6 +34,8 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.RunningFgsController;
+import com.android.systemui.statusbar.policy.RunningFgsControllerImpl;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.util.settings.SecureSettings;
@@ -89,4 +91,9 @@
/** */
@Binds
QSHost provideQsHost(QSTileHost controllerImpl);
+
+ /** */
+ @Binds
+ RunningFgsController provideRunningFgsController(
+ RunningFgsControllerImpl runningFgsController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 16be998..ac95bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -36,6 +36,7 @@
import com.android.systemui.qs.tiles.DataSaverTile;
import com.android.systemui.qs.tiles.DeviceControlsTile;
import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.qs.tiles.FgsManagerTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.InternetTile;
@@ -94,6 +95,7 @@
private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
+ private final Provider<FgsManagerTile> mFgsManagerTileProvider;
private final Lazy<QSHost> mQsHostLazy;
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -130,7 +132,8 @@
Provider<AlarmTile> alarmTileProvider,
Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
- Provider<OneHandedModeTile> oneHandedModeTileProvider) {
+ Provider<OneHandedModeTile> oneHandedModeTileProvider,
+ Provider<FgsManagerTile> fgsManagerTileProvider) {
mQsHostLazy = qsHostLazy;
mCustomTileBuilderProvider = customTileBuilderProvider;
@@ -163,6 +166,7 @@
mQuickAccessWalletTileProvider = quickAccessWalletTileProvider;
mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
mOneHandedModeTileProvider = oneHandedModeTileProvider;
+ mFgsManagerTileProvider = fgsManagerTileProvider;
}
public QSTile createTile(String tileSpec) {
@@ -233,6 +237,8 @@
return mQRCodeScannerTileProvider.get();
case "onehanded":
return mOneHandedModeTileProvider.get();
+ case "fgsmanager":
+ return mFgsManagerTileProvider.get();
}
// Custom tiles
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 09fad30..eb74b1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -652,7 +652,8 @@
"wallet" to R.array.tile_states_wallet,
"qr_code_scanner" to R.array.tile_states_qr_code_scanner,
"alarm" to R.array.tile_states_alarm,
- "onehanded" to R.array.tile_states_onehanded
+ "onehanded" to R.array.tile_states_onehanded,
+ "fgsmanager" to R.array.tile_states_fgsmanager
)
fun getSubtitleId(spec: String?): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
new file mode 100644
index 0000000..75cf4d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles
+
+import android.content.Intent
+import android.os.Handler
+import android.os.Looper
+import android.provider.DeviceConfig
+import android.view.View
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
+import com.android.internal.logging.MetricsLogger
+import com.android.systemui.DejankUtils
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.fgsmanager.FgsManagerDialogFactory
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.statusbar.policy.RunningFgsController
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Quicksettings tile for the foreground services manager (task manager)
+ */
+class FgsManagerTile @Inject constructor(
+ host: QSHost?,
+ @Background backgroundLooper: Looper?,
+ @Background private val backgroundExecutor: Executor?,
+ @Main mainHandler: Handler?,
+ falsingManager: FalsingManager?,
+ metricsLogger: MetricsLogger?,
+ statusBarStateController: StatusBarStateController?,
+ activityStarter: ActivityStarter?,
+ qsLogger: QSLogger?,
+ private val fgsManagerDialogFactory: FgsManagerDialogFactory,
+ private val runningFgsController: RunningFgsController
+) : QSTileImpl<QSTile.State?>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+ statusBarStateController, activityStarter, qsLogger), RunningFgsController.Callback {
+
+ override fun handleInitialize() {
+ super.handleInitialize()
+ mUiHandler.post { runningFgsController.observe(lifecycle, this) }
+ }
+
+ override fun isAvailable(): Boolean {
+ return DejankUtils.whitelistIpcs<Boolean> {
+ DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED, false)
+ }
+ }
+
+ override fun newTileState(): QSTile.State {
+ return QSTile.State()
+ }
+
+ override fun handleClick(view: View?) {
+ mUiHandler.post { fgsManagerDialogFactory.create(view) }
+ }
+
+ override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
+ state?.label = tileLabel
+ state?.secondaryLabel = runningFgsController.getPackagesWithFgs().size.toString()
+ state?.handlesLongClick = false
+ state?.icon = ResourceIcon.get(R.drawable.ic_list)
+ }
+
+ override fun getMetricsCategory(): Int = 0
+
+ override fun getLongClickIntent(): Intent? = null
+
+ // Inline the string so we don't waste translator time since this isn't used in the mocks.
+ // TODO If mocks change need to remember to move this to strings.xml
+ override fun getTileLabel(): CharSequence = "Active apps"
+
+ override fun onFgsPackagesChanged(packages: List<UserPackageTime>) = refreshState()
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 6bba1ed..033fe1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -391,6 +391,8 @@
array.recycle();
mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
+ mMobileToggleDivider.setVisibility(
+ mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 5635f65..2b5453a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -33,6 +33,7 @@
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
@@ -66,6 +67,7 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.util.DumpUtilsKt;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -653,9 +655,19 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
+ if (mRemoteInputController != null) {
+ pw.println("mRemoteInputController: " + mRemoteInputController);
+ pw.increaseIndent();
+ mRemoteInputController.dump(pw);
+ pw.decreaseIndent();
+ }
if (mRemoteInputListener instanceof Dumpable) {
+ pw.println("mRemoteInputListener: " + mRemoteInputListener.getClass().getSimpleName());
+ pw.increaseIndent();
((Dumpable) mRemoteInputListener).dump(fd, pw, args);
+ pw.decreaseIndent();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 83ef41e..00e7a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -368,6 +368,7 @@
// NOTE: NotificationEntry.isClearable() will internally check group children to ensure
// the group itself definitively clearable.
boolean isClearable = row.getEntry().isClearable();
+ visibleTopLevelEntries++;
if (isSilent) {
if (isClearable) {
hasClearableSilentNotifs = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index cde3b0e..31ab6bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -23,11 +23,15 @@
import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
import android.util.Pair;
+import androidx.annotation.NonNull;
+
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.util.DumpUtilsKt;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -293,6 +297,28 @@
mRemoteInputUriController.grantInlineReplyUriPermission(sbn, data);
}
+ /** dump debug info; called by {@link NotificationRemoteInputManager} */
+ public void dump(@NonNull IndentingPrintWriter pw) {
+ pw.print("isRemoteInputActive: ");
+ pw.println(isRemoteInputActive()); // Note that this prunes the mOpen list, printed later.
+ pw.println("mOpen: " + mOpen.size());
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
+ for (Pair<WeakReference<NotificationEntry>, Object> open : mOpen) {
+ NotificationEntry entry = open.first.get();
+ pw.println(entry == null ? "???" : entry.getKey());
+ }
+ });
+ pw.println("mSpinning: " + mSpinning.size());
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
+ for (String key : mSpinning.keySet()) {
+ pw.println(key);
+ }
+ });
+ pw.println(mSpinning);
+ pw.print("mDelegate: ");
+ pw.println(mDelegate);
+ }
+
public interface Callback {
default void onRemoteInputActive(boolean active) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
index d013261..e9b7caa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -57,6 +58,7 @@
public class BubbleCoordinator implements Coordinator {
private static final String TAG = "BubbleCoordinator";
+ private final NotifPipelineFlags mNotifPipelineFlags;
private final Optional<BubblesManager> mBubblesManagerOptional;
private final Optional<Bubbles> mBubblesOptional;
private final NotifCollection mNotifCollection;
@@ -66,9 +68,11 @@
@Inject
public BubbleCoordinator(
+ NotifPipelineFlags notifPipelineFlags,
Optional<BubblesManager> bubblesManagerOptional,
Optional<Bubbles> bubblesOptional,
NotifCollection notifCollection) {
+ mNotifPipelineFlags = notifPipelineFlags;
mBubblesManagerOptional = bubblesManagerOptional;
mBubblesOptional = bubblesOptional;
mNotifCollection = notifCollection;
@@ -130,6 +134,14 @@
DismissedByUserStats dismissedByUserStats,
int reason
) {
+ if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
+ // The `entry` will be from whichever pipeline is active, so if the old pipeline is
+ // running, make sure that we use the new pipeline's entry (if it still exists).
+ NotificationEntry newPipelineEntry = mNotifPipeline.getEntry(entry.getKey());
+ if (newPipelineEntry != null) {
+ entry = newPipelineEntry;
+ }
+ }
if (isInterceptingDismissal(entry)) {
mInterceptedDismissalEntries.remove(entry.getKey());
mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 1c2b938..2fbd212 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -54,6 +54,7 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
@@ -3431,46 +3432,47 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
// Skip super call; dump viewState ourselves
pw.println("Notification: " + mEntry.getKey());
- DumpUtilsKt.withIndenting(pw, ipw -> {
- ipw.print("visibility: " + getVisibility());
- ipw.print(", alpha: " + getAlpha());
- ipw.print(", translation: " + getTranslation());
- ipw.print(", removed: " + isRemoved());
- ipw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
+ pw.print("visibility: " + getVisibility());
+ pw.print(", alpha: " + getAlpha());
+ pw.print(", translation: " + getTranslation());
+ pw.print(", removed: " + isRemoved());
+ pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
NotificationContentView showingLayout = getShowingLayout();
- ipw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
- ipw.println();
- showingLayout.dump(fd, ipw, args);
+ pw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
+ pw.println();
+ showingLayout.dump(fd, pw, args);
if (getViewState() != null) {
- getViewState().dump(fd, ipw, args);
- ipw.println();
+ getViewState().dump(fd, pw, args);
+ pw.println();
} else {
- ipw.println("no viewState!!!");
+ pw.println("no viewState!!!");
}
if (mIsSummaryWithChildren) {
- ipw.println();
- ipw.print("ChildrenContainer");
- ipw.print(" visibility: " + mChildrenContainer.getVisibility());
- ipw.print(", alpha: " + mChildrenContainer.getAlpha());
- ipw.print(", translationY: " + mChildrenContainer.getTranslationY());
- ipw.println();
+ pw.println();
+ pw.print("ChildrenContainer");
+ pw.print(" visibility: " + mChildrenContainer.getVisibility());
+ pw.print(", alpha: " + mChildrenContainer.getAlpha());
+ pw.print(", translationY: " + mChildrenContainer.getTranslationY());
+ pw.println();
List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
- ipw.println("Children: " + notificationChildren.size());
- ipw.print("{");
- ipw.increaseIndent();
+ pw.println("Children: " + notificationChildren.size());
+ pw.print("{");
+ pw.increaseIndent();
for (ExpandableNotificationRow child : notificationChildren) {
- ipw.println();
- child.dump(fd, ipw, args);
+ pw.println();
+ child.dump(fd, pw, args);
}
- ipw.decreaseIndent();
- ipw.println("}");
+ pw.decreaseIndent();
+ pw.println("}");
} else if (mPrivateLayout != null) {
- mPrivateLayout.dumpSmartReplies(ipw);
+ mPrivateLayout.dumpSmartReplies(pw);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index fa2c1ee..4b3d6f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -22,6 +22,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -743,15 +744,16 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
pw.println(getClass().getSimpleName());
- DumpUtilsKt.withIndenting(pw, ipw -> {
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
ExpandableViewState viewState = getViewState();
if (viewState == null) {
- ipw.println("no viewState!!!");
+ pw.println("no viewState!!!");
} else {
- viewState.dump(fd, ipw, args);
- ipw.println();
+ viewState.dump(fd, pw, args);
+ pw.println();
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index b27a40a..e8e6e31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -20,6 +20,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
import android.view.View;
import com.android.systemui.R;
@@ -49,14 +50,15 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
super.dump(fd, pw, args);
- DumpUtilsKt.withIndenting(pw, ipw -> {
- ipw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
- ipw.println("manageButton showHistory: " + mShowHistory);
- ipw.println("manageButton visibility: "
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
+ pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
+ pw.println("manageButton showHistory: " + mShowHistory);
+ pw.println("manageButton visibility: "
+ DumpUtilsKt.visibilityString(mDismissButton.getVisibility()));
- ipw.println("dismissButton visibility: "
+ pw.println("dismissButton visibility: "
+ DumpUtilsKt.visibilityString(mDismissButton.getVisibility()));
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index ea25805..44e3718 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -47,6 +47,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
@@ -4901,7 +4902,8 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
StringBuilder sb = new StringBuilder("[")
.append(this.getClass().getSimpleName()).append(":")
.append(" pulsing=").append(mPulsing ? "T" : "f")
@@ -4915,15 +4917,15 @@
.append(" hideAmount=").append(mAmbientState.getHideAmount())
.append("]");
pw.println(sb.toString());
- DumpUtilsKt.withIndenting(pw, ipw -> {
+ DumpUtilsKt.withIncreasedIndent(pw, () -> {
int childCount = getChildCount();
- ipw.println("Number of children: " + childCount);
- ipw.println();
+ pw.println("Number of children: " + childCount);
+ pw.println();
for (int i = 0; i < childCount; i++) {
ExpandableView child = (ExpandableView) getChildAt(i);
- child.dump(fd, ipw, args);
- ipw.println();
+ child.dump(fd, pw, args);
+ pw.println();
}
int transientViewCount = getTransientViewCount();
pw.println("Transient Views: " + transientViewCount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 407d287..622c45e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -72,6 +72,7 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
@@ -154,6 +155,7 @@
private ControlsComponent mControlsComponent;
private boolean mControlServicesAvailable = false;
+ @Nullable private View mAmbientIndicationArea;
private ViewGroup mIndicationArea;
private TextView mIndicationText;
private TextView mIndicationTextBottom;
@@ -274,6 +276,29 @@
public void initFrom(KeyguardBottomAreaView oldBottomArea) {
setStatusBar(oldBottomArea.mStatusBar);
+
+ // if it exists, continue to use the original ambient indication container
+ // instead of the newly inflated one
+ if (mAmbientIndicationArea != null) {
+ // remove old ambient indication from its parent
+ View originalAmbientIndicationView =
+ oldBottomArea.findViewById(R.id.ambient_indication_container);
+ ((ViewGroup) originalAmbientIndicationView.getParent())
+ .removeView(originalAmbientIndicationView);
+
+ // remove current ambient indication from its parent (discard)
+ ViewGroup ambientIndicationParent = (ViewGroup) mAmbientIndicationArea.getParent();
+ int ambientIndicationIndex =
+ ambientIndicationParent.indexOfChild(mAmbientIndicationArea);
+ ambientIndicationParent.removeView(mAmbientIndicationArea);
+
+ // add the old ambient indication to this view
+ ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex);
+ mAmbientIndicationArea = originalAmbientIndicationView;
+
+ // update burn-in offsets
+ dozeTimeTick();
+ }
}
@Override
@@ -288,6 +313,7 @@
mQRCodeScannerButton = findViewById(R.id.qr_code_scanner_button);
mControlsButton = findViewById(R.id.controls_button);
mIndicationArea = findViewById(R.id.keyguard_indication_area);
+ mAmbientIndicationArea = findViewById(R.id.ambient_indication_container);
mIndicationText = findViewById(R.id.keyguard_indication_text);
mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom);
mIndicationBottomMargin = getResources().getDimensionPixelSize(
@@ -923,6 +949,7 @@
int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
- mBurnInYOffset;
mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
+ mAmbientIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
}
public void setAntiBurnInOffsetX(int burnInXOffset) {
@@ -931,6 +958,7 @@
}
mBurnInXOffset = burnInXOffset;
mIndicationArea.setTranslationX(burnInXOffset);
+ mAmbientIndicationArea.setTranslationX(burnInXOffset);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 763984f..84ef079 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -90,6 +90,7 @@
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
@@ -133,6 +134,7 @@
import com.android.systemui.InitController;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.assist.AssistManager;
@@ -735,6 +737,7 @@
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
+ AccessibilityFloatingMenuController accessibilityFloatingMenuController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
NotificationShadeWindowController notificationShadeWindowController,
@@ -838,6 +841,7 @@
mVisualStabilityManager = visualStabilityManager;
mDeviceProvisionedController = deviceProvisionedController;
mNavigationBarController = navigationBarController;
+ mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
mAssistManagerLazy = assistManagerLazy;
mConfigurationController = configurationController;
mNotificationShadeWindowController = notificationShadeWindowController;
@@ -1053,6 +1057,8 @@
mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
mLifecycle.setCurrentState(RESUMED);
+ mAccessibilityFloatingMenuController.init();
+
// set the initial view visibility
int disabledFlags1 = result.mDisabledFlags1;
int disabledFlags2 = result.mDisabledFlags2;
@@ -2292,7 +2298,8 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+ IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
synchronized (mQueueLock) {
pw.println("Current Status Bar state:");
pw.println(" mExpandedVisible=" + mExpandedVisible);
@@ -2333,14 +2340,12 @@
}
pw.println(" mStackScroller: ");
if (mStackScroller != null) {
- DumpUtilsKt.withIndenting(pw, ipw -> {
- // Triple indent until we rewrite the rest of this dump()
- ipw.increaseIndent();
- ipw.increaseIndent();
- mStackScroller.dump(fd, ipw, args);
- ipw.decreaseIndent();
- ipw.decreaseIndent();
- });
+ // Double indent until we rewrite the rest of this dump()
+ pw.increaseIndent();
+ pw.increaseIndent();
+ mStackScroller.dump(fd, pw, args);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
}
pw.println(" Theme:");
String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
@@ -3813,6 +3818,7 @@
private final DeviceProvisionedController mDeviceProvisionedController;
private final NavigationBarController mNavigationBarController;
+ private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
// UI-specific methods
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 24b7b7f..33171b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -28,6 +28,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.InitController;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -185,6 +186,7 @@
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
+ AccessibilityFloatingMenuController accessibilityFloatingMenuController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
NotificationShadeWindowController notificationShadeWindowController,
@@ -287,6 +289,7 @@
visualStabilityManager,
deviceProvisionedController,
navigationBarController,
+ accessibilityFloatingMenuController,
assistManagerLazy,
configurationController,
notificationShadeWindowController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
index 530da43..ef0a5b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
@@ -95,7 +95,6 @@
private val uiEventLogger: UiEventLogger
) : RemoteInputViewController {
- private object Token
private val onSendListeners = ArraySet<OnSendRemoteInputListener>()
private val resources get() = view.resources
@@ -179,8 +178,8 @@
entry.lastRemoteInputSent = SystemClock.elapsedRealtime()
entry.mRemoteEditImeAnimatingAway = true
- remoteInputController.addSpinning(entry.key, Token)
- remoteInputController.removeRemoteInput(entry, Token)
+ remoteInputController.addSpinning(entry.key, view.mToken)
+ remoteInputController.removeRemoteInput(entry, view.mToken)
remoteInputController.remoteInputSent(entry)
entry.setHasSentReply()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt
new file mode 100644
index 0000000..c6dbdb1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 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.policy
+
+/**
+ * Interface for tracking packages with running foreground services and demoting foreground status
+ */
+interface RunningFgsController : CallbackController<RunningFgsController.Callback> {
+
+ /**
+ * @return A list of [UserPackageTime]s which have running foreground service(s)
+ */
+ fun getPackagesWithFgs(): List<UserPackageTime>
+
+ /**
+ * Stops all foreground services running as a package
+ * @param userId the userId the package is running under
+ * @param packageName the packageName
+ */
+ fun stopFgs(userId: Int, packageName: String)
+
+ /**
+ * Returns when the list of packages with foreground services changes
+ */
+ interface Callback {
+ /**
+ * The thing that
+ * @param packages the list of packages
+ */
+ fun onFgsPackagesChanged(packages: List<UserPackageTime>)
+ }
+
+ /**
+ * A triplet <user, packageName, timeMillis> where each element is a package running
+ * under a user that has had at least one foreground service running since timeMillis.
+ * Time should be derived from [SystemClock.elapsedRealtime].
+ */
+ data class UserPackageTime(val userId: Int, val packageName: String, val startTimeMillis: Long)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt
new file mode 100644
index 0000000..d44d365
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2021 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.policy
+
+import android.app.IActivityManager
+import android.app.IForegroundServiceObserver
+import android.os.IBinder
+import android.os.RemoteException
+import android.util.Log
+import androidx.annotation.GuardedBy
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.policy.RunningFgsController.Callback
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Implementation for [RunningFgsController]
+ */
+@SysUISingleton
+class RunningFgsControllerImpl @Inject constructor(
+ @Background private val executor: Executor,
+ private val systemClock: SystemClock,
+ private val activityManager: IActivityManager
+) : RunningFgsController, IForegroundServiceObserver.Stub() {
+
+ companion object {
+ private val LOG_TAG = RunningFgsControllerImpl::class.java.simpleName
+ }
+
+ private val lock = Any()
+
+ @GuardedBy("lock")
+ var initialized = false
+
+ @GuardedBy("lock")
+ private val runningServiceTokens = mutableMapOf<UserPackageKey, StartTimeAndTokensValue>()
+
+ @GuardedBy("lock")
+ private val callbacks = mutableSetOf<Callback>()
+
+ fun init() {
+ synchronized(lock) {
+ if (initialized) {
+ return
+ }
+ try {
+ activityManager.registerForegroundServiceObserver(this)
+ } catch (e: RemoteException) {
+ e.rethrowFromSystemServer()
+ }
+
+ initialized = true
+ }
+ }
+
+ override fun addCallback(listener: Callback) {
+ init()
+ synchronized(lock) { callbacks.add(listener) }
+ }
+
+ override fun removeCallback(listener: Callback) {
+ init()
+ synchronized(lock) {
+ if (!callbacks.remove(listener)) {
+ Log.e(LOG_TAG, "Callback was not registered.", RuntimeException())
+ }
+ }
+ }
+
+ override fun observe(lifecycle: Lifecycle?, listener: Callback?): Callback {
+ init()
+ return super.observe(lifecycle, listener)
+ }
+
+ override fun observe(owner: LifecycleOwner?, listener: Callback?): Callback {
+ init()
+ return super.observe(owner, listener)
+ }
+
+ override fun getPackagesWithFgs(): List<UserPackageTime> {
+ init()
+ return synchronized(lock) { getPackagesWithFgsLocked() }
+ }
+
+ private fun getPackagesWithFgsLocked(): List<UserPackageTime> =
+ runningServiceTokens.map {
+ UserPackageTime(it.key.userId, it.key.packageName, it.value.fgsStartTime)
+ }
+
+ override fun stopFgs(userId: Int, packageName: String) {
+ init()
+ try {
+ activityManager.makeServicesNonForeground(packageName, userId)
+ } catch (e: RemoteException) {
+ e.rethrowFromSystemServer()
+ }
+ }
+
+ private data class UserPackageKey(
+ val userId: Int,
+ val packageName: String
+ )
+
+ private class StartTimeAndTokensValue(systemClock: SystemClock) {
+ val fgsStartTime = systemClock.elapsedRealtime()
+ var tokens = mutableSetOf<IBinder>()
+ fun addToken(token: IBinder): Boolean {
+ return tokens.add(token)
+ }
+
+ fun removeToken(token: IBinder): Boolean {
+ return tokens.remove(token)
+ }
+
+ val isEmpty: Boolean
+ get() = tokens.isEmpty()
+ }
+
+ override fun onForegroundStateChanged(
+ token: IBinder,
+ packageName: String,
+ userId: Int,
+ isForeground: Boolean
+ ) {
+ val result = synchronized(lock) {
+ val userPackageKey = UserPackageKey(userId, packageName)
+ if (isForeground) {
+ var addedNew = false
+ runningServiceTokens.getOrPut(userPackageKey) {
+ addedNew = true
+ StartTimeAndTokensValue(systemClock)
+ }.addToken(token)
+ if (!addedNew) {
+ return
+ }
+ } else {
+ val startTimeAndTokensValue = runningServiceTokens[userPackageKey]
+ if (startTimeAndTokensValue?.removeToken(token) == false) {
+ Log.e(LOG_TAG,
+ "Stopped foreground service was not known to be running.")
+ return
+ }
+ if (!startTimeAndTokensValue!!.isEmpty) {
+ return
+ }
+ runningServiceTokens.remove(userPackageKey)
+ }
+ getPackagesWithFgsLocked().toList()
+ }
+
+ callbacks.forEach { executor.execute { it.onFgsPackagesChanged(result) } }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 7a664b0..a537b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -219,6 +219,7 @@
private void clearLayoutLineCount(View view) {
if (view instanceof TextView) {
((TextView) view).nullLayouts();
+ view.forceLayout();
}
}
@@ -271,6 +272,9 @@
clearLayoutLineCount(child);
child.measure(MEASURE_SPEC_ANY_LENGTH, heightMeasureSpec);
+ if (((Button) child).getLayout() == null) {
+ Log.wtf(TAG, "Button layout is null after measure.");
+ }
coveredSuggestions.add(child);
@@ -604,6 +608,9 @@
button.getPaddingLeft() + button.getPaddingRight() + textWidth
+ getLeftCompoundDrawableWidthWithPadding(button), MeasureSpec.AT_MOST);
button.measure(widthMeasureSpec, heightMeasureSpec);
+ if (button.getLayout() == null) {
+ Log.wtf(TAG, "Button layout is null after measure.");
+ }
final int newWidth = button.getMeasuredWidth();
diff --git a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
index 9f33c27..f952476 100644
--- a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
@@ -19,39 +19,15 @@
import android.util.IndentingPrintWriter
import android.view.View
import java.io.PrintWriter
-import java.util.function.Consumer
/**
- * Run some code that will print to an [IndentingPrintWriter] that wraps the given [PrintWriter].
+ * Get an [IndentingPrintWriter] which either is or wraps the given [PrintWriter].
*
- * If the given [PrintWriter] is an [IndentingPrintWriter], the block will be passed that same
- * instance with [IndentingPrintWriter.increaseIndent] having been called, and calling
- * [IndentingPrintWriter.decreaseIndent] after completion of the block, so the passed [PrintWriter]
- * should not be used before the block completes.
+ * The original [PrintWriter] should not be used until the returned [IndentingPrintWriter] is no
+ * longer being used, to avoid inconsistent writing.
*/
-inline fun PrintWriter.withIndenting(block: (IndentingPrintWriter) -> Unit) {
- if (this is IndentingPrintWriter) {
- this.withIncreasedIndent { block(this) }
- } else {
- block(IndentingPrintWriter(this))
- }
-}
-
-/**
- * Run some code that will print to an [IndentingPrintWriter] that wraps the given [PrintWriter].
- *
- * If the given [PrintWriter] is an [IndentingPrintWriter], the block will be passed that same
- * instance with [IndentingPrintWriter.increaseIndent] having been called, and calling
- * [IndentingPrintWriter.decreaseIndent] after completion of the block, so the passed [PrintWriter]
- * should not be used before the block completes.
- */
-fun PrintWriter.withIndenting(consumer: Consumer<IndentingPrintWriter>) {
- if (this is IndentingPrintWriter) {
- this.withIncreasedIndent { consumer.accept(this) }
- } else {
- consumer.accept(IndentingPrintWriter(this))
- }
-}
+fun PrintWriter.asIndenting(): IndentingPrintWriter =
+ (this as? IndentingPrintWriter) ?: IndentingPrintWriter(this)
/**
* Run some code inside a block, with [IndentingPrintWriter.increaseIndent] having been called on
@@ -66,6 +42,19 @@
}
}
+/**
+ * Run some code inside a block, with [IndentingPrintWriter.increaseIndent] having been called on
+ * the given argument, and calling [IndentingPrintWriter.decreaseIndent] after completion.
+ */
+fun IndentingPrintWriter.withIncreasedIndent(runnable: Runnable) {
+ this.increaseIndent()
+ try {
+ runnable.run()
+ } finally {
+ this.decreaseIndent()
+ }
+}
+
/** Return a readable string for the visibility */
fun visibilityString(@View.Visibility visibility: Int): String = when (visibility) {
View.GONE -> "gone"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
index 326d902..796af11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
@@ -100,11 +100,11 @@
@Test
public void enableWindowMagnification_passThrough() throws RemoteException {
mIWindowMagnificationConnection.enableWindowMagnification(TEST_DISPLAY, 3.0f, Float.NaN,
- Float.NaN, mAnimationCallback);
+ Float.NaN, 0f, 0f, mAnimationCallback);
waitForIdleSync();
verify(mWindowMagnificationController).enableWindowMagnification(eq(3.0f),
- eq(Float.NaN), eq(Float.NaN), eq(mAnimationCallback));
+ eq(Float.NaN), eq(Float.NaN), eq(0f), eq(0f), eq(mAnimationCallback));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
index 8bb9d42..44770fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
@@ -110,7 +110,7 @@
}
/**
- * Sets the given window insets to the current window metics.
+ * Sets the given window insets to the current window metrics.
*
* @param insets the window insets.
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 854fc33..3cc177d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -17,22 +17,27 @@
package com.android.systemui.accessibility;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.app.Instrumentation;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowManager;
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
import android.view.animation.AccelerateInterpolator;
@@ -40,6 +45,7 @@
import androidx.test.filters.LargeTest;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
@@ -56,7 +62,6 @@
import java.util.concurrent.atomic.AtomicReference;
-
@Ignore
@LargeTest
@RunWith(AndroidTestingRunner.class)
@@ -74,6 +79,8 @@
private ArgumentCaptor<Float> mScaleCaptor = ArgumentCaptor.forClass(Float.class);
private ArgumentCaptor<Float> mCenterXCaptor = ArgumentCaptor.forClass(Float.class);
private ArgumentCaptor<Float> mCenterYCaptor = ArgumentCaptor.forClass(Float.class);
+ private final ArgumentCaptor<Float> mOffsetXCaptor = ArgumentCaptor.forClass(Float.class);
+ private final ArgumentCaptor<Float> mOffsetYCaptor = ArgumentCaptor.forClass(Float.class);
@Mock
Handler mHandler;
@@ -94,10 +101,16 @@
private long mWaitingAnimationPeriod;
private long mWaitIntermediateAnimationPeriod;
+ private TestableWindowManager mWindowManager;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ final WindowManager wm = mContext.getSystemService(WindowManager.class);
+ mWindowManager = spy(new TestableWindowManager(wm));
+ mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
+
mWaitingAnimationPeriod = 2 * ANIMATION_DURATION_MS;
mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2;
mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
@@ -119,12 +132,15 @@
throws RemoteException {
enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
verifyStartValue(mScaleCaptor, 1.0f);
verifyStartValue(mCenterXCaptor, DEFAULT_CENTER_X);
verifyStartValue(mCenterYCaptor, DEFAULT_CENTER_Y);
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
verify(mAnimationCallback).onResult(true);
}
@@ -162,8 +178,8 @@
});
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController).enableWindowMagnification(1, DEFAULT_CENTER_X,
- DEFAULT_CENTER_Y);
+ verify(mSpyController).enableWindowMagnificationInternal(1, DEFAULT_CENTER_X,
+ DEFAULT_CENTER_Y, 0f, 0f);
verify(mAnimationCallback).onResult(true);
}
@@ -187,11 +203,15 @@
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
verifyStartValue(mScaleCaptor, mCurrentScale.get());
verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
verify(mAnimationCallback).onResult(false);
verify(mAnimationCallback2).onResult(true);
@@ -213,11 +233,15 @@
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
verifyStartValue(mScaleCaptor, mCurrentScale.get());
verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
// It presents the window magnification is disabled.
verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
@@ -256,7 +280,7 @@
});
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+ verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
anyFloat());
verify(mAnimationCallback).onResult(false);
verify(mAnimationCallback2).onResult(true);
@@ -286,9 +310,10 @@
verify(mAnimationCallback).onResult(false);
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
//Animating in reverse, so we only check if the start values are greater than current.
assertTrue(mScaleCaptor.getAllValues().get(0) > mCurrentScale.get());
assertEquals(targetScale, mScaleCaptor.getValue(), 0f);
@@ -336,7 +361,7 @@
});
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+ verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
anyFloat());
verify(mSpyController, never()).deleteWindowMagnification();
verify(mAnimationCallback).onResult(false);
@@ -362,23 +387,51 @@
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
verifyStartValue(mScaleCaptor, mCurrentScale.get());
verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
verify(mAnimationCallback2).onResult(true);
}
@Test
+ public void enableWindowMagnificationWithOffset_expectedValues() {
+ final float offsetRatio = -0.1f;
+ final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
+ mInstrumentation.runOnMainSync(() -> {
+ Mockito.reset(mSpyController);
+ mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+ windowBounds.exactCenterX(), windowBounds.exactCenterY(),
+ offsetRatio, offsetRatio, mAnimationCallback);
+ });
+ SystemClock.sleep(mWaitingAnimationPeriod);
+ final View attachedView = mWindowManager.getAttachedView();
+ assertNotNull(attachedView);
+ final Rect mirrorViewBound = new Rect();
+ final View mirrorView = attachedView.findViewById(R.id.surface_view);
+ assertNotNull(mirrorView);
+ mirrorView.getBoundsOnScreen(mirrorViewBound);
+
+ assertEquals(mirrorViewBound.exactCenterX() - windowBounds.exactCenterX(),
+ Math.round(offsetRatio * mirrorViewBound.width() / 2), 0.1f);
+ assertEquals(mirrorViewBound.exactCenterY() - windowBounds.exactCenterY(),
+ Math.round(offsetRatio * mirrorViewBound.height() / 2), 0.1f);
+ }
+
+ @Test
public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback()
throws RemoteException {
enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
- verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+ verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
anyFloat());
verify(mAnimationCallback).onResult(true);
}
@@ -390,11 +443,15 @@
deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
verifyStartValue(mScaleCaptor, DEFAULT_SCALE);
verifyStartValue(mCenterXCaptor, Float.NaN);
verifyStartValue(mCenterYCaptor, Float.NaN);
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
verify(mAnimationCallback).onResult(true);
}
@@ -433,8 +490,10 @@
mCurrentCenterY.set(mController.getCenterY());
});
SystemClock.sleep(mWaitingAnimationPeriod);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
//The animation is in verse, so we only check the start values should no be greater than
// the current one.
@@ -442,6 +501,8 @@
assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
verifyStartValue(mCenterXCaptor, Float.NaN);
verifyStartValue(mCenterYCaptor, Float.NaN);
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
verify(mAnimationCallback).onResult(false);
verify(mAnimationCallback2).onResult(true);
@@ -471,9 +532,13 @@
deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback2);
- verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
- mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+ mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
+ verifyStartValue(mOffsetXCaptor, 0f);
+ verifyStartValue(mOffsetYCaptor, 0f);
verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
verify(mAnimationCallback).onResult(false);
verify(mAnimationCallback2).onResult(true);
@@ -571,9 +636,18 @@
}
@Override
- void enableWindowMagnification(float scale, float centerX, float centerY) {
- super.enableWindowMagnification(scale, centerX, centerY);
- mSpyController.enableWindowMagnification(scale, centerX, centerY);
+ void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
+ super.enableWindowMagnificationInternal(scale, centerX, centerY);
+ mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY);
+ }
+
+ @Override
+ void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+ float magnificationOffsetFrameRatioX, float magnificationOffsetFrameRatioY) {
+ super.enableWindowMagnificationInternal(scale, centerX, centerY,
+ magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
+ mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY,
+ magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 9a30465..8fdcadd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -146,7 +146,7 @@
@Test
public void enableWindowMagnification_showControlAndNotifyBoundsChanged() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -159,7 +159,7 @@
@Test
public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
// Wait for Rects updated.
@@ -180,7 +180,7 @@
mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState);
mInstrumentation.runOnMainSync(() -> {
- controller.enableWindowMagnification(Float.NaN, Float.NaN,
+ controller.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -195,7 +195,7 @@
@Test
public void deleteWindowMagnification_destroyControl() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -213,7 +213,7 @@
setSystemGestureInsets();
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
bounds.bottom);
});
ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag);
@@ -229,7 +229,7 @@
@Test
public void moveMagnifier_schedulesFrame() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
mWindowMagnificationController.moveWindowMagnifier(100f, 100f);
});
@@ -246,8 +246,8 @@
}).when(mHandler).postDelayed(any(Runnable.class), anyLong());
mInstrumentation.runOnMainSync(
- () -> mWindowMagnificationController.enableWindowMagnification(2.0f, Float.NaN,
- Float.NaN));
+ () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f,
+ Float.NaN, Float.NaN));
mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f));
@@ -283,8 +283,8 @@
final float displayWidth = windowBounds.width();
final PointF magnifiedCenter = new PointF(center, center + 5f);
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, magnifiedCenter.x,
- magnifiedCenter.y);
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+ magnifiedCenter.x, magnifiedCenter.y);
// Get the center again in case the center we set is out of screen.
magnifiedCenter.set(mWindowMagnificationController.getCenterX(),
mWindowMagnificationController.getCenterY());
@@ -327,7 +327,7 @@
testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
testWindowBounds.right + 100, testWindowBounds.bottom + 100);
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
mWindowManager.setWindowBounds(testWindowBounds);
@@ -347,7 +347,7 @@
@Test
public void screenSizeIsChangedToLarge_enabled_windowSizeIsConstrained() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
final int screenSize = mContext.getResources().getDimensionPixelSize(
@@ -369,7 +369,7 @@
@Test
public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
Mockito.reset(mWindowManager);
Mockito.reset(mMirrorWindowControl);
@@ -398,7 +398,7 @@
@Test
public void initializeA11yNode_enabled_expectedValues() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
Float.NaN);
});
final View mirrorView = mWindowManager.getAttachedView();
@@ -422,7 +422,7 @@
public void performA11yActions_visible_expectedResults() {
final int displayId = mContext.getDisplayId();
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
Float.NaN);
});
@@ -449,7 +449,7 @@
public void performA11yActions_visible_notifyAccessibilityActionPerformed() {
final int displayId = mContext.getDisplayId();
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
Float.NaN);
});
@@ -462,7 +462,7 @@
@Test
public void enableWindowMagnification_hasA11yWindowTitle() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -473,12 +473,12 @@
@Test
public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(0.9f, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN,
Float.NaN);
});
@@ -489,7 +489,7 @@
public void onLocaleChanged_enabled_updateA11yWindowTitle() {
final String newA11yWindowTitle = "new a11y window title";
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
final TestableResources testableResources = getContext().getOrCreateTestableResources();
@@ -506,7 +506,7 @@
@Test
public void onSingleTap_enabled_scaleIsChanged() {
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -530,7 +530,7 @@
final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
setSystemGestureInsets();
mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index cdf40a1..8ca17b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -291,9 +291,12 @@
mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class));
mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class));
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+ final AccessibilityFloatingMenuController controller =
+ new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver,
+ mModeObserver, mKeyguardUpdateMonitor);
+ controller.init();
- return new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver,
- mModeObserver, mKeyguardUpdateMonitor);
+ return controller;
}
private void enableAccessibilityFloatingMenuConfig() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 52173c1..1b5e5eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -121,7 +121,6 @@
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
R.string.media_output_dialog_pairing_new));
}
@@ -139,7 +138,6 @@
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_SESSION_NAME);
}
@@ -156,7 +154,6 @@
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getString(
R.string.media_output_dialog_group));
}
@@ -165,14 +162,13 @@
public void onBindViewHolder_bindConnectedDevice_verifyView() {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
@Test
@@ -199,7 +195,6 @@
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
}
@@ -213,13 +208,10 @@
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
TEST_DEVICE_NAME_2);
- assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
- mContext.getString(R.string.media_output_dialog_disconnected));
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -233,7 +225,6 @@
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
@@ -248,14 +239,13 @@
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -268,7 +258,6 @@
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 053851e..4dac6d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.testing.AndroidTestingRunner;
@@ -70,6 +71,7 @@
private MediaOutputController mMediaOutputController;
private int mHeaderIconRes;
private IconCompat mIconCompat;
+ private Drawable mAppSourceDrawable;
private CharSequence mHeaderTitle;
private CharSequence mHeaderSubtitle;
@@ -173,6 +175,11 @@
}
@Override
+ Drawable getAppSourceIcon() {
+ return mAppSourceDrawable;
+ }
+
+ @Override
int getHeaderIconRes() {
return mHeaderIconRes;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 09ec4ca..d71d98e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -234,7 +235,7 @@
mMediaOutputController.onRequestFailed(0 /* reason */);
- verify(mCb).onRouteChanged();
+ verify(mCb, atLeastOnce()).onRouteChanged();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
index ca5d570..2c883a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
@@ -100,7 +100,6 @@
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getText(
@@ -114,7 +113,6 @@
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -140,7 +138,6 @@
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -165,7 +162,6 @@
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -183,7 +179,6 @@
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index ed5b8cb..a445d6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -18,6 +18,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -34,6 +35,7 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import org.junit.Before;
@@ -42,6 +44,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
import dagger.Lazy;
@RunWith(AndroidJUnit4.class)
@@ -82,8 +86,8 @@
mNavBarHelper = new NavBarHelper(mContext, mAccessibilityManager,
mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver,
- mOverviewProxyService, mAssistManagerLazy, mNavigationModeController,
- mUserTracker, mDumpManager);
+ mOverviewProxyService, mAssistManagerLazy, () -> Optional.of(mock(StatusBar.class)),
+ mNavigationModeController, mUserTracker, mDumpManager);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index e038b6e..5003013 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -76,6 +76,7 @@
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -90,6 +91,7 @@
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -103,6 +105,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.util.Optional;
@@ -135,7 +138,6 @@
EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
@Mock
EdgeBackGestureHandler mEdgeBackGestureHandler;
- @Mock
NavBarHelper mNavBarHelper;
@Mock
private LightBarController mLightBarController;
@@ -179,6 +181,12 @@
mDependency.injectTestDependency(OverviewProxyService.class, mOverviewProxyService);
mDependency.injectTestDependency(NavigationModeController.class, mNavigationModeController);
TestableLooper.get(this).runWithLooper(() -> {
+ mNavBarHelper = spy(new NavBarHelper(mContext, mock(AccessibilityManager.class),
+ mock(AccessibilityManagerWrapper.class),
+ mock(AccessibilityButtonModeObserver.class), mOverviewProxyService,
+ () -> mock(AssistManager.class), () -> Optional.of(mStatusBar),
+ mock(NavigationModeController.class), mock(UserTracker.class),
+ mock(DumpManager.class)));
mNavigationBar = createNavBar(mContext);
mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
});
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
index 210744e..3257a84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
@@ -47,8 +47,8 @@
@Test
fun initFrom_doesntCrash() {
- val other = LayoutInflater.from(mContext).inflate(
- R.layout.keyguard_bottom_area, null, false) as KeyguardBottomAreaView
+ val other = LayoutInflater.from(mContext).inflate(R.layout.keyguard_bottom_area,
+ null, false) as KeyguardBottomAreaView
other.initFrom(mKeyguardBottomArea)
other.launchVoiceAssist()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 6625d73..a34d2f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -77,6 +77,7 @@
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -219,6 +220,7 @@
@Mock private NotificationGutsManager mNotificationGutsManager;
@Mock private NotificationMediaManager mNotificationMediaManager;
@Mock private NavigationBarController mNavigationBarController;
+ @Mock private AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
@Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock private ColorExtractor.GradientColors mGradientColors;
@@ -416,6 +418,7 @@
mVisualStabilityManager,
mDeviceProvisionedController,
mNavigationBarController,
+ mAccessibilityFloatingMenuController,
() -> mAssistManager,
configurationController,
mNotificationShadeWindowController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index d36c516..526f5b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -21,7 +21,6 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import android.app.Fragment;
@@ -63,7 +62,6 @@
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -85,7 +83,6 @@
// Set in instantiate()
private StatusBarIconController mStatusBarIconController;
private NetworkController mNetworkController;
- private StatusBarStateController mStatusBarStateController;
private KeyguardStateController mKeyguardStateController;
private final StatusBar mStatusBar = mock(StatusBar.class);
@@ -98,7 +95,11 @@
@Mock
private StatusBarFragmentComponent mStatusBarFragmentComponent;
@Mock
+ private StatusBarStateController mStatusBarStateController;
+ @Mock
private HeadsUpAppearanceController mHeadsUpAppearanceController;
+ @Mock
+ private NotificationPanelViewController mNotificationPanelViewController;
public CollapsedStatusBarFragmentTest() {
super(CollapsedStatusBarFragment.class);
@@ -106,49 +107,35 @@
@Before
public void setup() {
- mStatusBarStateController = mDependency
- .injectMockDependency(StatusBarStateController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- when(mStatusBar.getPanelController()).thenReturn(
- mock(NotificationPanelViewController.class));
}
@Test
- public void testDisableNone() throws Exception {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ public void testDisableNone() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
- .getVisibility());
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock)
- .getVisibility());
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
}
@Test
- public void testDisableSystemInfo() throws Exception {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ public void testDisableSystemInfo() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
- assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
- .getVisibility());
+ assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
- .getVisibility());
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
}
@Test
- public void testDisableNotifications() throws Exception {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ public void testDisableNotifications() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
@@ -160,25 +147,21 @@
}
@Test
- public void testDisableClock() throws Exception {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ public void testDisableClock() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_CLOCK, 0, false);
- assertEquals(View.GONE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+ assertEquals(View.GONE, getClockView().getVisibility());
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
}
@Test
public void disable_noOngoingCall_chipHidden() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
@@ -190,9 +173,7 @@
@Test
public void disable_hasOngoingCall_chipDisplayedAndNotificationIconsHidden() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
@@ -206,9 +187,7 @@
@Test
public void disable_hasOngoingCallButNotificationIconsDisabled_chipHidden() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
@@ -221,9 +200,7 @@
@Test
public void disable_ongoingCallEnded_chipHidden() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
@@ -241,56 +218,87 @@
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
}
- @Ignore("b/192618546")
@Test
- public void testOnDozingChanged() throws Exception {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
- fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
-
- Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
-
- reset(mStatusBarStateController);
+ public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
+
+ fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
+ }
+
+ @Test
+ public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+ fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
+ }
+
+ @Test
+ public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+ // Make sure they start out as visible
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
+
+ fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+ assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.GONE, getClockView().getVisibility());
+ }
+
+ @Test
+ public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() {
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+ // Make sure they start out as visible
+ assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
+
fragment.onDozingChanged(true);
- Mockito.verify(mStatusBarStateController).isDozing();
- Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
+ // When this callback is triggered, we want to make sure the clock and system info
+ // visibilities are recalculated. Since dozing=true, they shouldn't be visible.
+ assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+ assertEquals(View.GONE, getClockView().getVisibility());
}
@Test
public void disable_headsUpShouldBeVisibleTrue_clockDisabled() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+ assertEquals(View.GONE, getClockView().getVisibility());
}
@Test
public void disable_headsUpShouldBeVisibleFalse_clockNotDisabled() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+ assertEquals(View.VISIBLE, getClockView().getVisibility());
}
@Test
public void setUp_fragmentCreatesDaggerComponent() {
- mFragments.dispatchResume();
- processAllMessages();
- CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ CollapsedStatusBarFragment fragment = resumeAndGetFragment();
assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent());
}
@@ -324,7 +332,7 @@
new StatusBarHideIconsForBouncerManager(
mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()),
mKeyguardStateController,
- mock(NotificationPanelViewController.class),
+ mNotificationPanelViewController,
mNetworkController,
mStatusBarStateController,
() -> Optional.of(mStatusBar),
@@ -361,4 +369,18 @@
when(mMockNotificationAreaController.getNotificationInnerAreaView()).thenReturn(
mNotificationAreaInner);
}
+
+ private CollapsedStatusBarFragment resumeAndGetFragment() {
+ mFragments.dispatchResume();
+ processAllMessages();
+ return (CollapsedStatusBarFragment) mFragment;
+ }
+
+ private View getClockView() {
+ return mFragment.getView().findViewById(R.id.clock);
+ }
+
+ private View getSystemIconAreaView() {
+ return mFragment.getView().findViewById(R.id.system_icon_area);
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 946d22e4..86777a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -537,6 +537,8 @@
// touch, we figure out what to do. If were waiting
// we resent the delayed callback and wait again.
mSendHoverEnterAndMoveDelayed.cancel();
+ // clear any hover events that might have been queued and never sent.
+ mSendHoverEnterAndMoveDelayed.clear();
mSendHoverExitDelayed.cancel();
// If a touch exploration gesture is in progress send events for its end.
if (mState.isTouchExploring()) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
index 5277425..25dcc2a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
@@ -59,15 +59,19 @@
}
boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+ float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
@Nullable MagnificationAnimationCallback callback) {
if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
mTrace.logTrace(TAG + ".enableWindowMagnification",
FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
"displayId=" + displayId + ";scale=" + scale + ";centerX=" + centerX
- + ";centerY=" + centerY + ";callback=" + callback);
+ + ";centerY=" + centerY + ";magnificationFrameOffsetRatioX="
+ + magnificationFrameOffsetRatioX + ";magnificationFrameOffsetRatioY="
+ + magnificationFrameOffsetRatioY + ";callback=" + callback);
}
try {
mConnection.enableWindowMagnification(displayId, scale, centerX, centerY,
+ magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
transformToRemoteCallback(callback, mTrace));
} catch (RemoteException e) {
if (DBG) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 7d8f545..820be28 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -18,6 +18,7 @@
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static java.util.Arrays.asList;
@@ -78,6 +79,8 @@
final DetectingState mDetectingState;
@VisibleForTesting
final PanningScalingGestureState mObservePanningScalingState;
+ @VisibleForTesting
+ final ViewportDraggingState mViewportDraggingState;
@VisibleForTesting
State mCurrentState;
@@ -105,6 +108,7 @@
policyFlags));
mDelegatingState = new DelegatingState(mMotionEventDispatcherDelegate);
mDetectingState = new DetectingState(context, mDetectTripleTap);
+ mViewportDraggingState = new ViewportDraggingState();
mObservePanningScalingState = new PanningScalingGestureState(
new PanningScalingHandler(context, MAX_SCALE, MIN_SCALE, true,
new PanningScalingHandler.MagnificationDelegate() {
@@ -158,7 +162,8 @@
public void handleShortcutTriggered() {
final Point screenSize = mTempPoint;
getScreenSize(mTempPoint);
- toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f);
+ toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f,
+ WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
}
private void getScreenSize(Point outSize) {
@@ -171,14 +176,17 @@
return Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
}
- private void enableWindowMagnifier(float centerX, float centerY) {
+ private void enableWindowMagnifier(float centerX, float centerY,
+ @WindowMagnificationManager.WindowPosition int windowPosition) {
if (DEBUG_ALL) {
- Slog.i(mLogTag, "enableWindowMagnifier :" + centerX + ", " + centerY);
+ Slog.i(mLogTag, "enableWindowMagnifier :"
+ + centerX + ", " + centerY + ", " + windowPosition);
}
final float scale = MathUtils.constrain(
mWindowMagnificationMgr.getPersistedScale(mDisplayId), MIN_SCALE, MAX_SCALE);
- mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY);
+ mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY,
+ windowPosition);
}
private void disableWindowMagnifier() {
@@ -188,11 +196,12 @@
mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, false);
}
- private void toggleMagnification(float centerX, float centerY) {
+ private void toggleMagnification(float centerX, float centerY,
+ @WindowMagnificationManager.WindowPosition int windowPosition) {
if (mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId)) {
disableWindowMagnifier();
} else {
- enableWindowMagnifier(centerX, centerY);
+ enableWindowMagnifier(centerX, centerY, windowPosition);
}
}
@@ -200,7 +209,17 @@
if (DEBUG_DETECTING) {
Slog.i(mLogTag, "onTripleTap()");
}
- toggleMagnification(up.getX(), up.getY());
+ toggleMagnification(up.getX(), up.getY(),
+ WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
+ }
+
+ private void onTripleTapAndHold(MotionEvent up) {
+ if (DEBUG_DETECTING) {
+ Slog.i(mLogTag, "onTripleTapAndHold()");
+ }
+ enableWindowMagnifier(up.getX(), up.getY(),
+ WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT);
+ transitionTo(mViewportDraggingState);
}
void resetToDetectState() {
@@ -319,6 +338,65 @@
}
}
+
+ /**
+ * This class handles motion events when the event dispatcher has
+ * determined that the user is performing a single-finger drag of the
+ * magnification viewport.
+ *
+ * Leaving this state until receiving {@link MotionEvent#ACTION_UP}
+ * or {@link MotionEvent#ACTION_CANCEL}.
+ */
+ final class ViewportDraggingState implements State {
+
+ private float mLastX = Float.NaN;
+ private float mLastY = Float.NaN;
+
+ @Override
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ final int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_MOVE: {
+ if (!Float.isNaN(mLastX) && !Float.isNaN(mLastY)) {
+ float offsetX = event.getX() - mLastX;
+ float offsetY = event.getY() - mLastY;
+ mWindowMagnificationMgr.moveWindowMagnification(mDisplayId, offsetX,
+ offsetY);
+ }
+ mLastX = event.getX();
+ mLastY = event.getY();
+ }
+ break;
+
+ case ACTION_UP:
+ case ACTION_CANCEL: {
+ mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true);
+ transitionTo(mDetectingState);
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void clear() {
+ mLastX = Float.NaN;
+ mLastY = Float.NaN;
+ }
+
+ @Override
+ public void onExit() {
+ clear();
+ }
+
+ @Override
+ public String toString() {
+ return "ViewportDraggingState{"
+ + "mLastX=" + mLastX
+ + ",mLastY=" + mLastY
+ + '}';
+ }
+ }
+
/**
* This class handles motion events in a duration to determine if the user is going to
* manipulate the window magnifier or want to interact with current UI. The rule of leaving
@@ -405,6 +483,8 @@
transitionTo(mObservePanningScalingState);
} else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP) {
onTripleTap(motionEvent);
+ } else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD) {
+ onTripleTapAndHold(motionEvent);
} else {
mMotionEventDispatcherDelegate.sendDelayedMotionEvents(delayedEventQueue,
lastDownEventTime);
@@ -439,6 +519,7 @@
return "WindowMagnificationGestureHandler{"
+ "mDetectingState=" + mDetectingState
+ ", mDelegatingState=" + mDelegatingState
+ + ", mViewportDraggingState=" + mViewportDraggingState
+ ", mMagnifiedInteractionState=" + mObservePanningScalingState
+ ", mCurrentState=" + State.nameOf(mCurrentState)
+ ", mPreviousState=" + State.nameOf(mPreviousState)
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index d34b4a9..9162064 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -20,12 +20,14 @@
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
@@ -44,6 +46,9 @@
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.statusbar.StatusBarManagerInternal;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}
* create by {@link #setConnection(IWindowMagnificationConnection)}. To set the connection with
@@ -58,6 +63,25 @@
private static final String TAG = "WindowMagnificationMgr";
+ /**
+ * Indicate that the magnification window is at the magnification center.
+ */
+ public static final int WINDOW_POSITION_AT_CENTER = 0;
+
+ /**
+ * Indicate that the magnification window is at the top-left side of the magnification
+ * center. The offset is equal to a half of MirrorSurfaceView. So, the bottom-right corner
+ * of the window is at the magnification center.
+ */
+ public static final int WINDOW_POSITION_AT_TOP_LEFT = 1;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "WINDOW_POSITION_AT_" }, value = {
+ WINDOW_POSITION_AT_CENTER,
+ WINDOW_POSITION_AT_TOP_LEFT
+ })
+ public @interface WindowPosition {}
+
private final Object mLock = new Object();
private final Context mContext;
@VisibleForTesting
@@ -281,20 +305,60 @@
}
/**
- * Enables window magnification with specified center and scale on the specified display and
+ * Enables window magnification with specified center and scale on the given display and
* animating the transition.
*
* @param displayId The logical display id.
* @param scale The target scale, must be >= 1.
- * @param centerX The screen-relative X coordinate around which to center,
+ * @param centerX The screen-relative X coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
- * @param centerY The screen-relative Y coordinate around which to center,
+ * @param centerY The screen-relative Y coordinate around which to center for magnification,
* or {@link Float#NaN} to leave unchanged.
* @param animationCallback Called when the animation result is valid.
* @return {@code true} if the magnification is enabled successfully.
*/
public boolean enableWindowMagnification(int displayId, float scale, float centerX,
float centerY, @Nullable MagnificationAnimationCallback animationCallback) {
+ return enableWindowMagnification(displayId, scale, centerX, centerY, animationCallback,
+ WINDOW_POSITION_AT_CENTER);
+ }
+
+ /**
+ * Enables window magnification with specified center and scale on the given display and
+ * animating the transition.
+ *
+ * @param displayId The logical display id.
+ * @param scale The target scale, must be >= 1.
+ * @param centerX The screen-relative X coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param centerY The screen-relative Y coordinate around which to center for magnification,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param windowPosition Indicate the offset between window position and (centerX, centerY).
+ * @return {@code true} if the magnification is enabled successfully.
+ */
+ public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+ float centerY, @WindowPosition int windowPosition) {
+ return enableWindowMagnification(displayId, scale, centerX, centerY,
+ STUB_ANIMATION_CALLBACK, windowPosition);
+ }
+
+ /**
+ * Enables window magnification with specified center and scale on the given display and
+ * animating the transition.
+ *
+ * @param displayId The logical display id.
+ * @param scale The target scale, must be >= 1.
+ * @param centerX The screen-relative X coordinate around which to center for
+ * magnification, or {@link Float#NaN} to leave unchanged.
+ * @param centerY The screen-relative Y coordinate around which to center for
+ * magnification, or {@link Float#NaN} to leave unchanged.
+ * @param animationCallback Called when the animation result is valid.
+ * @param windowPosition Indicate the offset between window position and (centerX, centerY).
+ * @return {@code true} if the magnification is enabled successfully.
+ */
+ public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+ float centerY, @Nullable MagnificationAnimationCallback animationCallback,
+ @WindowPosition int windowPosition) {
final boolean enabled;
boolean previousEnabled;
synchronized (mLock) {
@@ -307,7 +371,7 @@
}
previousEnabled = magnifier.mEnabled;
enabled = magnifier.enableWindowMagnificationInternal(scale, centerX, centerY,
- animationCallback);
+ animationCallback, windowPosition);
}
if (enabled && !previousEnabled) {
@@ -662,6 +726,8 @@
// The magnified bounds on the screen.
private final Rect mSourceBounds = new Rect();
+ private PointF mMagnificationFrameOffsetRatio = new PointF(0f, 0f);
+
WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) {
mDisplayId = displayId;
mWindowMagnificationManager = windowMagnificationManager;
@@ -669,14 +735,17 @@
@GuardedBy("mLock")
boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY,
- @Nullable MagnificationAnimationCallback animationCallback) {
+ @Nullable MagnificationAnimationCallback animationCallback,
+ @WindowPosition int windowPosition) {
// Handle defaults. The scale may be NAN when just updating magnification center.
if (Float.isNaN(scale)) {
scale = getScale();
}
final float normScale = MagnificationScaleProvider.constrainScale(scale);
+ setMagnificationFrameOffsetRatioByWindowPosition(windowPosition);
if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,
- centerX, centerY, animationCallback)) {
+ centerX, centerY, mMagnificationFrameOffsetRatio.x,
+ mMagnificationFrameOffsetRatio.y, animationCallback)) {
mScale = normScale;
mEnabled = true;
@@ -685,6 +754,19 @@
return false;
}
+ void setMagnificationFrameOffsetRatioByWindowPosition(@WindowPosition int windowPosition) {
+ switch (windowPosition) {
+ case WINDOW_POSITION_AT_CENTER: {
+ mMagnificationFrameOffsetRatio.set(0f, 0f);
+ }
+ break;
+ case WINDOW_POSITION_AT_TOP_LEFT: {
+ mMagnificationFrameOffsetRatio.set(-1f, -1f);
+ }
+ break;
+ }
+ }
+
@GuardedBy("mLock")
boolean disableWindowMagnificationInternal(
@Nullable MagnificationAnimationCallback animationResultCallback) {
@@ -768,9 +850,15 @@
}
private boolean enableWindowMagnificationInternal(int displayId, float scale, float centerX,
- float centerY, MagnificationAnimationCallback animationCallback) {
- return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification(
- displayId, scale, centerX, centerY, animationCallback);
+ float centerY, float magnificationFrameOffsetRatioX,
+ float magnificationFrameOffsetRatioY,
+ MagnificationAnimationCallback animationCallback) {
+ synchronized (mLock) {
+ return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification(
+ displayId, scale, centerX, centerY,
+ magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
+ animationCallback);
+ }
}
private boolean setScaleInternal(int displayId, float scale) {
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 6ac015b..f3fad84 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -18,6 +18,7 @@
import android.annotation.AppIdInt;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -108,7 +109,7 @@
// Please note the numbers should be continuous.
public static final int LAST_KNOWN_PACKAGE = PACKAGE_RECENTS;
- @IntDef(flag = true, prefix = "RESOLVE_", value = {
+ @LongDef(flag = true, prefix = "RESOLVE_", value = {
RESOLVE_NON_BROWSER_ONLY,
RESOLVE_NON_RESOLVER_ONLY
})
@@ -197,7 +198,7 @@
* @see PackageManager#getPackageInfo(String, int)
*/
public abstract PackageInfo getPackageInfo(String packageName,
- @PackageInfoFlags int flags, int filterCallingUid, int userId);
+ @PackageInfoFlags long flags, int filterCallingUid, int userId);
/**
* Retrieve CE data directory inode number of an application.
@@ -226,7 +227,7 @@
* deleted with {@code DELETE_KEEP_DATA} flag set).
*/
public abstract List<ApplicationInfo> getInstalledApplications(
- @ApplicationInfoFlags int flags, @UserIdInt int userId, int callingUid);
+ @ApplicationInfoFlags long flags, @UserIdInt int userId, int callingUid);
/**
* Retrieve launcher extras for a suspended package provided to the system in
@@ -323,7 +324,7 @@
* @see PackageManager#getPackageUidAsUser(String, int, int)
* @return The app's uid, or < 0 if the package was not found in that user
*/
- public abstract int getPackageUid(String packageName, @PackageInfoFlags int flags, int userId);
+ public abstract int getPackageUid(String packageName, @PackageInfoFlags long flags, int userId);
/**
* Retrieve all of the information we know about a particular package/application.
@@ -332,7 +333,7 @@
* @see PackageManager#getApplicationInfo(String, int)
*/
public abstract ApplicationInfo getApplicationInfo(String packageName,
- @ApplicationInfoFlags int flags, int filterCallingUid, int userId);
+ @ApplicationInfoFlags long flags, int filterCallingUid, int userId);
/**
* Retrieve all of the information we know about a particular activity class.
@@ -341,7 +342,7 @@
* @see PackageManager#getActivityInfo(ComponentName, int)
*/
public abstract ActivityInfo getActivityInfo(ComponentName component,
- @ComponentInfoFlags int flags, int filterCallingUid, int userId);
+ @ComponentInfoFlags long flags, int filterCallingUid, int userId);
/**
* Retrieve all activities that can be performed for the given intent.
@@ -352,7 +353,7 @@
* @see PackageManager#queryIntentActivities(Intent, int)
*/
public abstract List<ResolveInfo> queryIntentActivities(
- Intent intent, @Nullable String resolvedType, @ResolveInfoFlags int flags,
+ Intent intent, @Nullable String resolvedType, @ResolveInfoFlags long flags,
int filterCallingUid, int userId);
@@ -360,14 +361,14 @@
* Retrieve all receivers that can handle a broadcast of the given intent.
*/
public abstract List<ResolveInfo> queryIntentReceivers(Intent intent,
- String resolvedType, int flags, int filterCallingUid, int userId);
+ String resolvedType, @ResolveInfoFlags long flags, int filterCallingUid, int userId);
/**
* Retrieve all services that can be performed for the given intent.
* @see PackageManager#queryIntentServices(Intent, int)
*/
public abstract List<ResolveInfo> queryIntentServices(
- Intent intent, int flags, int callingUid, int userId);
+ Intent intent, @ResolveInfoFlags long flags, int callingUid, int userId);
/**
* Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
@@ -591,20 +592,20 @@
* Resolves an activity intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, @PrivateResolveFlags int privateResolveFlags, int userId,
+ @ResolveInfoFlags long flags, @PrivateResolveFlags long privateResolveFlags, int userId,
boolean resolveForStart, int filterCallingUid);
/**
* Resolves a service intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveService(Intent intent, String resolvedType,
- int flags, int userId, int callingUid);
+ @ResolveInfoFlags long flags, int userId, int callingUid);
/**
* Resolves a content provider intent.
*/
- public abstract ProviderInfo resolveContentProvider(String name, int flags, int userId,
- int callingUid);
+ public abstract ProviderInfo resolveContentProvider(String name, @ComponentInfoFlags long flags,
+ int userId, int callingUid);
/**
* Track the creator of a new isolated uid.
@@ -875,8 +876,8 @@
throws IOException;
/** Returns {@code true} if the specified component is enabled and matches the given flags. */
- public abstract boolean isEnabledAndMatches(@NonNull ParsedMainComponent component, int flags,
- int userId);
+ public abstract boolean isEnabledAndMatches(@NonNull ParsedMainComponent component,
+ @ComponentInfoFlags long flags, int userId);
/** Returns {@code true} if the given user requires extra badging for icons. */
public abstract boolean userNeedsBadging(int userId);
@@ -1024,7 +1025,7 @@
* @param flags flags about the uninstall.
*/
public abstract void uninstallApex(String packageName, long versionCode, int userId,
- IntentSender intentSender, int flags);
+ IntentSender intentSender, @PackageManager.InstallFlags int installFlags);
/**
* Update fingerprint of build that updated the runtime permissions for a user.
@@ -1260,5 +1261,5 @@
/**
* Reconcile all app data for the given user.
*/
- public abstract void reconcileAppsData(int userId, int flags, boolean migrateAppsData);
+ public abstract void reconcileAppsData(int userId, int storageFlags, boolean migrateAppsData);
}
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 7b5f2cd..259dd8ec 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -53,7 +53,7 @@
mHandler.sendEmptyMessage(DISABLE_BUTTONS);
mHandler.sendMessageDelayed(mHandler.obtainMessage(ENABLE_BUTTONS), 1000);
getContext().registerReceiver(mReceiver,
- new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), Context.RECEIVER_EXPORTED);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 61b8ded..7341e74 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -251,7 +251,7 @@
"Successful background authentication!");
}
- mAlreadyDone = true;
+ markAlreadyDone();
if (mTaskStackListener != null) {
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
@@ -327,7 +327,7 @@
final @LockoutTracker.LockoutMode int lockoutMode =
handleFailedAttempt(getTargetUserId());
if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
- mAlreadyDone = true;
+ markAlreadyDone();
}
final CoexCoordinator coordinator = CoexCoordinator.getInstance();
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 9764a16..b73e911 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -114,7 +114,7 @@
// Currently only used for authentication client. The cookie generated by BiometricService
// is never 0.
private final int mCookie;
- boolean mAlreadyDone;
+ private boolean mAlreadyDone = false;
// Use an empty callback by default since delayed operations can receive events
// before they are started and cause NPE in subclasses that access this field directly.
@@ -202,11 +202,9 @@
return callback;
}
- public boolean isAlreadyDone() {
- return mAlreadyDone;
- }
-
- public void destroy() {
+ /** Signals this operation has completed its lifecycle and should no longer be used. */
+ void destroy() {
+ mAlreadyDone = true;
if (mToken != null) {
try {
mToken.unlinkToDeath(this, 0);
@@ -218,6 +216,20 @@
}
}
+ /**
+ * Call while the operation is still active, but nearly done, to prevent any action
+ * upon client death (only needed for authentication clients).
+ */
+ void markAlreadyDone() {
+ Slog.d(TAG, "marking operation as done: " + this);
+ mAlreadyDone = true;
+ }
+
+ /** If this operation has been marked as completely done (or cancelled). */
+ public boolean isAlreadyDone() {
+ return mAlreadyDone;
+ }
+
@Override
public void binderDied() {
binderDiedInternal(true /* clearListener */);
@@ -225,10 +237,9 @@
// TODO(b/157790417): Move this to the scheduler
void binderDiedInternal(boolean clearListener) {
- Slog.e(TAG, "Binder died, owner: " + getOwnerString()
- + ", operation: " + this.getClass().getName());
+ Slog.e(TAG, "Binder died, operation: " + this);
- if (isAlreadyDone()) {
+ if (mAlreadyDone) {
Slog.w(TAG, "Binder died but client is finished, ignoring");
return;
}
@@ -299,7 +310,7 @@
@Override
public String toString() {
return "{[" + mSequentialId + "] "
- + this.getClass().getSimpleName()
+ + this.getClass().getName()
+ ", proto=" + getProtoEnum()
+ ", owner=" + getOwnerString()
+ ", cookie=" + getCookie()
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 361ec40..a358bc2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -605,6 +605,9 @@
if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) {
Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation);
// We can set it to null immediately, since the HAL was never notified to start.
+ if (mCurrentOperation != null) {
+ mCurrentOperation.mClientMonitor.destroy();
+ }
mCurrentOperation = null;
startNextOperationIfIdle();
return;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 1c62699..a36a1a91 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1120,50 +1120,211 @@
}
}
- private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
+ private boolean validatePackageName(int uid, String packageName) {
+ if (packageName != null) {
+ String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+ if (packageNames != null) {
+ for (String n : packageNames) {
+ if (n.equals(packageName)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean canProjectVideo(IMediaProjection projection) {
+ if (projection != null) {
+ try {
+ if (projection.canProjectVideo()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to query projection service for permissions", e);
+ }
+ }
+ if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
+ return true;
+ }
+ return canProjectSecureVideo(projection);
+ }
+
+ private boolean canProjectSecureVideo(IMediaProjection projection) {
+ if (projection != null) {
+ try {
+ if (projection.canProjectSecureVideo()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to query projection service for permissions", e);
+ }
+ }
+ return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
+ }
+
+ private boolean checkCallingPermission(String permission, String func) {
+ if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid() + " requires " + permission;
+ Slog.w(TAG, msg);
+ return false;
+ }
+
+ private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig,
+ IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+ DisplayWindowPolicyController controller) {
+ final int callingUid = Binder.getCallingUid();
+ if (!validatePackageName(callingUid, packageName)) {
+ throw new SecurityException("packageName must match the calling uid");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("appToken must not be null");
+ }
+ if (virtualDisplayConfig == null) {
+ throw new IllegalArgumentException("virtualDisplayConfig must not be null");
+ }
+ final Surface surface = virtualDisplayConfig.getSurface();
+ int flags = virtualDisplayConfig.getFlags();
+
+ if (surface != null && surface.isSingleBuffered()) {
+ throw new IllegalArgumentException("Surface can't be single-buffered");
+ }
+
+ if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+ flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+
+ // Public displays can't be allowed to show content when locked.
+ if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+ throw new IllegalArgumentException(
+ "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
+ }
+ }
+ if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
+ flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+ }
+ if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+ flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
+ }
+
+ if (projection != null) {
+ try {
+ if (!getProjectionService().isValidMediaProjection(projection)) {
+ throw new SecurityException("Invalid media projection");
+ }
+ flags = projection.applyVirtualDisplayFlags(flags);
+ } catch (RemoteException e) {
+ throw new SecurityException("unable to validate media projection or flags");
+ }
+ }
+
+ if (callingUid != Process.SYSTEM_UID
+ && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+ if (!canProjectVideo(projection)) {
+ throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
+ + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
+ + "MediaProjection token in order to create a screen sharing virtual "
+ + "display.");
+ }
+ }
+ if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
+ if (!canProjectSecureVideo(projection)) {
+ throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
+ + "or an appropriate MediaProjection token to create a "
+ + "secure virtual display.");
+ }
+ }
+
+ if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
+ if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+ EventLog.writeEvent(0x534e4554, "162627132", callingUid,
+ "Attempt to create a trusted display without holding permission!");
+ throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ + "create a trusted virtual display.");
+ }
+ }
+
+ if (callingUid != Process.SYSTEM_UID
+ && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
+ if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+ throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ + "create a virtual display which is not in the default DisplayGroup.");
+ }
+ }
+
+ if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
+ flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
+ }
+
+ // Sometimes users can have sensitive information in system decoration windows. An app
+ // could create a virtual display with system decorations support and read the user info
+ // from the surface.
+ // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ // to trusted virtual displays.
+ final int trustedDisplayWithSysDecorFlag =
+ (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ | VIRTUAL_DISPLAY_FLAG_TRUSTED);
+ if ((flags & trustedDisplayWithSysDecorFlag)
+ == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
+ throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ return createVirtualDisplayLocked(callback, projection, callingUid, packageName,
+ surface, flags, virtualDisplayConfig, controller);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private int createVirtualDisplayLocked(IVirtualDisplayCallback callback,
IMediaProjection projection, int callingUid, String packageName, Surface surface,
int flags, VirtualDisplayConfig virtualDisplayConfig,
DisplayWindowPolicyController controller) {
- synchronized (mSyncRoot) {
- if (mVirtualDisplayAdapter == null) {
- Slog.w(TAG, "Rejecting request to create private virtual display "
- + "because the virtual display adapter is not available.");
- return -1;
- }
-
- DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
- callback, projection, callingUid, packageName, surface, flags,
- virtualDisplayConfig);
- if (device == null) {
- return -1;
- }
-
- // DisplayDevice events are handled manually for Virtual Displays.
- // TODO: multi-display Fix this so that generic add/remove events are not handled in a
- // different code path for virtual displays. Currently this happens so that we can
- // return a valid display ID synchronously upon successful Virtual Display creation.
- // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
- // called on the DisplayThread (which we don't want to wait for?).
- // One option would be to actually wait here on the binder thread
- // to be notified when the virtual display is created (or failed).
- mDisplayDeviceRepo.onDisplayDeviceEvent(device,
- DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
-
- final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
- if (display != null) {
- if (controller != null) {
- mDisplayWindowPolicyController.put(display.getDisplayIdLocked(), controller);
- }
- return display.getDisplayIdLocked();
- }
-
- // Something weird happened and the logical display was not created.
- Slog.w(TAG, "Rejecting request to create virtual display "
- + "because the logical display was not created.");
- mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
- mDisplayDeviceRepo.onDisplayDeviceEvent(device,
- DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
+ if (mVirtualDisplayAdapter == null) {
+ Slog.w(TAG, "Rejecting request to create private virtual display "
+ + "because the virtual display adapter is not available.");
+ return -1;
}
+
+ DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
+ callback, projection, callingUid, packageName, surface, flags,
+ virtualDisplayConfig);
+ if (device == null) {
+ return -1;
+ }
+
+ // DisplayDevice events are handled manually for Virtual Displays.
+ // TODO: multi-display Fix this so that generic add/remove events are not handled in a
+ // different code path for virtual displays. Currently this happens so that we can
+ // return a valid display ID synchronously upon successful Virtual Display creation.
+ // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
+ // called on the DisplayThread (which we don't want to wait for?).
+ // One option would be to actually wait here on the binder thread
+ // to be notified when the virtual display is created (or failed).
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device,
+ DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
+
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
+ if (display != null) {
+ if (controller != null) {
+ mDisplayWindowPolicyController.put(display.getDisplayIdLocked(), controller);
+ }
+ return display.getDisplayIdLocked();
+ }
+
+ // Something weird happened and the logical display was not created.
+ Slog.w(TAG, "Rejecting request to create virtual display "
+ + "because the logical display was not created.");
+ mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device,
+ DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
return -1;
}
@@ -2726,116 +2887,8 @@
@Override // Binder call
public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
- return createVirtualDisplay(virtualDisplayConfig, callback, projection, packageName,
- null /* controller */);
- }
-
- public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
- IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
- DisplayWindowPolicyController controller) {
- final int callingUid = Binder.getCallingUid();
- if (!validatePackageName(callingUid, packageName)) {
- throw new SecurityException("packageName must match the calling uid");
- }
- if (callback == null) {
- throw new IllegalArgumentException("appToken must not be null");
- }
- if (virtualDisplayConfig == null) {
- throw new IllegalArgumentException("virtualDisplayConfig must not be null");
- }
- final Surface surface = virtualDisplayConfig.getSurface();
- int flags = virtualDisplayConfig.getFlags();
-
- if (surface != null && surface.isSingleBuffered()) {
- throw new IllegalArgumentException("Surface can't be single-buffered");
- }
-
- if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
- flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
-
- // Public displays can't be allowed to show content when locked.
- if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
- throw new IllegalArgumentException(
- "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
- }
- }
- if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
- flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
- }
- if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
- flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
- }
-
- if (projection != null) {
- try {
- if (!getProjectionService().isValidMediaProjection(projection)) {
- throw new SecurityException("Invalid media projection");
- }
- flags = projection.applyVirtualDisplayFlags(flags);
- } catch (RemoteException e) {
- throw new SecurityException("unable to validate media projection or flags");
- }
- }
-
- if (callingUid != Process.SYSTEM_UID &&
- (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
- if (!canProjectVideo(projection)) {
- throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
- + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
- + "MediaProjection token in order to create a screen sharing virtual "
- + "display.");
- }
- }
- if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
- if (!canProjectSecureVideo(projection)) {
- throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
- + "or an appropriate MediaProjection token to create a "
- + "secure virtual display.");
- }
- }
-
- if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
- if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
- EventLog.writeEvent(0x534e4554, "162627132", callingUid,
- "Attempt to create a trusted display without holding permission!");
- throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
- + "create a trusted virtual display.");
- }
- }
-
- if (callingUid != Process.SYSTEM_UID
- && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
- if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
- throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
- + "create a virtual display which is not in the default DisplayGroup.");
- }
- }
-
- if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
- flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
- }
-
- // Sometimes users can have sensitive information in system decoration windows. An app
- // could create a virtual display with system decorations support and read the user info
- // from the surface.
- // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
- // to trusted virtual displays.
- final int trustedDisplayWithSysDecorFlag =
- (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
- | VIRTUAL_DISPLAY_FLAG_TRUSTED);
- if ((flags & trustedDisplayWithSysDecorFlag)
- == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
- && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
- throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
- }
-
- final long token = Binder.clearCallingIdentity();
- try {
- return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
- surface, flags, virtualDisplayConfig, controller);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
+ packageName, null /* controller */);
}
@Override // Binder call
@@ -3265,60 +3318,6 @@
Binder.restoreCallingIdentity(token);
}
}
-
- private boolean validatePackageName(int uid, String packageName) {
- if (packageName != null) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
- if (packageNames != null) {
- for (String n : packageNames) {
- if (n.equals(packageName)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- private boolean canProjectVideo(IMediaProjection projection) {
- if (projection != null) {
- try {
- if (projection.canProjectVideo()) {
- return true;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to query projection service for permissions", e);
- }
- }
- if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
- return true;
- }
- return canProjectSecureVideo(projection);
- }
-
- private boolean canProjectSecureVideo(IMediaProjection projection) {
- if (projection != null) {
- try {
- if (projection.canProjectSecureVideo()){
- return true;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to query projection service for permissions", e);
- }
- }
- return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
- }
-
- private boolean checkCallingPermission(String permission, String func) {
- if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid() + " requires " + permission;
- Slog.w(TAG, msg);
- return false;
- }
-
}
private static boolean isValidBrightness(float brightness) {
@@ -3655,6 +3654,14 @@
}
@Override
+ public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+ IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+ DisplayWindowPolicyController controller) {
+ return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
+ packageName, controller);
+ }
+
+ @Override
public DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId) {
synchronized (mSyncRoot) {
return mDisplayWindowPolicyController.get(displayId);
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 8460d67..1781588 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -52,8 +52,6 @@
private class GnssMeasurementListenerRegistration extends GnssListenerRegistration {
- private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement";
-
protected GnssMeasurementListenerRegistration(
@Nullable GnssMeasurementRequest request,
CallerIdentity callerIdentity,
@@ -70,15 +68,13 @@
@Nullable
@Override
protected void onActive() {
- mLocationAttributionHelper.reportHighPowerLocationStart(
- getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
+ mLocationAttributionHelper.reportHighPowerLocationStart(getIdentity());
}
@Nullable
@Override
protected void onInactive() {
- mLocationAttributionHelper.reportHighPowerLocationStop(
- getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
+ mLocationAttributionHelper.reportHighPowerLocationStop(getIdentity());
}
}
diff --git a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
index 5cb360b..4838752 100644
--- a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
+++ b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
@@ -24,55 +24,23 @@
import android.location.util.identity.CallerIdentity;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
/**
* Helps manage appop monitoring for multiple location clients.
*/
public class LocationAttributionHelper {
- private static class BucketKey {
- private final String mBucket;
- private final Object mKey;
-
- private BucketKey(String bucket, Object key) {
- mBucket = Objects.requireNonNull(bucket);
- mKey = Objects.requireNonNull(key);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- BucketKey that = (BucketKey) o;
- return mBucket.equals(that.mBucket)
- && mKey.equals(that.mKey);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mBucket, mKey);
- }
- }
-
private final AppOpsHelper mAppOpsHelper;
@GuardedBy("this")
- private final Map<CallerIdentity, Set<BucketKey>> mAttributions;
+ private final Map<CallerIdentity, Integer> mAttributions;
@GuardedBy("this")
- private final Map<CallerIdentity, Set<BucketKey>> mHighPowerAttributions;
+ private final Map<CallerIdentity, Integer> mHighPowerAttributions;
public LocationAttributionHelper(AppOpsHelper appOpsHelper) {
mAppOpsHelper = appOpsHelper;
@@ -84,15 +52,16 @@
/**
* Report normal location usage for the given caller in the given bucket, with a unique key.
*/
- public synchronized void reportLocationStart(CallerIdentity identity, String bucket,
- Object key) {
- Set<BucketKey> keySet = mAttributions.computeIfAbsent(identity,
- i -> new ArraySet<>());
- boolean empty = keySet.isEmpty();
- if (keySet.add(new BucketKey(bucket, key)) && empty) {
- if (!mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) {
- mAttributions.remove(identity);
+ public synchronized void reportLocationStart(CallerIdentity identity) {
+ identity = CallerIdentity.forAggregation(identity);
+
+ int count = mAttributions.getOrDefault(identity, 0);
+ if (count == 0) {
+ if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) {
+ mAttributions.put(identity, 1);
}
+ } else {
+ mAttributions.put(identity, count + 1);
}
}
@@ -100,13 +69,15 @@
* Report normal location usage has stopped for the given caller in the given bucket, with a
* unique key.
*/
- public synchronized void reportLocationStop(CallerIdentity identity, String bucket,
- Object key) {
- Set<BucketKey> keySet = mAttributions.get(identity);
- if (keySet != null && keySet.remove(new BucketKey(bucket, key))
- && keySet.isEmpty()) {
+ public synchronized void reportLocationStop(CallerIdentity identity) {
+ identity = CallerIdentity.forAggregation(identity);
+
+ int count = mAttributions.getOrDefault(identity, 0);
+ if (count == 1) {
mAttributions.remove(identity);
mAppOpsHelper.finishOp(OP_MONITOR_LOCATION, identity);
+ } else if (count > 1) {
+ mAttributions.put(identity, count - 1);
}
}
@@ -114,19 +85,19 @@
* Report high power location usage for the given caller in the given bucket, with a unique
* key.
*/
- public synchronized void reportHighPowerLocationStart(CallerIdentity identity, String bucket,
- Object key) {
- Set<BucketKey> keySet = mHighPowerAttributions.computeIfAbsent(identity,
- i -> new ArraySet<>());
- boolean empty = keySet.isEmpty();
- if (keySet.add(new BucketKey(bucket, key)) && empty) {
- if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) {
- if (D) {
- Log.v(TAG, "starting high power location attribution for " + identity);
- }
- } else {
- mHighPowerAttributions.remove(identity);
+ public synchronized void reportHighPowerLocationStart(CallerIdentity identity) {
+ identity = CallerIdentity.forAggregation(identity);
+
+ int count = mHighPowerAttributions.getOrDefault(identity, 0);
+ if (count == 0) {
+ if (D) {
+ Log.v(TAG, "starting high power location attribution for " + identity);
}
+ if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) {
+ mHighPowerAttributions.put(identity, 1);
+ }
+ } else {
+ mHighPowerAttributions.put(identity, count + 1);
}
}
@@ -134,16 +105,18 @@
* Report high power location usage has stopped for the given caller in the given bucket,
* with a unique key.
*/
- public synchronized void reportHighPowerLocationStop(CallerIdentity identity, String bucket,
- Object key) {
- Set<BucketKey> keySet = mHighPowerAttributions.get(identity);
- if (keySet != null && keySet.remove(new BucketKey(bucket, key))
- && keySet.isEmpty()) {
+ public synchronized void reportHighPowerLocationStop(CallerIdentity identity) {
+ identity = CallerIdentity.forAggregation(identity);
+
+ int count = mHighPowerAttributions.getOrDefault(identity, 0);
+ if (count == 1) {
if (D) {
Log.v(TAG, "stopping high power location attribution for " + identity);
}
mHighPowerAttributions.remove(identity);
mAppOpsHelper.finishOp(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+ } else if (count > 1) {
+ mHighPowerAttributions.put(identity, count - 1);
}
}
}
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 17efeb3..0ce24dd 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -398,7 +398,7 @@
EVENT_LOG.logProviderClientActive(mName, getIdentity());
if (!getRequest().isHiddenFromAppOps()) {
- mLocationAttributionHelper.reportLocationStart(getIdentity(), getName(), getKey());
+ mLocationAttributionHelper.reportLocationStart(getIdentity());
}
onHighPowerUsageChanged();
@@ -413,7 +413,7 @@
onHighPowerUsageChanged();
if (!getRequest().isHiddenFromAppOps()) {
- mLocationAttributionHelper.reportLocationStop(getIdentity(), getName(), getKey());
+ mLocationAttributionHelper.reportLocationStop(getIdentity());
}
onProviderListenerInactive();
@@ -488,10 +488,10 @@
if (!getRequest().isHiddenFromAppOps()) {
if (mIsUsingHighPower) {
mLocationAttributionHelper.reportHighPowerLocationStart(
- getIdentity(), getName(), getKey());
+ getIdentity());
} else {
mLocationAttributionHelper.reportHighPowerLocationStop(
- getIdentity(), getName(), getKey());
+ getIdentity());
}
}
}
diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java
index 5199ef6..be5f219 100644
--- a/services/core/java/com/android/server/notification/VibratorHelper.java
+++ b/services/core/java/com/android/server/notification/VibratorHelper.java
@@ -89,7 +89,7 @@
*/
public void vibrate(VibrationEffect effect, AudioAttributes attrs, String reason) {
mVibrator.vibrate(Process.SYSTEM_UID, PackageManagerService.PLATFORM_PACKAGE_NAME,
- effect, reason, new VibrationAttributes.Builder(attrs, effect).build());
+ effect, reason, new VibrationAttributes.Builder(attrs).build());
}
/** Stop all notification vibrations (ringtone, alarm, notification usages). */
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index dca8654..6ec3405 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -318,7 +318,7 @@
}
@Nullable
- List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryActivities(Intent intent, String resolvedType, long flags,
int userId) {
synchronized (mLock) {
return mActivities.queryIntent(intent, resolvedType, flags, userId);
@@ -326,7 +326,7 @@
}
@Nullable
- List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryActivities(Intent intent, String resolvedType, long flags,
List<ParsedActivity> activities, int userId) {
synchronized (mLock) {
return mActivities.queryIntentForPackage(
@@ -335,14 +335,14 @@
}
@Nullable
- List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> queryProviders(Intent intent, String resolvedType, long flags, int userId) {
synchronized (mLock) {
return mProviders.queryIntent(intent, resolvedType, flags, userId);
}
}
@Nullable
- List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryProviders(Intent intent, String resolvedType, long flags,
List<ParsedProvider> providers, int userId) {
synchronized (mLock) {
return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId);
@@ -350,7 +350,7 @@
}
@Nullable
- List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
+ List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, long flags,
int userId) {
if (!sUserManager.exists(userId)) {
return null;
@@ -409,7 +409,7 @@
}
@Nullable
- ProviderInfo queryProvider(String authority, int flags, int userId) {
+ ProviderInfo queryProvider(String authority, long flags, int userId) {
synchronized (mLock) {
final ParsedProvider p = mProvidersByAuthority.get(authority);
if (p == null) {
@@ -480,14 +480,14 @@
}
@Nullable
- List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, long flags, int userId) {
synchronized (mLock) {
return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
}
@Nullable
- List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, long flags,
List<ParsedActivity> receivers, int userId) {
synchronized (mLock) {
return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId);
@@ -495,14 +495,14 @@
}
@Nullable
- List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> queryServices(Intent intent, String resolvedType, long flags, int userId) {
synchronized (mLock) {
return mServices.queryIntent(intent, resolvedType, flags, userId);
}
}
@Nullable
- List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryServices(Intent intent, String resolvedType, long flags,
List<ParsedService> services, int userId) {
synchronized (mLock) {
return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId);
@@ -1380,7 +1380,7 @@
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
int userId) {
if (!sUserManager.exists(userId)) {
return null;
@@ -1392,7 +1392,7 @@
}
List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, List<ParsedActivity> packageActivities, int userId) {
+ long flags, List<ParsedActivity> packageActivities, int userId) {
if (!sUserManager.exists(userId)) {
return null;
}
@@ -1669,7 +1669,7 @@
// ActivityIntentResolver.
protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
new ArrayMap<>();
- private int mFlags;
+ private long mFlags;
}
// Both receivers and activities share a class, but point to different get methods
@@ -1711,7 +1711,7 @@
}
@Nullable
- List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
int userId) {
if (!sUserManager.exists(userId)) {
return null;
@@ -1724,7 +1724,7 @@
@Nullable
List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, List<ParsedProvider> packageProviders, int userId) {
+ long flags, List<ParsedProvider> packageProviders, int userId) {
if (!sUserManager.exists(userId)) {
return null;
}
@@ -1946,7 +1946,7 @@
}
private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
- private int mFlags;
+ private long mFlags;
}
private static final class ServiceIntentResolver
@@ -1969,7 +1969,7 @@
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
int userId) {
if (!sUserManager.exists(userId)) return null;
mFlags = flags;
@@ -1979,7 +1979,7 @@
}
List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, List<ParsedService> packageServices, int userId) {
+ long flags, List<ParsedService> packageServices, int userId) {
if (!sUserManager.exists(userId)) return null;
if (packageServices == null) {
return Collections.emptyList();
@@ -2190,7 +2190,7 @@
// Keys are String (activity class name), values are Activity.
private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
- private int mFlags;
+ private long mFlags;
}
static final class InstantAppIntentResolver
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index a9df4ba..3e849f8 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -133,35 +133,36 @@
}
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType,
- int flags, @PackageManagerInternal.PrivateResolveFlags int privateResolveFlags,
+ @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,
int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType,
- int flags, int userId);
+ long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent, String resolvedType,
- int flags, int userId, int callingUid, boolean includeInstantApps);
+ long flags, int userId, int callingUid, boolean includeInstantApps);
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
@NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(Intent intent,
- String resolvedType, int flags, int filterCallingUid, int userId,
+ String resolvedType, long flags, int filterCallingUid, int userId,
boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
String instantAppPkgName);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ActivityInfo getActivityInfo(ComponentName component, int flags, int userId);
+ ActivityInfo getActivityInfo(ComponentName component, long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
+ ActivityInfo getActivityInfoInternal(ComponentName component, long flags,
int filterCallingUid, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
AndroidPackage getPackage(String packageName);
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
AndroidPackage getPackage(int uid);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ApplicationInfo generateApplicationInfoFromSettings(String packageName, int flags,
+ ApplicationInfo generateApplicationInfoFromSettings(String packageName, long flags,
int filterCallingUid, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ApplicationInfo getApplicationInfo(String packageName, int flags, int userId);
+ ApplicationInfo getApplicationInfo(String packageName, long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+ ApplicationInfo getApplicationInfoInternal(String packageName, long flags,
int filterCallingUid, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
ComponentName getDefaultHomeActivity(int userId);
@@ -169,7 +170,7 @@
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent, String resolvedType,
- int flags, int sourceUserId, int parentUserId);
+ long flags, int sourceUserId, int parentUserId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
Intent getHomeIntent();
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@@ -180,11 +181,11 @@
String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
boolean resolveForStart, int userId, Intent intent);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- PackageInfo generatePackageInfo(PackageStateInternal ps, int flags, int userId);
+ PackageInfo generatePackageInfo(PackageStateInternal ps, long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- PackageInfo getPackageInfo(String packageName, int flags, int userId);
+ PackageInfo getPackageInfo(String packageName, long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- PackageInfo getPackageInfoInternal(String packageName, long versionCode, int flags,
+ PackageInfo getPackageInfoInternal(String packageName, long versionCode, long flags,
int filterCallingUid, int userId);
/**
@@ -202,12 +203,12 @@
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
@Nullable PackageState getPackageStateCopied(@NonNull String packageName);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId);
+ ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter,
int sourceUserId, int targetUserId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ServiceInfo getServiceInfo(ComponentName component, int flags, int userId);
+ ServiceInfo getServiceInfo(ComponentName component, long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
SharedLibraryInfo getSharedLibraryInfo(String name, long version);
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
@@ -224,7 +225,7 @@
boolean canViewInstantApps(int callingUid, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid, int userId,
- int flags);
+ long flags);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
boolean isCallerSameApp(String packageName, int uid);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@@ -234,7 +235,7 @@
@PackageManager.ComponentType int type);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId,
- String resolvedType, int flags);
+ String resolvedType, long flags);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
boolean isInstantApp(String packageName, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
@@ -254,18 +255,18 @@
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
int checkUidPermission(String permName, int uid);
@Computer.LiveImplementation(override = Computer.LiveImplementation.MANDATORY)
- int getPackageUidInternal(String packageName, int flags, int userId, int callingUid);
+ int getPackageUidInternal(String packageName, long flags, int userId, int callingUid);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- int updateFlagsForApplication(int flags, int userId);
+ long updateFlagsForApplication(long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- int updateFlagsForComponent(int flags, int userId);
+ long updateFlagsForComponent(long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- int updateFlagsForPackage(int flags, int userId);
+ long updateFlagsForPackage(long flags, int userId);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- int updateFlagsForResolve(int flags, int userId, int callingUid, boolean wantInstantApps,
+ long updateFlagsForResolve(long flags, int userId, int callingUid, boolean wantInstantApps,
boolean isImplicitImageCaptureIntentAndNotSetByDpc);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- int updateFlagsForResolve(int flags, int userId, int callingUid, boolean wantInstantApps,
+ long updateFlagsForResolve(long flags, int userId, int callingUid, boolean wantInstantApps,
boolean onlyExposedExplicitly, boolean isImplicitImageCaptureIntentAndNotSetByDpc);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId,
@@ -291,10 +292,10 @@
void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal(
- Intent intent, String resolvedType, int flags, List<ResolveInfo> query, boolean always,
+ Intent intent, String resolvedType, long flags, List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered);
@Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
- ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, int flags,
+ ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, long flags,
List<ResolveInfo> query, boolean debug, int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@@ -337,7 +338,8 @@
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@NonNull
- int[] getPackageGids(@NonNull String packageName, int flags, @UserIdInt int userId);
+ int[] getPackageGids(@NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
int getTargetSdkVersion(@NonNull String packageName);
@@ -348,13 +350,13 @@
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
- ActivityInfo getReceiverInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId);
+ ActivityInfo getReceiverInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName,
- int flags, @UserIdInt int userId);
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
boolean canRequestPackageInstalls(@NonNull String packageName, int callingUid,
@@ -367,17 +369,18 @@
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
- int flags, int callingUid, @UserIdInt int userId);
+ @PackageManager.PackageInfoFlags long flags, int callingUid, @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
- @NonNull String packageName, int flags, @UserIdInt int userId);
+ @NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
- ProviderInfo getProviderInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId);
+ ProviderInfo getProviderInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
@@ -436,17 +439,17 @@
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@NonNull
ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(@NonNull String[] permissions,
- int flags, @UserIdInt int userId);
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@NonNull
- List<ApplicationInfo> getInstalledApplications(int flags, @UserIdInt int userId,
- int callingUid);
+ List<ApplicationInfo> getInstalledApplications(@PackageManager.ApplicationInfoFlags long flags,
+ @UserIdInt int userId, int callingUid);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
- ProviderInfo resolveContentProvider(@NonNull String name, int flags,
- @UserIdInt int userId, int callingUid);
+ ProviderInfo resolveContentProvider(@NonNull String name,
+ @PackageManager.ResolveInfoFlags long flags, @UserIdInt int userId, int callingUid);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
@@ -460,7 +463,7 @@
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@NonNull
ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName, int uid,
- int flags, @Nullable String metaDataKey);
+ @PackageManager.ComponentInfoFlags long flags, @Nullable String metaDataKey);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
@Nullable
@@ -557,7 +560,8 @@
boolean canQueryPackage(int callingUid, @Nullable String targetPackageName);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
- int getPackageUid(@NonNull String packageName, int flags, @UserIdInt int userId);
+ int getPackageUid(@NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId);
@Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
boolean canAccessComponent(int callingUid, @NonNull ComponentName component,
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 887dfff..2d61773 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -125,7 +125,6 @@
import android.util.TypedXmlSerializer;
import android.util.Xml;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -165,7 +164,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -215,7 +213,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public boolean isEnabledAndMatch(AndroidPackage pkg, ParsedMainComponent component,
- int flags, int userId) {
+ long flags, int userId) {
PackageStateInternal pkgState = getPackage(component.getPackageName());
if (pkgState == null) {
return false;
@@ -431,8 +429,8 @@
}
public final @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags,
- @PackageManagerInternal.PrivateResolveFlags int privateResolveFlags,
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,
int filterCallingUid, int userId, boolean resolveForStart,
boolean allowDynamicSplits) {
if (!mUserManager.exists(userId)) return Collections.emptyList();
@@ -543,15 +541,15 @@
}
public final @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
return queryIntentActivitiesInternal(
intent, resolvedType, flags, 0 /*privateResolveFlags*/, Binder.getCallingUid(),
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
public final @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- boolean includeInstantApps) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId,
+ int callingUid, boolean includeInstantApps) {
if (!mUserManager.exists(userId)) return Collections.emptyList();
enforceCrossUserOrProfilePermission(callingUid,
userId,
@@ -627,8 +625,8 @@
}
protected @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- String instantAppPkgName) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId,
+ int callingUid, String instantAppPkgName) {
// reader
String pkgName = intent.getPackage();
if (pkgName == null) {
@@ -655,9 +653,9 @@
}
public @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(
- Intent intent, String resolvedType, int flags, int filterCallingUid, int userId,
- boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
- String instantAppPkgName) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits,
+ String pkgName, String instantAppPkgName) {
// reader
boolean sortResult = false;
boolean addInstant = false;
@@ -787,7 +785,8 @@
return null;
}
- public final ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ public final ActivityInfo getActivityInfo(ComponentName component,
+ @PackageManager.ResolveInfoFlags long flags, int userId) {
return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
}
@@ -797,8 +796,8 @@
* to clearing. Because it can only be provided by trusted code, its value can be
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
- public final ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
- int filterCallingUid, int userId) {
+ public final ActivityInfo getActivityInfoInternal(ComponentName component,
+ @PackageManager.ResolveInfoFlags long flags, int filterCallingUid, int userId) {
if (!mUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId);
@@ -811,8 +810,8 @@
return getActivityInfoInternalBody(component, flags, filterCallingUid, userId);
}
- protected ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
- int filterCallingUid, int userId) {
+ protected ActivityInfo getActivityInfoInternalBody(ComponentName component,
+ @PackageManager.ResolveInfoFlags long flags, int filterCallingUid, int userId) {
ParsedActivity a = mComponentResolver.getActivity(component);
if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
@@ -852,7 +851,7 @@
}
public final ApplicationInfo generateApplicationInfoFromSettings(String packageName,
- int flags, int filterCallingUid, int userId) {
+ long flags, int filterCallingUid, int userId) {
if (!mUserManager.exists(userId)) return null;
PackageStateInternal ps = mSettings.getPackage(packageName);
if (ps != null) {
@@ -879,7 +878,8 @@
return null;
}
- public final ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+ public final ApplicationInfo getApplicationInfo(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags, int userId) {
return getApplicationInfoInternal(packageName, flags, Binder.getCallingUid(), userId);
}
@@ -889,7 +889,8 @@
* to clearing. Because it can only be provided by trusted code, its value can be
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
- public final ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+ public final ApplicationInfo getApplicationInfoInternal(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags,
int filterCallingUid, int userId) {
if (!mUserManager.exists(userId)) return null;
flags = updateFlagsForApplication(flags, userId);
@@ -903,7 +904,8 @@
return getApplicationInfoInternalBody(packageName, flags, filterCallingUid, userId);
}
- protected ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
+ protected ApplicationInfo getApplicationInfoInternalBody(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags,
int filterCallingUid, int userId) {
// writer
// Normalize package name to handle renamed packages and static libs
@@ -960,7 +962,7 @@
}
protected ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
- Intent intent, int matchFlags, List<ResolveInfo> candidates,
+ Intent intent, long matchFlags, List<ResolveInfo> candidates,
CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
final ArrayList<ResolveInfo> result = new ArrayList<>();
final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
@@ -1159,7 +1161,8 @@
}
public final CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
- String resolvedType, int flags, int sourceUserId, int parentUserId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int sourceUserId,
+ int parentUserId) {
if (!mUserManager.hasUserRestriction(UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
sourceUserId)) {
return null;
@@ -1380,7 +1383,7 @@
}
private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent,
- int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
+ long matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
int userId) {
final boolean debug = (intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0;
@@ -1423,9 +1426,8 @@
}
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
- Intent intent,
- String resolvedType, int flags, int userId, boolean resolveForStart,
- boolean isRequesterInstantApp) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
// first, check to see if we've got an instant app already installed
final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
ResolveInfo localInstantApp = null;
@@ -1529,7 +1531,8 @@
return result;
}
- public final PackageInfo generatePackageInfo(PackageStateInternal ps, int flags, int userId) {
+ public final PackageInfo generatePackageInfo(PackageStateInternal ps,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
if (!mUserManager.exists(userId)) return null;
if (ps == null) {
return null;
@@ -1603,7 +1606,8 @@
}
}
- public final PackageInfo getPackageInfo(String packageName, int flags, int userId) {
+ public final PackageInfo getPackageInfo(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
flags, Binder.getCallingUid(), userId);
}
@@ -1615,7 +1619,7 @@
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
public final PackageInfo getPackageInfoInternal(String packageName, long versionCode,
- int flags, int filterCallingUid, int userId) {
+ long flags, int filterCallingUid, int userId) {
if (!mUserManager.exists(userId)) return null;
flags = updateFlagsForPackage(flags, userId);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -1626,7 +1630,7 @@
}
protected PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
- int flags, int filterCallingUid, int userId) {
+ long flags, int filterCallingUid, int userId) {
// reader
// Normalize package name to handle renamed packages and static libs
packageName = resolveInternalPackageNameLPr(packageName, versionCode);
@@ -1711,7 +1715,7 @@
return pkgSetting == null ? null : PackageStateImpl.copy(pkgSetting);
}
- public final ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
+ public final ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId) {
final int callingUid = Binder.getCallingUid();
if (getInstantAppPackageName(callingUid) != null) {
return ParceledListSlice.emptyList();
@@ -1725,7 +1729,7 @@
return getInstalledPackagesBody(flags, userId, callingUid);
}
- protected ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
+ protected ParceledListSlice<PackageInfo> getInstalledPackagesBody(long flags, int userId,
int callingUid) {
// writer
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
@@ -1804,7 +1808,8 @@
@Nullable
private CrossProfileDomainInfo createForwardingResolveInfo(
@NonNull CrossProfileIntentFilter filter, @NonNull Intent intent,
- @Nullable String resolvedType, int flags, int sourceUserId) {
+ @Nullable String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int sourceUserId) {
int targetUserId = filter.getTargetUserId();
if (!isUserEnabled(targetUserId)) {
return null;
@@ -1891,7 +1896,7 @@
@Nullable
private CrossProfileDomainInfo queryCrossProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
- int flags, int sourceUserId, boolean matchInCurrentProfile) {
+ long flags, int sourceUserId, boolean matchInCurrentProfile) {
if (matchingFilters == null) {
return null;
}
@@ -1945,7 +1950,7 @@
private ResolveInfo querySkipCurrentProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
- int flags, int sourceUserId) {
+ long flags, int sourceUserId) {
if (matchingFilters != null) {
int size = matchingFilters.size();
for (int i = 0; i < size; i++) {
@@ -1964,7 +1969,8 @@
return null;
}
- public final ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+ public final ServiceInfo getServiceInfo(ComponentName component,
+ @PackageManager.ResolveInfoFlags long flags, int userId) {
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId);
@@ -1974,8 +1980,8 @@
return getServiceInfoBody(component, flags, userId, callingUid);
}
- protected ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
- int callingUid) {
+ protected ServiceInfo getServiceInfoBody(ComponentName component,
+ @PackageManager.ResolveInfoFlags long flags, int userId, int callingUid) {
ParsedService s = mComponentResolver.getService(component);
if (DEBUG_PACKAGE_INFO) {
Log.v(
@@ -2227,7 +2233,7 @@
}
public final boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
- int userId, int flags) {
+ int userId, @PackageManager.ComponentInfoFlags long flags) {
// Callers can access only the libs they depend on, otherwise they need to explicitly
// ask for the shared libraries given the caller is allowed to access all static libs.
if ((flags & PackageManager.MATCH_STATIC_SHARED_LIBRARIES) != 0) {
@@ -2375,7 +2381,7 @@
* activity was not set by the DPC.
*/
public final boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent,
- int userId, String resolvedType, int flags) {
+ int userId, String resolvedType, @PackageManager.ResolveInfoFlags long flags) {
return intent.isImplicitImageCaptureIntent() && !isPersistentPreferredActivitySetByDpm(
intent, userId, resolvedType, flags);
}
@@ -2416,7 +2422,7 @@
private boolean isInstantAppResolutionAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
- boolean skipPackageCheck, int flags) {
+ boolean skipPackageCheck, @PackageManager.ResolveInfoFlags long flags) {
if (mInstantAppResolverConnection == null) {
return false;
}
@@ -2456,7 +2462,7 @@
// Or if there's already an ephemeral app installed that handles the action
protected boolean isInstantAppResolutionAllowedBody(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
- boolean skipPackageCheck, int flags) {
+ boolean skipPackageCheck, @PackageManager.ResolveInfoFlags long flags) {
final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
for (int n = 0; n < count; n++) {
final ResolveInfo info = resolvedActivities.get(n);
@@ -2488,7 +2494,7 @@
}
private boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
- String resolvedType, int flags) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags) {
PersistentPreferredIntentResolver ppir =
mSettings.getPersistentPreferredActivities(userId);
//TODO(b/158003772): Remove double query
@@ -2645,8 +2651,8 @@
return mPermissionManager.checkUidPermission(uid, permName);
}
- public int getPackageUidInternal(String packageName, int flags, int userId,
- int callingUid) {
+ public int getPackageUidInternal(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId, int callingUid) {
// reader
final AndroidPackage p = mPackages.get(packageName);
if (p != null && AndroidPackageUtils.isMatchForSystemOnly(p, flags)) {
@@ -2670,7 +2676,7 @@
/**
* Update given flags based on encryption status of current user.
*/
- private int updateFlags(int flags, int userId) {
+ private long updateFlags(long flags, int userId) {
if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE)) != 0) {
// Caller expressed an explicit opinion about what encryption
@@ -2691,21 +2697,21 @@
/**
* Update given flags when being used to request {@link ApplicationInfo}.
*/
- public final int updateFlagsForApplication(int flags, int userId) {
+ public final long updateFlagsForApplication(long flags, int userId) {
return updateFlagsForPackage(flags, userId);
}
/**
* Update given flags when being used to request {@link ComponentInfo}.
*/
- public final int updateFlagsForComponent(int flags, int userId) {
+ public final long updateFlagsForComponent(long flags, int userId) {
return updateFlags(flags, userId);
}
/**
* Update given flags when being used to request {@link PackageInfo}.
*/
- public final int updateFlagsForPackage(int flags, int userId) {
+ public final long updateFlagsForPackage(long flags, int userId) {
final boolean isCallerSystemUser = UserHandle.getCallingUserId()
== UserHandle.USER_SYSTEM;
if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
@@ -2741,14 +2747,14 @@
* action and a {@code android.intent.category.BROWSABLE} category</li>
* </ul>
*/
- public final int updateFlagsForResolve(int flags, int userId, int callingUid,
+ public final long updateFlagsForResolve(long flags, int userId, int callingUid,
boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
return updateFlagsForResolve(flags, userId, callingUid,
wantInstantApps, false /*onlyExposedExplicitly*/,
isImplicitImageCaptureIntentAndNotSetByDpc);
}
- public final int updateFlagsForResolve(int flags, int userId, int callingUid,
+ public final long updateFlagsForResolve(long flags, int userId, int callingUid,
boolean wantInstantApps, boolean onlyExposedExplicitly,
boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
// Safe mode means we shouldn't match any third-party components
@@ -3169,7 +3175,7 @@
// The body of findPreferredActivity.
protected PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityBody(
- Intent intent, String resolvedType, int flags,
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered,
int callingUid, boolean isDeviceProvisioned) {
@@ -3378,7 +3384,7 @@
}
public final PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal(
- Intent intent, String resolvedType, int flags,
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
@@ -3395,8 +3401,8 @@
}
public final ResolveInfo findPersistentPreferredActivityLP(Intent intent,
- String resolvedType,
- int flags, List<ResolveInfo> query, boolean debug, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ List<ResolveInfo> query, boolean debug, int userId) {
final int n = query.size();
PersistentPreferredIntentResolver ppir =
mSettings.getPersistentPreferredActivities(userId);
@@ -3592,7 +3598,8 @@
}
@Override
- public int[] getPackageGids(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int[] getPackageGids(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForPackage(flags, userId);
@@ -3668,8 +3675,8 @@
@Nullable
@Override
- public ActivityInfo getReceiverInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ActivityInfo getReceiverInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId);
@@ -3702,7 +3709,7 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName,
- int flags, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return null;
Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0");
final int callingUid = Binder.getCallingUid();
@@ -3831,7 +3838,7 @@
@Override
public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
- int flags, int callingUid, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, int callingUid, @UserIdInt int userId) {
List<VersionedPackage> versionedPackages = null;
final ArrayMap<String, ? extends PackageStateInternal> packageStates = getPackageStates();
final int packageCount = packageStates.size();
@@ -3888,7 +3895,8 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
- @NonNull String packageName, int flags, @UserIdInt int userId) {
+ @NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_SHARED_LIBRARIES,
"getDeclaredSharedLibraries");
int callingUid = Binder.getCallingUid();
@@ -3963,8 +3971,8 @@
@Nullable
@Override
- public ProviderInfo getProviderInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ProviderInfo getProviderInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId);
@@ -4438,7 +4446,8 @@
@NonNull
@Override
public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
- @NonNull String[] permissions, int flags, @UserIdInt int userId) {
+ @NonNull String[] permissions, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForPackage(flags, userId);
enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */,
@@ -4458,7 +4467,8 @@
}
private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageStateInternal ps,
- String[] permissions, boolean[] tmp, int flags, int userId) {
+ String[] permissions, boolean[] tmp, @PackageManager.PackageInfoFlags long flags,
+ int userId) {
int numMatch = 0;
for (int i=0; i<permissions.length; i++) {
final String permission = permissions[i];
@@ -4478,7 +4488,7 @@
// The above might return null in cases of uninstalled apps or install-state
// skew across users/profiles.
if (pi != null) {
- if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+ if ((flags & PackageManager.GET_PERMISSIONS) == 0) {
if (numMatch == permissions.length) {
pi.requestedPermissions = permissions;
} else {
@@ -4498,7 +4508,8 @@
@NonNull
@Override
- public List<ApplicationInfo> getInstalledApplications(int flags, @UserIdInt int userId,
+ public List<ApplicationInfo> getInstalledApplications(
+ @PackageManager.ApplicationInfoFlags long flags, @UserIdInt int userId,
int callingUid) {
if (getInstantAppPackageName(callingUid) != null) {
return Collections.emptyList();
@@ -4521,7 +4532,7 @@
list = new ArrayList<>(packageStates.size());
for (PackageStateInternal ps : packageStates.values()) {
ApplicationInfo ai;
- int effectiveFlags = flags;
+ long effectiveFlags = flags;
if (ps.isSystem()) {
effectiveFlags |= PackageManager.MATCH_ANY_USER;
}
@@ -4574,8 +4585,8 @@
@Nullable
@Override
- public ProviderInfo resolveContentProvider(@NonNull String name, int flags,
- @UserIdInt int userId, int callingUid) {
+ public ProviderInfo resolveContentProvider(@NonNull String name,
+ @PackageManager.ResolveInfoFlags long flags, @UserIdInt int userId, int callingUid) {
if (!mUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId);
final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
@@ -4664,7 +4675,7 @@
@NonNull
@Override
public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName,
- int uid, int flags, @Nullable String metaDataKey) {
+ int uid, @PackageManager.ComponentInfoFlags long flags, @Nullable String metaDataKey) {
final int callingUid = Binder.getCallingUid();
final int userId = processName != null ? UserHandle.getUserId(uid)
: UserHandle.getCallingUserId();
@@ -5209,7 +5220,8 @@
}
@Override
- public int getPackageUid(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int getPackageUid(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
if (!mUserManager.exists(userId)) return -1;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForPackage(flags, userId);
@@ -5312,7 +5324,7 @@
if (parent == null) {
return false;
}
- int flags = updateFlagsForResolve(0, parent.id, callingUid,
+ long flags = updateFlagsForResolve(0, parent.id, callingUid,
false /*includeInstantApps*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, parent.id,
resolvedType, 0));
diff --git a/services/core/java/com/android/server/pm/ComputerLocked.java b/services/core/java/com/android/server/pm/ComputerLocked.java
index 801aaef..f180d19 100644
--- a/services/core/java/com/android/server/pm/ComputerLocked.java
+++ b/services/core/java/com/android/server/pm/ComputerLocked.java
@@ -29,6 +29,7 @@
import android.content.pm.InstrumentationInfo;
import android.content.pm.KeySet;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProcessInfo;
import android.content.pm.ProviderInfo;
@@ -89,7 +90,7 @@
}
}
public @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(
- Intent intent, String resolvedType, int flags, int filterCallingUid, int userId,
+ Intent intent, String resolvedType, long flags, int filterCallingUid, int userId,
boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
String instantAppPkgName) {
synchronized (mLock) {
@@ -312,7 +313,8 @@
}
@Override
- public int[] getPackageGids(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int[] getPackageGids(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
synchronized (mLock) {
return super.getPackageGids(packageName, flags, userId);
}
@@ -336,8 +338,8 @@
@Nullable
@Override
- public ActivityInfo getReceiverInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ActivityInfo getReceiverInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
synchronized (mLock) {
return super.getReceiverInfo(component, flags, userId);
}
@@ -346,7 +348,7 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName,
- int flags, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
synchronized (mLock) {
return super.getSharedLibraries(packageName, flags, userId);
}
@@ -363,7 +365,7 @@
@Override
public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
- int flags, int callingUid, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, int callingUid, @UserIdInt int userId) {
synchronized (mLock) {
return super.getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId);
}
@@ -372,7 +374,8 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
- @NonNull String packageName, int flags, @UserIdInt int userId) {
+ @NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
synchronized (mLock) {
return super.getDeclaredSharedLibraries(packageName, flags, userId);
}
@@ -380,8 +383,8 @@
@Nullable
@Override
- public ProviderInfo getProviderInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ProviderInfo getProviderInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
synchronized (mLock) {
return super.getProviderInfo(component, flags, userId);
}
@@ -495,7 +498,8 @@
@NonNull
@Override
public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
- @NonNull String[] permissions, int flags, @UserIdInt int userId) {
+ @NonNull String[] permissions, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
synchronized (mLock) {
return super.getPackagesHoldingPermissions(permissions, flags, userId);
}
@@ -503,7 +507,8 @@
@NonNull
@Override
- public List<ApplicationInfo> getInstalledApplications(int flags, @UserIdInt int userId,
+ public List<ApplicationInfo> getInstalledApplications(
+ @PackageManager.ApplicationInfoFlags long flags, @UserIdInt int userId,
int callingUid) {
synchronized (mLock) {
return super.getInstalledApplications(flags, userId, callingUid);
@@ -512,8 +517,8 @@
@Nullable
@Override
- public ProviderInfo resolveContentProvider(@NonNull String name, int flags,
- @UserIdInt int userId, int callingUid) {
+ public ProviderInfo resolveContentProvider(@NonNull String name,
+ @PackageManager.ResolveInfoFlags long flags, @UserIdInt int userId, int callingUid) {
synchronized (mLock) {
return super.resolveContentProvider(name, flags, userId, callingUid);
}
@@ -539,7 +544,7 @@
@NonNull
@Override
public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName,
- int uid, int flags, @Nullable String metaDataKey) {
+ int uid, @PackageManager.ComponentInfoFlags long flags, @Nullable String metaDataKey) {
synchronized (mLock) {
return super.queryContentProviders(processName, uid, flags, metaDataKey);
}
@@ -711,7 +716,8 @@
}
@Override
- public int getPackageUid(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int getPackageUid(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
synchronized (mLock) {
return super.getPackageUid(packageName, flags, userId);
}
diff --git a/services/core/java/com/android/server/pm/ComputerTracker.java b/services/core/java/com/android/server/pm/ComputerTracker.java
index ca17d66..a3cd092 100644
--- a/services/core/java/com/android/server/pm/ComputerTracker.java
+++ b/services/core/java/com/android/server/pm/ComputerTracker.java
@@ -97,8 +97,8 @@
}
public @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags,
- @PackageManagerInternal.PrivateResolveFlags int privateResolveFlags,
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,
int filterCallingUid, int userId, boolean resolveForStart,
boolean allowDynamicSplits) {
ThreadComputer current = snapshot();
@@ -111,7 +111,7 @@
}
}
public @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
ThreadComputer current = snapshot();
try {
return current.mComputer.queryIntentActivitiesInternal(intent, resolvedType, flags,
@@ -121,8 +121,8 @@
}
}
public @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- boolean includeInstantApps) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId,
+ int callingUid, boolean includeInstantApps) {
ThreadComputer current = snapshot();
try {
return current.mComputer.queryIntentServicesInternal(intent, resolvedType, flags,
@@ -132,10 +132,9 @@
}
}
public @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(
- Intent intent,
- String resolvedType, int flags, int filterCallingUid, int userId,
- boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
- String instantAppPkgName) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits,
+ String pkgName, String instantAppPkgName) {
ThreadComputer current = live();
try {
return current.mComputer.queryIntentActivitiesInternalBody(intent, resolvedType,
@@ -145,7 +144,8 @@
current.release();
}
}
- public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ public ActivityInfo getActivityInfo(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, int userId) {
ThreadComputer current = snapshot();
try {
return current.mComputer.getActivityInfo(component, flags, userId);
@@ -153,7 +153,8 @@
current.release();
}
}
- public ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
+ public ActivityInfo getActivityInfoInternal(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags,
int filterCallingUid, int userId) {
ThreadComputer current = live();
try {
@@ -180,7 +181,7 @@
}
}
public ApplicationInfo generateApplicationInfoFromSettings(String packageName,
- int flags, int filterCallingUid, int userId) {
+ long flags, int filterCallingUid, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.generateApplicationInfoFromSettings(packageName, flags,
@@ -189,7 +190,8 @@
current.release();
}
}
- public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+ public ApplicationInfo getApplicationInfo(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags, int userId) {
ThreadComputer current = snapshot();
try {
return current.mComputer.getApplicationInfo(packageName, flags, userId);
@@ -197,8 +199,8 @@
current.release();
}
}
- public ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
- int filterCallingUid, int userId) {
+ public ApplicationInfo getApplicationInfoInternal(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags, int filterCallingUid, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.getApplicationInfoInternal(packageName, flags,
@@ -225,7 +227,8 @@
}
}
public CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
- String resolvedType, int flags, int sourceUserId, int parentUserId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int sourceUserId,
+ int parentUserId) {
ThreadComputer current = live();
try {
return current.mComputer.getCrossProfileDomainPreferredLpr(intent, resolvedType,
@@ -264,7 +267,8 @@
current.release();
}
}
- public PackageInfo generatePackageInfo(PackageStateInternal ps, int flags, int userId) {
+ public PackageInfo generatePackageInfo(PackageStateInternal ps,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.generatePackageInfo(ps, flags, userId);
@@ -272,7 +276,8 @@
current.release();
}
}
- public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
+ public PackageInfo getPackageInfo(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
ThreadComputer current = snapshot();
try {
return current.mComputer.getPackageInfo(packageName, flags, userId);
@@ -281,7 +286,7 @@
}
}
public PackageInfo getPackageInfoInternal(String packageName, long versionCode,
- int flags, int filterCallingUid, int userId) {
+ long flags, int filterCallingUid, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.getPackageInfoInternal(packageName, versionCode, flags,
@@ -317,7 +322,7 @@
}
}
- public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
+ public ParceledListSlice<PackageInfo> getInstalledPackages(long flags, int userId) {
ThreadComputer current = snapshot();
try {
return current.mComputer.getInstalledPackages(flags, userId);
@@ -335,7 +340,8 @@
current.release();
}
}
- public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+ public ServiceInfo getServiceInfo(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.getServiceInfo(component, flags, userId);
@@ -440,7 +446,7 @@
}
}
public boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
- int userId, int flags) {
+ int userId, @PackageManager.ComponentInfoFlags long flags) {
ThreadComputer current = live();
try {
return current.mComputer.filterSharedLibPackage(ps, uid, userId, flags);
@@ -474,7 +480,7 @@
}
}
public boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent,
- int userId, String resolvedType, int flags) {
+ int userId, String resolvedType, @PackageManager.ResolveInfoFlags long flags) {
ThreadComputer current = live();
try {
return current.mComputer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent,
@@ -546,8 +552,8 @@
current.release();
}
}
- public int getPackageUidInternal(String packageName, int flags, int userId,
- int callingUid) {
+ public int getPackageUidInternal(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId, int callingUid) {
ThreadComputer current = live();
try {
return current.mComputer.getPackageUidInternal(packageName, flags, userId,
@@ -556,7 +562,7 @@
current.release();
}
}
- public int updateFlagsForApplication(int flags, int userId) {
+ public long updateFlagsForApplication(long flags, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.updateFlagsForApplication(flags, userId);
@@ -564,7 +570,7 @@
current.release();
}
}
- public int updateFlagsForComponent(int flags, int userId) {
+ public long updateFlagsForComponent(long flags, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.updateFlagsForComponent(flags, userId);
@@ -572,7 +578,7 @@
current.release();
}
}
- public int updateFlagsForPackage(int flags, int userId) {
+ public long updateFlagsForPackage(long flags, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.updateFlagsForPackage(flags, userId);
@@ -580,7 +586,7 @@
current.release();
}
}
- public int updateFlagsForResolve(int flags, int userId, int callingUid,
+ public long updateFlagsForResolve(long flags, int userId, int callingUid,
boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
ThreadComputer current = snapshot();
try {
@@ -590,7 +596,7 @@
current.release();
}
}
- public int updateFlagsForResolve(int flags, int userId, int callingUid,
+ public long updateFlagsForResolve(long flags, int userId, int callingUid,
boolean wantInstantApps, boolean onlyExposedExplicitly,
boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
ThreadComputer current = live();
@@ -642,8 +648,9 @@
}
}
public PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal(
- Intent intent, String resolvedType, int flags, List<ResolveInfo> query, boolean always,
- boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug,
+ int userId, boolean queryMayBeFiltered) {
ThreadComputer current = live();
try {
return current.mComputer.findPreferredActivityInternal(intent, resolvedType, flags,
@@ -653,8 +660,8 @@
}
}
public ResolveInfo findPersistentPreferredActivityLP(Intent intent,
- String resolvedType, int flags, List<ResolveInfo> query, boolean debug,
- int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ List<ResolveInfo> query, boolean debug, int userId) {
ThreadComputer current = live();
try {
return current.mComputer.findPersistentPreferredActivityLP(intent, resolvedType,
@@ -741,7 +748,8 @@
}
@Override
- public int[] getPackageGids(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int[] getPackageGids(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getPackageGids(packageName, flags, userId);
}
@@ -765,8 +773,8 @@
@Nullable
@Override
- public ActivityInfo getReceiverInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ActivityInfo getReceiverInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getReceiverInfo(component, flags, userId);
}
@@ -775,7 +783,7 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(@NonNull String packageName,
- int flags, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getSharedLibraries(packageName, flags, userId);
}
@@ -800,7 +808,7 @@
@Override
public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
- int flags, int callingUid, @UserIdInt int userId) {
+ @PackageManager.PackageInfoFlags long flags, int callingUid, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getPackagesUsingSharedLibrary(libInfo, flags, callingUid,
userId);
@@ -810,7 +818,8 @@
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
- @NonNull String packageName, int flags, @UserIdInt int userId) {
+ @NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getDeclaredSharedLibraries(packageName, flags, userId);
}
@@ -818,8 +827,8 @@
@Nullable
@Override
- public ProviderInfo getProviderInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ProviderInfo getProviderInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getProviderInfo(component, flags, userId);
}
@@ -934,7 +943,8 @@
@NonNull
@Override
public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
- @NonNull String[] permissions, int flags, @UserIdInt int userId) {
+ @NonNull String[] permissions, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getPackagesHoldingPermissions(permissions, flags, userId);
}
@@ -942,7 +952,8 @@
@NonNull
@Override
- public List<ApplicationInfo> getInstalledApplications(int flags, @UserIdInt int userId,
+ public List<ApplicationInfo> getInstalledApplications(
+ @PackageManager.ApplicationInfoFlags long flags, @UserIdInt int userId,
int callingUid) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getInstalledApplications(flags, userId, callingUid);
@@ -951,8 +962,8 @@
@Nullable
@Override
- public ProviderInfo resolveContentProvider(@NonNull String name, int flags,
- @UserIdInt int userId, int callingUid) {
+ public ProviderInfo resolveContentProvider(@NonNull String name,
+ @PackageManager.ResolveInfoFlags long flags, @UserIdInt int userId, int callingUid) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.resolveContentProvider(name, flags, userId, callingUid);
}
@@ -979,7 +990,7 @@
@NonNull
@Override
public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName,
- int uid, int flags, @Nullable String metaDataKey) {
+ int uid, @PackageManager.ComponentInfoFlags long flags, @Nullable String metaDataKey) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.queryContentProviders(processName, uid, flags, metaDataKey);
}
@@ -1152,7 +1163,8 @@
}
@Override
- public int getPackageUid(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int getPackageUid(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
try (ThreadComputer current = snapshot()) {
return current.mComputer.getPackageUid(packageName, flags, userId);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 7c8515b..4767d3a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1461,8 +1461,9 @@
private TreeMap<PackageInstallerSession, TreeSet<PackageInstallerSession>> mSessionMap;
private final Comparator<PackageInstallerSession> mSessionCreationComparator =
- Comparator.comparingLong((PackageInstallerSession sess) -> sess.createdMillis)
- .thenComparingInt(sess -> sess.sessionId);
+ Comparator.comparingLong(
+ (PackageInstallerSession sess) -> sess != null ? sess.createdMillis : -1)
+ .thenComparingInt(sess -> sess != null ? sess.sessionId : -1);
ParentChildSessionMap() {
mSessionMap = new TreeMap<>(mSessionCreationComparator);
@@ -1500,10 +1501,12 @@
for (Map.Entry<PackageInstallerSession, TreeSet<PackageInstallerSession>> entry
: mSessionMap.entrySet()) {
PackageInstallerSession parentSession = entry.getKey();
- pw.print(tag + " ");
- parentSession.dump(pw);
- pw.println();
- pw.increaseIndent();
+ if (parentSession != null) {
+ pw.print(tag + " ");
+ parentSession.dump(pw);
+ pw.println();
+ pw.increaseIndent();
+ }
for (PackageInstallerSession childSession : entry.getValue()) {
pw.print(tag + " Child ");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5526990..9f5adcb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2576,8 +2576,8 @@
return mComputer.canViewInstantApps(callingUid, userId);
}
- private PackageInfo generatePackageInfo(@NonNull PackageStateInternal ps, int flags,
- int userId) {
+ private PackageInfo generatePackageInfo(@NonNull PackageStateInternal ps,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return mComputer.generatePackageInfo(ps, flags, userId);
}
@@ -2616,13 +2616,14 @@
}
@Override
- public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
+ public PackageInfo getPackageInfo(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return mComputer.getPackageInfo(packageName, flags, userId);
}
@Override
public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
- int flags, int userId) {
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return mComputer.getPackageInfoInternal(versionedPackage.getPackageName(),
versionedPackage.getLongVersionCode(), flags, Binder.getCallingUid(), userId);
}
@@ -2659,7 +2660,7 @@
}
private boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
- int userId, int flags) {
+ int userId, @PackageManager.ComponentInfoFlags long flags) {
return mComputer.filterSharedLibPackage(ps, uid, userId, flags);
}
@@ -2674,16 +2675,19 @@
}
@Override
- public int getPackageUid(@NonNull String packageName, int flags, @UserIdInt int userId) {
+ public int getPackageUid(@NonNull String packageName,
+ @PackageManager.PackageInfoFlags long flags, @UserIdInt int userId) {
return mComputer.getPackageUid(packageName, flags, userId);
}
- private int getPackageUidInternal(String packageName, int flags, int userId, int callingUid) {
+ private int getPackageUidInternal(String packageName,
+ @PackageManager.PackageInfoFlags long flags, int userId, int callingUid) {
return mComputer.getPackageUidInternal(packageName, flags, userId, callingUid);
}
@Override
- public int[] getPackageGids(String packageName, int flags, int userId) {
+ public int[] getPackageGids(String packageName, @PackageManager.PackageInfoFlags long flags,
+ int userId) {
return mComputer.getPackageGids(packageName, flags, userId);
}
@@ -2696,14 +2700,15 @@
.getPermissionGroupInfo(groupName, flags);
}
- private ApplicationInfo generateApplicationInfoFromSettings(String packageName, int flags,
- int filterCallingUid, int userId) {
- return mComputer.generateApplicationInfoFromSettings(packageName, flags,
- filterCallingUid, userId);
+ private ApplicationInfo generateApplicationInfoFromSettings(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags, int filterCallingUid, int userId) {
+ return mComputer.generateApplicationInfoFromSettings(packageName, flags, filterCallingUid,
+ userId);
}
@Override
- public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+ public ApplicationInfo getApplicationInfo(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags, int userId) {
return mComputer.getApplicationInfo(packageName, flags, userId);
}
@@ -2713,7 +2718,8 @@
* to clearing. Because it can only be provided by trusted code, its value can be
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
- private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+ private ApplicationInfo getApplicationInfoInternal(String packageName,
+ @PackageManager.ApplicationInfoFlags long flags,
int filterCallingUid, int userId) {
return mComputer.getApplicationInfoInternal(packageName, flags,
filterCallingUid, userId);
@@ -2948,21 +2954,21 @@
/**
* Update given flags when being used to request {@link PackageInfo}.
*/
- private int updateFlagsForPackage(int flags, int userId) {
+ private long updateFlagsForPackage(long flags, int userId) {
return mComputer.updateFlagsForPackage(flags, userId);
}
/**
* Update given flags when being used to request {@link ApplicationInfo}.
*/
- private int updateFlagsForApplication(int flags, int userId) {
+ private long updateFlagsForApplication(long flags, int userId) {
return mComputer.updateFlagsForApplication(flags, userId);
}
/**
* Update given flags when being used to request {@link ComponentInfo}.
*/
- private int updateFlagsForComponent(int flags, int userId) {
+ private long updateFlagsForComponent(long flags, int userId) {
return mComputer.updateFlagsForComponent(flags, userId);
}
@@ -2978,7 +2984,7 @@
* action and a {@code android.intent.category.BROWSABLE} category</li>
* </ul>
*/
- int updateFlagsForResolve(int flags, int userId, int callingUid,
+ long updateFlagsForResolve(long flags, int userId, int callingUid,
boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
return mComputer.updateFlagsForResolve(flags, userId, callingUid,
wantInstantApps, isImplicitImageCaptureIntentAndNotSetByDpc);
@@ -2990,7 +2996,8 @@
}
@Override
- public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ public ActivityInfo getActivityInfo(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, int userId) {
return mComputer.getActivityInfo(component, flags, userId);
}
@@ -3000,8 +3007,8 @@
* to clearing. Because it can only be provided by trusted code, its value can be
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
- private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
- int filterCallingUid, int userId) {
+ private ActivityInfo getActivityInfoInternal(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, int filterCallingUid, int userId) {
return mComputer.getActivityInfoInternal(component, flags,
filterCallingUid, userId);
}
@@ -3014,40 +3021,43 @@
}
@Override
- public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
+ public ActivityInfo getReceiverInfo(ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, int userId) {
return mComputer.getReceiverInfo(component, flags, userId);
}
@Override
public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(String packageName,
- int flags, int userId) {
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return mComputer.getSharedLibraries(packageName, flags, userId);
}
@Nullable
@Override
public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
- @NonNull String packageName, int flags, @UserIdInt int userId) {
+ @NonNull String packageName, @PackageManager.PackageInfoFlags long flags,
+ @NonNull int userId) {
return mComputer.getDeclaredSharedLibraries(packageName, flags, userId);
}
@Nullable
List<VersionedPackage> getPackagesUsingSharedLibrary(
- SharedLibraryInfo libInfo, int flags, int callingUid, int userId) {
+ SharedLibraryInfo libInfo, @PackageManager.PackageInfoFlags long flags, int callingUid,
+ int userId) {
return mComputer.getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId);
}
@Nullable
@Override
- public ServiceInfo getServiceInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ServiceInfo getServiceInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
return mComputer.getServiceInfo(component, flags, userId);
}
@Nullable
@Override
- public ProviderInfo getProviderInfo(@NonNull ComponentName component, int flags,
- @UserIdInt int userId) {
+ public ProviderInfo getProviderInfo(@NonNull ComponentName component,
+ @PackageManager.ComponentInfoFlags long flags, @UserIdInt int userId) {
return mComputer.getProviderInfo(component, flags, userId);
}
@@ -3336,7 +3346,7 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int userId) {
+ @PackageManager.ResolveInfoFlags long flags, int userId) {
return mResolveIntentHelper.resolveIntentInternal(intent, resolvedType, flags,
0 /*privateResolveFlags*/, userId, false, Binder.getCallingUid());
}
@@ -3381,7 +3391,7 @@
*/
@GuardedBy("mLock")
boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId,
- String resolvedType, int flags) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags) {
return mComputer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
resolvedType, flags);
}
@@ -3389,10 +3399,10 @@
@GuardedBy("mLock")
ResolveInfo findPersistentPreferredActivityLP(Intent intent,
String resolvedType,
- int flags, List<ResolveInfo> query, boolean debug, int userId) {
+ @PackageManager.ResolveInfoFlags long flags, List<ResolveInfo> query, boolean debug,
+ int userId) {
return mComputer.findPersistentPreferredActivityLP(intent,
- resolvedType,
- flags, query, debug, userId);
+ resolvedType, flags, query, debug, userId);
}
// findPreferredActivityBody returns two items: a "things changed" flag and a
@@ -3403,7 +3413,7 @@
}
FindPreferredActivityBodyResult findPreferredActivityInternal(
- Intent intent, String resolvedType, int flags,
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
return mComputer.findPreferredActivityInternal(
@@ -3433,7 +3443,7 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
@@ -3453,21 +3463,23 @@
}
@NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
return mComputer.queryIntentActivitiesInternal(intent,
resolvedType, flags, userId);
}
@NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
- int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ @PrivateResolveFlags long privateResolveFlags, int filterCallingUid, int userId,
+ boolean resolveForStart, boolean allowDynamicSplits) {
return mComputer.queryIntentActivitiesInternal(intent,
resolvedType, flags, privateResolveFlags,
filterCallingUid, userId, resolveForStart, allowDynamicSplits);
}
private CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
- String resolvedType, int flags, int sourceUserId, int parentUserId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int sourceUserId,
+ int parentUserId) {
return mComputer.getCrossProfileDomainPreferredLpr(intent,
resolvedType, flags, sourceUserId, parentUserId);
}
@@ -3494,20 +3506,21 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
return new ParceledListSlice<>(mResolveIntentHelper.queryIntentActivityOptionsInternal(
caller, specifics, specificTypes, intent, resolvedType, flags, userId));
}
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
return new ParceledListSlice<>(mResolveIntentHelper.queryIntentReceiversInternal(intent,
resolvedType, flags, userId, Binder.getCallingUid()));
}
@Override
- public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+ public ResolveInfo resolveService(Intent intent, String resolvedType,
+ @PackageManager.ResolveInfoFlags long flags, int userId) {
final int callingUid = Binder.getCallingUid();
return mResolveIntentHelper.resolveServiceInternal(intent, resolvedType, flags, userId,
callingUid);
@@ -3515,15 +3528,15 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
final int callingUid = Binder.getCallingUid();
return new ParceledListSlice<>(queryIntentServicesInternal(
intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/));
}
@NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- boolean includeInstantApps) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId,
+ int callingUid, boolean includeInstantApps) {
return mComputer.queryIntentServicesInternal(intent,
resolvedType, flags, userId, callingUid,
includeInstantApps);
@@ -3531,24 +3544,27 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
return new ParceledListSlice<>(mResolveIntentHelper.queryIntentContentProvidersInternal(
intent, resolvedType, flags, userId));
}
@Override
- public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
+ public ParceledListSlice<PackageInfo> getInstalledPackages(
+ @PackageManager.PackageInfoFlags long flags, int userId) {
return mComputer.getInstalledPackages(flags, userId);
}
@Override
public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
- @NonNull String[] permissions, int flags, @UserIdInt int userId) {
+ @NonNull String[] permissions, @PackageManager.PackageInfoFlags long flags,
+ @UserIdInt int userId) {
return mComputer.getPackagesHoldingPermissions(permissions, flags, userId);
}
@Override
- public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
+ public ParceledListSlice<ApplicationInfo> getInstalledApplications(
+ @PackageManager.ApplicationInfoFlags long flags, int userId) {
final int callingUid = Binder.getCallingUid();
return new ParceledListSlice<>(
mComputer.getInstalledApplications(flags, userId, callingUid));
@@ -3652,7 +3668,8 @@
}
@Override
- public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
+ public ProviderInfo resolveContentProvider(String name,
+ @PackageManager.ResolveInfoFlags long flags, int userId) {
return mComputer.resolveContentProvider(name, flags, userId, Binder.getCallingUid());
}
@@ -3664,7 +3681,7 @@
@NonNull
@Override
public ParceledListSlice<ProviderInfo> queryContentProviders(@Nullable String processName,
- int uid, int flags, @Nullable String metaDataKey) {
+ int uid, @PackageManager.ComponentInfoFlags long flags, @Nullable String metaDataKey) {
return mComputer.queryContentProviders(processName, uid, flags, metaDataKey);
}
@@ -7509,8 +7526,8 @@
private class PackageManagerInternalImpl extends PackageManagerInternal {
@Override
- public List<ApplicationInfo> getInstalledApplications(int flags, int userId,
- int callingUid) {
+ public List<ApplicationInfo> getInstalledApplications(
+ @PackageManager.ApplicationInfoFlags long flags, int userId, int callingUid) {
return PackageManagerService.this.mComputer.getInstalledApplications(flags, userId,
callingUid);
}
@@ -7705,7 +7722,8 @@
@Override
public PackageInfo getPackageInfo(
- String packageName, int flags, int filterCallingUid, int userId) {
+ String packageName, @PackageManager.PackageInfoFlags long flags,
+ int filterCallingUid, int userId) {
return PackageManagerService.this.mComputer
.getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
flags, filterCallingUid, userId);
@@ -7833,28 +7851,32 @@
}
@Override
- public int getPackageUid(String packageName, int flags, int userId) {
+ public int getPackageUid(String packageName, @PackageManager.PackageInfoFlags long flags,
+ int userId) {
return PackageManagerService.this
.getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID);
}
@Override
public ApplicationInfo getApplicationInfo(
- String packageName, int flags, int filterCallingUid, int userId) {
+ String packageName, @PackageManager.ApplicationInfoFlags long flags,
+ int filterCallingUid, int userId) {
return PackageManagerService.this
.getApplicationInfoInternal(packageName, flags, filterCallingUid, userId);
}
@Override
public ActivityInfo getActivityInfo(
- ComponentName component, int flags, int filterCallingUid, int userId) {
+ ComponentName component, @PackageManager.ComponentInfoFlags long flags,
+ int filterCallingUid, int userId) {
return PackageManagerService.this
.getActivityInfoInternal(component, flags, filterCallingUid, userId);
}
@Override
public List<ResolveInfo> queryIntentActivities(
- Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int filterCallingUid, int userId) {
return PackageManagerService.this
.queryIntentActivitiesInternal(intent, resolvedType, flags, 0, filterCallingUid,
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
@@ -7862,14 +7884,16 @@
@Override
public List<ResolveInfo> queryIntentReceivers(Intent intent,
- String resolvedType, int flags, int filterCallingUid, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int filterCallingUid, int userId) {
return PackageManagerService.this.mResolveIntentHelper.queryIntentReceiversInternal(
intent, resolvedType, flags, userId, filterCallingUid);
}
@Override
public List<ResolveInfo> queryIntentServices(
- Intent intent, int flags, int callingUid, int userId) {
+ Intent intent, @PackageManager.ResolveInfoFlags long flags, int callingUid,
+ int userId) {
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
return PackageManagerService.this
.queryIntentServicesInternal(intent, resolvedType, flags, userId, callingUid,
@@ -7935,7 +7959,7 @@
}
@Override
- public boolean isEnabledAndMatches(ParsedMainComponent component, int flags, int userId) {
+ public boolean isEnabledAndMatches(ParsedMainComponent component, long flags, int userId) {
return PackageStateUtils.isEnabledAndMatches(
getPackageStateInternal(component.getPackageName()), component, flags, userId);
}
@@ -8137,8 +8161,9 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int privateResolveFlags, int userId, boolean resolveForStart,
- int filterCallingUid) {
+ @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
+ boolean resolveForStart, int filterCallingUid) {
return mResolveIntentHelper.resolveIntentInternal(
intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
filterCallingUid);
@@ -8146,14 +8171,14 @@
@Override
public ResolveInfo resolveService(Intent intent, String resolvedType,
- int flags, int userId, int callingUid) {
+ @PackageManager.ResolveInfoFlags long flags, int userId, int callingUid) {
return mResolveIntentHelper.resolveServiceInternal(intent, resolvedType, flags, userId,
callingUid);
}
@Override
- public ProviderInfo resolveContentProvider(String name, int flags, int userId,
- int callingUid) {
+ public ProviderInfo resolveContentProvider(String name,
+ @PackageManager.ResolveInfoFlags long flags, int userId, int callingUid) {
return PackageManagerService.this.mComputer
.resolveContentProvider(name, flags, userId,callingUid);
}
@@ -9037,9 +9062,12 @@
@Override
public void setSplashScreenTheme(@NonNull String packageName, @Nullable String themeId,
int userId) {
- mutateInstalledPackageSetting(packageName, Binder.getCallingUid(), userId, pkgSetting -> {
- pkgSetting.setSplashScreenTheme(userId, themeId);
- });
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
+ false /* checkShell */, "setSplashScreenTheme");
+ enforceOwnerRights(packageName, callingUid);
+ mutateInstalledPackageSetting(packageName, callingUid, userId,
+ pkgSetting -> pkgSetting.setSplashScreenTheme(userId, themeId));
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 1848ef5..3b643b5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -1079,7 +1079,7 @@
public static boolean hasAnyDomainApproval(
@NonNull DomainVerificationManagerInternal manager,
@NonNull PackageStateInternal pkgSetting, @NonNull Intent intent,
- @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
+ @PackageManager.ResolveInfoFlags long resolveInfoFlags, @UserIdInt int userId) {
return manager.approvalLevelForDomain(pkgSetting, intent, resolveInfoFlags, userId)
> DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE;
}
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index cb97e2a..8c91b16 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -75,8 +75,8 @@
}
private ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query, boolean always, boolean removeMatches,
- boolean debug, int userId) {
+ @PackageManager.ResolveInfoFlags long flags, List<ResolveInfo> query, boolean always,
+ boolean removeMatches, boolean debug, int userId) {
return findPreferredActivityNotLocked(
intent, resolvedType, flags, query, always, removeMatches, debug, userId,
UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID);
@@ -85,8 +85,9 @@
// TODO: handle preferred activities missing while user has amnesia
/** <b>must not hold {@link PackageManagerService.mLock}</b> */
public ResolveInfo findPreferredActivityNotLocked(
- Intent intent, String resolvedType, int flags, List<ResolveInfo> query, boolean always,
- boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug,
+ int userId, boolean queryMayBeFiltered) {
if (Thread.holdsLock(mPm.mLock)) {
Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
+ " is holding mLock", new Throwable());
@@ -675,7 +676,7 @@
final int callingUid = Binder.getCallingUid();
intent = PackageManagerServiceUtils.updateIntentForResolve(intent);
final String resolvedType = intent.resolveTypeIfNeeded(mPm.mContext.getContentResolver());
- final int flags = mPm.updateFlagsForResolve(
+ final long flags = mPm.updateFlagsForResolve(
0, userId, callingUid, false /*includeInstantApps*/,
mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
0));
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 70855a9..0ee1f89 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -74,8 +74,9 @@
* However, if {@code resolveForStart} is {@code true}, all instant apps are visible
* since we need to allow the system to start any installed application.
*/
- public ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, int flags,
- @PackageManagerInternal.PrivateResolveFlags int privateResolveFlags, int userId,
+ public ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
+ @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
boolean resolveForStart, int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
@@ -114,8 +115,9 @@
}
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
- int flags, int privateResolveFlags, List<ResolveInfo> query, int userId,
- boolean queryMayBeFiltered) {
+ @PackageManager.ResolveInfoFlags long flags,
+ @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,
+ List<ResolveInfo> query, int userId, boolean queryMayBeFiltered) {
if (query != null) {
final int n = query.size();
if (n == 1) {
@@ -276,7 +278,8 @@
// In this method, we have to know the actual calling UID, but in some cases Binder's
// call identity is removed, so the UID has to be passed in explicitly.
public @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
- String resolvedType, int flags, int userId, int filterCallingUid) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId,
+ int filterCallingUid) {
if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
mPm.enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
false /*checkShell*/, "query intent receivers");
@@ -370,8 +373,8 @@
}
- public ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
- int userId, int callingUid) {
+ public ResolveInfo resolveServiceInternal(Intent intent, String resolvedType,
+ @PackageManager.ResolveInfoFlags long flags, int userId, int callingUid) {
if (!mPm.mUserManager.exists(userId)) return null;
flags = mPm.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
@@ -388,7 +391,8 @@
}
public @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
- Intent intent, String resolvedType, int flags, int userId) {
+ Intent intent, String resolvedType, @PackageManager.ResolveInfoFlags long flags,
+ int userId) {
if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
final int callingUid = Binder.getCallingUid();
final String instantAppPkgName = mPm.getInstantAppPackageName(callingUid);
@@ -529,7 +533,7 @@
public @NonNull List<ResolveInfo> queryIntentActivityOptionsInternal(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, @PackageManager.ResolveInfoFlags long flags, int userId) {
if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
final int callingUid = Binder.getCallingUid();
flags = mPm.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 1f5d79c..6a163b2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -154,7 +154,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -4150,7 +4149,7 @@
return getDisabledSystemPkgLPr(enabledPackageSetting.getPackageName());
}
- boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
+ boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, long flags, int userId) {
final PackageSetting ps = mPackages.get(componentInfo.packageName);
if (ps == null) return false;
@@ -4160,7 +4159,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component,
- int flags, int userId) {
+ long flags, int userId) {
final PackageSetting ps = mPackages.get(component.getPackageName());
if (ps == null) return false;
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index d54acb7..a5a8d5c 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -24,20 +24,6 @@
"name": "CtsMatchFlagTestCases"
},
{
- "name": "FrameworksServicesTests",
- "options": [
- {
- "include-filter": "com.android.server.pm."
- },
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
- },
- {
"name": "FrameworksMockingServicesTests",
"options": [
{
@@ -46,45 +32,6 @@
]
},
{
- "name": "FrameworksServicesTests",
- "file_patterns": ["(/|^)ShortcutService\\.java"],
- "options": [
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest1"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest2"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest3"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest4"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest5"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest6"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest7"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest8"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest9"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest10"
- },
- {
- "include-filter": "com.android.server.pm.ShortcutManagerTest11"
- }
- ]
- },
- {
"name": "CtsShortcutHostTestCases",
"file_patterns": ["(/|^)ShortcutService\\.java"]
},
@@ -188,47 +135,6 @@
},
{
"name": "PackageManagerServiceHostTests"
- },
- {
- "name": "FrameworksServicesTests",
- "options": [
- {
- "install-arg": "-t"
- },
- {
- "include-filter": "com.android.server.pm.UserDataPreparerTest"
- },
- {
- "include-filter": "com.android.server.pm.UserLifecycleStressTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerServiceCreateProfileTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerServiceIdRecyclingTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerServiceTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerServiceUserInfoTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerServiceUserTypeTest"
- },
- {
- "include-filter": "com.android.server.pm.UserManagerTest"
- },
- {
- "include-filter": "com.android.server.pm.UserRestrictionsUtilsTest"
- },
- {
- "include-filter": "com.android.server.pm.UserSystemPackageInstallerTest"
- },
- {
- "include-filter": "com.android.server.pm.parsing.SystemPartitionParseTest"
- }
- ]
}
],
"imports": [
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 74529c5..bc4c8b0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2408,6 +2408,14 @@
return userTypeDetails != null && canAddMoreUsersOfType(userTypeDetails);
}
+ /** Returns whether the creation of users of the given user type is enabled on this device. */
+ @Override
+ public boolean isUserTypeEnabled(String userType) {
+ checkManageOrCreateUsersPermission("check if user type is enabled.");
+ final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
+ return userTypeDetails != null && userTypeDetails.isEnabled();
+ }
+
@Override
public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
return canAddMoreProfilesToUser(UserManager.USER_TYPE_PROFILE_MANAGED, userId,
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 0ab1d36..bcb5e72 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -84,8 +84,8 @@
*/
@Nullable
public static PackageInfo generate(AndroidPackage pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
- Set<String> grantedPermissions, PackageUserState state, int userId,
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime,
+ long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId,
@Nullable PackageStateInternal pkgSetting) {
return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime,
grantedPermissions, state, userId, null, pkgSetting);
@@ -105,8 +105,8 @@
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
*/
private static PackageInfo generateWithComponents(AndroidPackage pkg, int[] gids,
- @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
- Set<String> grantedPermissions, PackageUserState state, int userId,
+ @PackageManager.PackageInfoFlags long flags, long firstInstallTime,
+ long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId,
@Nullable ApexInfo apexInfo, @Nullable PackageStateInternal pkgSetting) {
ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId,
pkgSetting);
@@ -209,7 +209,7 @@
*/
@Nullable
public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
- @PackageManager.ApplicationInfoFlags int flags, @NonNull PackageUserState state,
+ @PackageManager.ApplicationInfoFlags long flags, @NonNull PackageUserState state,
int userId, @Nullable PackageStateInternal pkgSetting) {
if (pkg == null) {
return null;
@@ -255,7 +255,7 @@
*/
@Nullable
public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
- @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
+ @PackageManager.ComponentInfoFlags long flags, PackageUserState state, int userId,
@Nullable PackageStateInternal pkgSetting) {
return generateActivityInfo(pkg, a, flags, state, null, userId, pkgSetting);
}
@@ -265,7 +265,7 @@
*/
@Nullable
private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
- @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, PackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId,
@Nullable PackageStateInternal pkgSetting) {
if (a == null) return null;
@@ -291,7 +291,7 @@
*/
@Nullable
public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
- @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
+ @PackageManager.ComponentInfoFlags long flags, PackageUserState state, int userId,
@Nullable PackageStateInternal pkgSetting) {
return generateServiceInfo(pkg, s, flags, state, null, userId, pkgSetting);
}
@@ -301,7 +301,7 @@
*/
@Nullable
private static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
- @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, PackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId,
@Nullable PackageStateInternal pkgSetting) {
if (s == null) return null;
@@ -326,7 +326,7 @@
*/
@Nullable
public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
- @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+ @PackageManager.ComponentInfoFlags long flags, PackageUserState state,
@NonNull ApplicationInfo applicationInfo, int userId,
@Nullable PackageStateInternal pkgSetting) {
if (p == null) return null;
@@ -353,7 +353,7 @@
*/
@Nullable
public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
- AndroidPackage pkg, @PackageManager.ComponentInfoFlags int flags, int userId,
+ AndroidPackage pkg, @PackageManager.ComponentInfoFlags long flags, int userId,
@Nullable PackageStateInternal pkgSetting) {
if (i == null) return null;
@@ -381,7 +381,7 @@
// PackageStateInternal os that checkUseInstalledOrHidden filter can apply
@Nullable
public static PermissionInfo generatePermissionInfo(ParsedPermission p,
- @PackageManager.ComponentInfoFlags int flags) {
+ @PackageManager.ComponentInfoFlags long flags) {
// TODO(b/135203078): Remove null checks and make all usages @NonNull
if (p == null) return null;
@@ -391,7 +391,7 @@
@Nullable
public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
- @PackageManager.ComponentInfoFlags int flags) {
+ @PackageManager.ComponentInfoFlags long flags) {
if (pg == null) return null;
// For now, permissions don't have state-adjustable fields; return directly
@@ -400,7 +400,7 @@
@Nullable
public static ArrayMap<String, ProcessInfo> generateProcessInfo(
- Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlags int flags) {
+ Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlags long flags) {
if (procs == null) {
return null;
}
@@ -423,7 +423,7 @@
*/
public static boolean checkUseInstalledOrHidden(AndroidPackage pkg,
PackageStateInternal pkgSetting, PackageUserState state,
- @PackageManager.PackageInfoFlags int flags) {
+ @PackageManager.PackageInfoFlags long flags) {
// Returns false if the package is hidden system app until installed.
if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
&& !state.isInstalled()
@@ -628,7 +628,7 @@
*/
@Nullable
public ApplicationInfo generate(AndroidPackage pkg,
- @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
+ @PackageManager.ApplicationInfoFlags long flags, PackageUserState state, int userId,
@Nullable PackageStateInternal pkgSetting) {
ApplicationInfo appInfo = mCache.get(pkg.getPackageName());
if (appInfo != null) {
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index 61fd5ee..32b1e5d 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -256,7 +256,7 @@
* Returns false iff the provided flags include the {@link PackageManager#MATCH_SYSTEM_ONLY}
* flag and the provided package is not a system package. Otherwise returns {@code true}.
*/
- public static boolean isMatchForSystemOnly(AndroidPackage pkg, int flags) {
+ public static boolean isMatchForSystemOnly(AndroidPackage pkg, long flags) {
if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
return pkg.isSystem();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
index 6744ff5..09b9d31 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java
@@ -27,7 +27,7 @@
public class PackageStateUtils {
- public static boolean isMatch(PackageState packageState, int flags) {
+ public static boolean isMatch(PackageState packageState, long flags) {
if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
return packageState.isSystem();
}
@@ -54,7 +54,7 @@
}
public static boolean isEnabledAndMatches(@Nullable PackageStateInternal packageState,
- ComponentInfo componentInfo, int flags, int userId) {
+ ComponentInfo componentInfo, long flags, int userId) {
if (packageState == null) return false;
final PackageUserState userState = packageState.getUserStateOrDefault(userId);
@@ -62,7 +62,7 @@
}
public static boolean isEnabledAndMatches(@Nullable PackageStateInternal packageState,
- @NonNull ParsedMainComponent component, int flags, int userId) {
+ @NonNull ParsedMainComponent component, long flags, int userId) {
if (packageState == null) {
return false;
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 1f024ea..471f38a 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -391,7 +391,7 @@
*/
@ApprovalLevel
int approvalLevelForDomain(@NonNull PackageStateInternal pkgSetting, @NonNull Intent intent,
- @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId);
+ @PackageManager.ResolveInfoFlags long resolveInfoFlags, @UserIdInt int userId);
/**
* @return the domain verification set ID for the given package, or null if the ID is
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 0fb8475..661e67d 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -1721,7 +1721,7 @@
@Override
public int approvalLevelForDomain(@NonNull PackageStateInternal pkgSetting,
- @NonNull Intent intent, @PackageManager.ResolveInfoFlags int resolveInfoFlags,
+ @NonNull Intent intent, @PackageManager.ResolveInfoFlags long resolveInfoFlags,
@UserIdInt int userId) {
String packageName = pkgSetting.getPackageName();
if (!DomainVerificationUtils.isDomainVerificationIntent(intent, resolveInfoFlags)) {
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
index 246810f..12cce0d 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationUtils.java
@@ -49,7 +49,7 @@
}
public static boolean isDomainVerificationIntent(Intent intent,
- @PackageManager.ResolveInfoFlags int resolveInfoFlags) {
+ @PackageManager.ResolveInfoFlags long resolveInfoFlags) {
if (!intent.isWebIntent()) {
return false;
}
diff --git a/services/core/java/com/android/server/security/AttestationVerificationManagerService.java b/services/core/java/com/android/server/security/AttestationVerificationManagerService.java
new file mode 100644
index 0000000..f519ced
--- /dev/null
+++ b/services/core/java/com/android/server/security/AttestationVerificationManagerService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+import static android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelDuration;
+import android.os.RemoteException;
+import android.security.attestationverification.AttestationProfile;
+import android.security.attestationverification.IAttestationVerificationManagerService;
+import android.security.attestationverification.IVerificationResult;
+import android.security.attestationverification.VerificationToken;
+import android.util.ExceptionUtils;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.server.SystemService;
+
+/**
+ * A {@link SystemService} which provides functionality related to verifying attestations of
+ * (usually) remote computing environments.
+ *
+ * @hide
+ */
+public class AttestationVerificationManagerService extends SystemService {
+
+ private static final String TAG = "AVF";
+
+ public AttestationVerificationManagerService(final Context context) {
+ super(context);
+ }
+
+ private final IBinder mService = new IAttestationVerificationManagerService.Stub() {
+ @Override
+ public void verifyAttestation(
+ AttestationProfile profile,
+ int localBindingType,
+ Bundle requirements,
+ byte[] attestation,
+ AndroidFuture resultCallback) throws RemoteException {
+ try {
+ Slog.d(TAG, "verifyAttestation");
+ verifyAttestationForAllVerifiers(profile, localBindingType, requirements,
+ attestation, resultCallback);
+ } catch (Throwable t) {
+ Slog.e(TAG, "failed to verify attestation", t);
+ throw ExceptionUtils.propagate(t, RemoteException.class);
+ }
+ }
+
+ @Override
+ public void verifyToken(VerificationToken token, ParcelDuration parcelDuration,
+ AndroidFuture resultCallback) throws RemoteException {
+ // TODO(b/201696614): Implement
+ resultCallback.complete(RESULT_UNKNOWN);
+ }
+ };
+
+ private void verifyAttestationForAllVerifiers(
+ AttestationProfile profile, int localBindingType, Bundle requirements,
+ byte[] attestation, AndroidFuture<IVerificationResult> resultCallback) {
+ // TODO(b/201696614): Implement
+ IVerificationResult result = new IVerificationResult();
+ result.resultCode = RESULT_UNKNOWN;
+ result.token = null;
+ resultCallback.complete(result);
+ }
+
+ @Override
+ public void onStart() {
+ Slog.d(TAG, "Started");
+ publishBinderService(Context.ATTESTATION_VERIFICATION_SERVICE, mService);
+ }
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 3182290..eb69ff7 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -64,6 +64,8 @@
import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static libcore.io.IoUtils.closeQuietly;
+
import static java.lang.Math.min;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
@@ -222,6 +224,7 @@
import org.json.JSONException;
import org.json.JSONObject;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -3413,9 +3416,12 @@
metricsState.getGeoDetectionEnabledSetting(),
convertToMetricsDetectionMode(metricsState.getDetectionMode()),
metricsState.getDeviceTimeZoneIdOrdinal(),
- metricsState.getLatestManualSuggestionProtoBytes(),
- metricsState.getLatestTelephonySuggestionProtoBytes(),
- metricsState.getLatestGeolocationSuggestionProtoBytes()
+ convertTimeZoneSuggestionToProtoBytes(
+ metricsState.getLatestManualSuggestion()),
+ convertTimeZoneSuggestionToProtoBytes(
+ metricsState.getLatestTelephonySuggestion()),
+ convertTimeZoneSuggestionToProtoBytes(
+ metricsState.getLatestGeolocationSuggestion())
));
} catch (RuntimeException e) {
Slog.e(TAG, "Getting time zone detection state failed: ", e);
@@ -3426,7 +3432,8 @@
return StatsManager.PULL_SUCCESS;
}
- private int convertToMetricsDetectionMode(int detectionMode) {
+ private static int convertToMetricsDetectionMode(
+ @MetricsTimeZoneDetectorState.DetectionMode int detectionMode) {
switch (detectionMode) {
case MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL:
return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
@@ -3439,6 +3446,34 @@
}
}
+ @Nullable
+ private static byte[] convertTimeZoneSuggestionToProtoBytes(
+ @Nullable MetricsTimeZoneDetectorState.MetricsTimeZoneSuggestion suggestion) {
+ if (suggestion == null) {
+ return null;
+ }
+
+ // We don't get access to the atoms.proto definition for nested proto fields, so we use
+ // an identically specified proto.
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
+ int typeProtoValue = suggestion.isCertain()
+ ? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
+ : android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
+ protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
+ typeProtoValue);
+ if (suggestion.isCertain()) {
+ for (int zoneIdOrdinal : suggestion.getZoneIdOrdinals()) {
+ protoOutputStream.write(
+ android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
+ zoneIdOrdinal);
+ }
+ }
+ protoOutputStream.flush();
+ closeQuietly(byteArrayOutputStream);
+ return byteArrayOutputStream.toByteArray();
+ }
+
private void registerExternalStorageInfo() {
int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO;
mStatsManager.setPullAtomCallback(
diff --git a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
index 0c20586..f156f8c 100644
--- a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
+++ b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
@@ -16,16 +16,12 @@
package com.android.server.timezonedetector;
-import static libcore.io.IoUtils.closeQuietly;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.util.proto.ProtoOutputStream;
-import java.io.ByteArrayOutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -50,7 +46,7 @@
value = { DETECTION_MODE_MANUAL, DETECTION_MODE_GEO, DETECTION_MODE_TELEPHONY})
@Retention(RetentionPolicy.SOURCE)
@Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
- @interface DetectionMode {};
+ public @interface DetectionMode {};
public static final @DetectionMode int DETECTION_MODE_MANUAL = 0;
public static final @DetectionMode int DETECTION_MODE_GEO = 1;
@@ -89,16 +85,16 @@
int deviceTimeZoneIdOrdinal =
tzIdOrdinalGenerator.ordinal(Objects.requireNonNull(deviceTimeZoneId));
- MetricsTimeZoneSuggestion latestObfuscatedManualSuggestion =
+ MetricsTimeZoneSuggestion latestCanonicalManualSuggestion =
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestManualSuggestion);
- MetricsTimeZoneSuggestion latestObfuscatedTelephonySuggestion =
+ MetricsTimeZoneSuggestion latestCanonicalTelephonySuggestion =
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestTelephonySuggestion);
- MetricsTimeZoneSuggestion latestObfuscatedGeolocationSuggestion =
+ MetricsTimeZoneSuggestion latestCanonicalGeolocationSuggestion =
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestGeolocationSuggestion);
return new MetricsTimeZoneDetectorState(
- configurationInternal, deviceTimeZoneIdOrdinal, latestObfuscatedManualSuggestion,
- latestObfuscatedTelephonySuggestion, latestObfuscatedGeolocationSuggestion);
+ configurationInternal, deviceTimeZoneIdOrdinal, latestCanonicalManualSuggestion,
+ latestCanonicalTelephonySuggestion, latestCanonicalGeolocationSuggestion);
}
/** Returns true if the device supports telephony time zone detection. */
@@ -154,30 +150,27 @@
}
/**
- * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last manual
- * suggestion received.
+ * Returns a canonical form of the last manual suggestion received.
*/
@Nullable
- public byte[] getLatestManualSuggestionProtoBytes() {
- return suggestionProtoBytes(mLatestManualSuggestion);
+ public MetricsTimeZoneSuggestion getLatestManualSuggestion() {
+ return mLatestManualSuggestion;
}
/**
- * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last, best
- * telephony suggestion received.
+ * Returns a canonical form of the last telephony suggestion received.
*/
@Nullable
- public byte[] getLatestTelephonySuggestionProtoBytes() {
- return suggestionProtoBytes(mLatestTelephonySuggestion);
+ public MetricsTimeZoneSuggestion getLatestTelephonySuggestion() {
+ return mLatestTelephonySuggestion;
}
/**
- * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last geolocation
- * suggestion received.
+ * Returns a canonical form of last geolocation suggestion received.
*/
@Nullable
- public byte[] getLatestGeolocationSuggestionProtoBytes() {
- return suggestionProtoBytes(mLatestGeolocationSuggestion);
+ public MetricsTimeZoneSuggestion getLatestGeolocationSuggestion() {
+ return mLatestGeolocationSuggestion;
}
@Override
@@ -213,14 +206,6 @@
+ '}';
}
- private static byte[] suggestionProtoBytes(
- @Nullable MetricsTimeZoneSuggestion suggestion) {
- if (suggestion == null) {
- return null;
- }
- return suggestion.toBytes();
- }
-
@Nullable
private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion(
@NonNull OrdinalGenerator<String> zoneIdOrdinalGenerator,
@@ -264,10 +249,11 @@
}
/**
- * A Java class that closely matches the android.app.time.MetricsTimeZoneSuggestion
- * proto definition.
+ * A Java class that represents a generic time zone suggestion, i.e. one that is independent of
+ * origin-specific information. This closely matches the metrics atoms.proto
+ * MetricsTimeZoneSuggestion proto definition.
*/
- private static final class MetricsTimeZoneSuggestion {
+ public static final class MetricsTimeZoneSuggestion {
@Nullable
private final int[] mZoneIdOrdinals;
@@ -281,42 +267,20 @@
}
@NonNull
- public static MetricsTimeZoneSuggestion createCertain(
+ static MetricsTimeZoneSuggestion createCertain(
@NonNull int[] zoneIdOrdinals) {
return new MetricsTimeZoneSuggestion(zoneIdOrdinals);
}
- boolean isCertain() {
+ public boolean isCertain() {
return mZoneIdOrdinals != null;
}
@Nullable
- int[] getZoneIdOrdinals() {
+ public int[] getZoneIdOrdinals() {
return mZoneIdOrdinals;
}
- byte[] toBytes() {
- // We don't get access to the atoms.proto definition for nested proto fields, so we use
- // an identically specified proto.
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
- int typeProtoValue = isCertain()
- ? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
- : android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
- protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
- typeProtoValue);
- if (isCertain()) {
- for (int zoneIdOrdinal : getZoneIdOrdinals()) {
- protoOutputStream.write(
- android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
- zoneIdOrdinal);
- }
- }
- protoOutputStream.flush();
- closeQuietly(byteArrayOutputStream);
- return byteArrayOutputStream.toByteArray();
- }
-
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
index 984b9ba..692b0cc 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -172,12 +172,13 @@
* Enables/disables the state recording mode for tests. The value is reset with {@link
* #resetVolatileTestConfig()}.
*/
- void setRecordProviderStateChanges(boolean enabled);
+ void setRecordStateChangesForTests(boolean enabled);
/**
- * Returns {@code true} if providers are expected to record their state changes for tests.
+ * Returns {@code true} if the controller / providers are expected to record their state changes
+ * for tests.
*/
- boolean getRecordProviderStateChanges();
+ boolean getRecordStateChangesForTests();
/**
* Returns the mode for the primary location time zone provider.
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
index b9885d2..02ea433 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
@@ -150,7 +150,7 @@
* See also {@link #resetVolatileTestConfig()}.
*/
@GuardedBy("this")
- private boolean mRecordProviderStateChanges;
+ private boolean mRecordStateChangesForTests;
private ServiceConfigAccessorImpl(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
@@ -453,13 +453,13 @@
}
@Override
- public synchronized void setRecordProviderStateChanges(boolean enabled) {
- mRecordProviderStateChanges = enabled;
+ public synchronized void setRecordStateChangesForTests(boolean enabled) {
+ mRecordStateChangesForTests = enabled;
}
@Override
- public synchronized boolean getRecordProviderStateChanges() {
- return mRecordProviderStateChanges;
+ public synchronized boolean getRecordStateChangesForTests() {
+ return mRecordStateChangesForTests;
}
@Override
@@ -548,7 +548,7 @@
mTestPrimaryLocationTimeZoneProviderMode = null;
mTestSecondaryLocationTimeZoneProviderPackageName = null;
mTestSecondaryLocationTimeZoneProviderMode = null;
- mRecordProviderStateChanges = false;
+ mRecordStateChangesForTests = false;
}
private boolean isTelephonyFallbackSupported() {
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index af8cf6e..b23f11a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -247,8 +247,7 @@
* completion, it cannot be called from the {@code mThreadingDomain} thread.
*/
void startWithTestProviders(@Nullable String testPrimaryProviderPackageName,
- @Nullable String testSecondaryProviderPackageName,
- boolean recordProviderStateChanges) {
+ @Nullable String testSecondaryProviderPackageName, boolean recordStateChanges) {
enforceManageTimeZoneDetectorPermission();
if (testPrimaryProviderPackageName == null && testSecondaryProviderPackageName == null) {
@@ -263,7 +262,7 @@
testPrimaryProviderPackageName);
mServiceConfigAccessor.setTestSecondaryLocationTimeZoneProviderPackageName(
testSecondaryProviderPackageName);
- mServiceConfigAccessor.setRecordProviderStateChanges(recordProviderStateChanges);
+ mServiceConfigAccessor.setRecordStateChangesForTests(recordStateChanges);
startOnDomainThread();
}
}, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -281,10 +280,20 @@
if (mLocationTimeZoneProviderController == null) {
LocationTimeZoneProvider primary = mPrimaryProviderConfig.createProvider();
LocationTimeZoneProvider secondary = mSecondaryProviderConfig.createProvider();
+ LocationTimeZoneProviderController.MetricsLogger metricsLogger =
+ new LocationTimeZoneProviderController.MetricsLogger() {
+ @Override
+ public void onStateChange(
+ @LocationTimeZoneProviderController.State String state) {
+ // TODO b/200279201 - wire this up to metrics code
+ // No-op.
+ }
+ };
+ boolean recordStateChanges = mServiceConfigAccessor.getRecordStateChangesForTests();
LocationTimeZoneProviderController controller =
- new LocationTimeZoneProviderController(
- mThreadingDomain, primary, secondary);
+ new LocationTimeZoneProviderController(mThreadingDomain, metricsLogger,
+ primary, secondary, recordStateChanges);
LocationTimeZoneProviderControllerEnvironmentImpl environment =
new LocationTimeZoneProviderControllerEnvironmentImpl(
mThreadingDomain, mServiceConfigAccessor, controller);
@@ -342,7 +351,7 @@
mThreadingDomain.postAndWait(() -> {
synchronized (mSharedLock) {
if (mLocationTimeZoneProviderController != null) {
- mLocationTimeZoneProviderController.clearRecordedProviderStates();
+ mLocationTimeZoneProviderController.clearRecordedStates();
}
}
}, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -450,7 +459,7 @@
ProviderMetricsLogger providerMetricsLogger = new RealProviderMetricsLogger(mIndex);
return new BinderLocationTimeZoneProvider(
providerMetricsLogger, mThreadingDomain, mName, proxy,
- mServiceConfigAccessor.getRecordProviderStateChanges());
+ mServiceConfigAccessor.getRecordStateChangesForTests());
}
@Override
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
index 113926a..1f752f4 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
@@ -21,6 +21,7 @@
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
import java.util.ArrayList;
import java.util.Collections;
@@ -30,22 +31,35 @@
/** A snapshot of the location time zone manager service's state for tests. */
final class LocationTimeZoneManagerServiceState {
+ private final @State String mControllerState;
@Nullable private final GeolocationTimeZoneSuggestion mLastSuggestion;
+ @NonNull private final List<@State String> mControllerStates;
@NonNull private final List<ProviderState> mPrimaryProviderStates;
@NonNull private final List<ProviderState> mSecondaryProviderStates;
LocationTimeZoneManagerServiceState(@NonNull Builder builder) {
+ mControllerState = builder.mControllerState;
mLastSuggestion = builder.mLastSuggestion;
+ mControllerStates = Objects.requireNonNull(builder.mControllerStates);
mPrimaryProviderStates = Objects.requireNonNull(builder.mPrimaryProviderStates);
mSecondaryProviderStates = Objects.requireNonNull(builder.mSecondaryProviderStates);
}
+ public @State String getControllerState() {
+ return mControllerState;
+ }
+
@Nullable
public GeolocationTimeZoneSuggestion getLastSuggestion() {
return mLastSuggestion;
}
@NonNull
+ public List<@State String> getControllerStates() {
+ return mControllerStates;
+ }
+
+ @NonNull
public List<ProviderState> getPrimaryProviderStates() {
return Collections.unmodifiableList(mPrimaryProviderStates);
}
@@ -58,7 +72,9 @@
@Override
public String toString() {
return "LocationTimeZoneManagerServiceState{"
- + "mLastSuggestion=" + mLastSuggestion
+ + "mControllerState=" + mControllerState
+ + ", mLastSuggestion=" + mLastSuggestion
+ + ", mControllerStates=" + mControllerStates
+ ", mPrimaryProviderStates=" + mPrimaryProviderStates
+ ", mSecondaryProviderStates=" + mSecondaryProviderStates
+ '}';
@@ -66,17 +82,31 @@
static final class Builder {
+ private @State String mControllerState;
private GeolocationTimeZoneSuggestion mLastSuggestion;
+ private List<@State String> mControllerStates;
private List<ProviderState> mPrimaryProviderStates;
private List<ProviderState> mSecondaryProviderStates;
@NonNull
+ public Builder setControllerState(@State String stateEnum) {
+ mControllerState = stateEnum;
+ return this;
+ }
+
+ @NonNull
Builder setLastSuggestion(@NonNull GeolocationTimeZoneSuggestion lastSuggestion) {
mLastSuggestion = Objects.requireNonNull(lastSuggestion);
return this;
}
@NonNull
+ public Builder setStateChanges(@NonNull List<@State String> states) {
+ mControllerStates = new ArrayList<>(states);
+ return this;
+ }
+
+ @NonNull
Builder setPrimaryProviderStateChanges(@NonNull List<ProviderState> primaryProviderStates) {
mPrimaryProviderStates = new ArrayList<>(primaryProviderStates);
return this;
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
index 6c9e174..60bbea7 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
@@ -40,6 +40,14 @@
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_UNKNOWN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_PROVIDERS_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -55,6 +63,7 @@
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -245,6 +254,7 @@
outputStream.end(lastSuggestionToken);
}
+ writeControllerStates(outputStream, state.getControllerStates());
writeProviderStates(outputStream, state.getPrimaryProviderStates(),
"primary_provider_states",
LocationTimeZoneManagerServiceStateProto.PRIMARY_PROVIDER_STATES);
@@ -256,6 +266,37 @@
return 0;
}
+ private static void writeControllerStates(DualDumpOutputStream outputStream,
+ List<@State String> states) {
+ for (@State String state : states) {
+ outputStream.write("controller_states",
+ LocationTimeZoneManagerServiceStateProto.CONTROLLER_STATES,
+ convertControllerStateToProtoEnum(state));
+ }
+ }
+
+ private static int convertControllerStateToProtoEnum(@State String state) {
+ switch (state) {
+ case STATE_PROVIDERS_INITIALIZING:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_PROVIDERS_INITIALIZING;
+ case STATE_STOPPED:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_STOPPED;
+ case STATE_INITIALIZING:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_INITIALIZING;
+ case STATE_UNCERTAIN:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_UNCERTAIN;
+ case STATE_CERTAIN:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_CERTAIN;
+ case STATE_FAILED:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_FAILED;
+ case STATE_DESTROYED:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_DESTROYED;
+ case STATE_UNKNOWN:
+ default:
+ return LocationTimeZoneManagerProto.CONTROLLER_STATE_UNKNOWN;
+ }
+ }
+
private static void writeProviderStates(DualDumpOutputStream outputStream,
List<LocationTimeZoneProvider.ProviderState> providerStates, String fieldName,
long fieldId) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
index dbd3877..5d7730a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -34,6 +34,7 @@
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringDef;
import android.service.timezone.TimeZoneProviderEvent;
import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
@@ -43,9 +44,15 @@
import com.android.server.timezonedetector.ConfigurationInternal;
import com.android.server.timezonedetector.Dumpable;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
+import com.android.server.timezonedetector.ReferenceWithHistory;
import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -93,6 +100,36 @@
*/
class LocationTimeZoneProviderController implements Dumpable {
+ // String is used for easier logging / interpretation in bug reports Vs int.
+ @StringDef(prefix = "STATE_",
+ value = { STATE_UNKNOWN, STATE_PROVIDERS_INITIALIZING, STATE_STOPPED,
+ STATE_INITIALIZING, STATE_UNCERTAIN, STATE_CERTAIN, STATE_FAILED,
+ STATE_DESTROYED })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+ @interface State {}
+
+ /** The state used for an uninitialized controller. */
+ static final @State String STATE_UNKNOWN = "UNKNOWN";
+
+ /**
+ * A state used while the location time zone providers are initializing. Enables detection
+ * / avoidance of unwanted fail-over behavior before both providers are initialized.
+ */
+ static final @State String STATE_PROVIDERS_INITIALIZING = "PROVIDERS_INITIALIZING";
+ /** An inactive state: Detection is disabled. */
+ static final @State String STATE_STOPPED = "STOPPED";
+ /** An active state: No suggestion has yet been made. */
+ static final @State String STATE_INITIALIZING = "INITIALIZING";
+ /** An active state: The last suggestion was "uncertain". */
+ static final @State String STATE_UNCERTAIN = "UNCERTAIN";
+ /** An active state: The last suggestion was "certain". */
+ static final @State String STATE_CERTAIN = "CERTAIN";
+ /** An inactive state: The location time zone providers have failed. */
+ static final @State String STATE_FAILED = "FAILED";
+ /** An inactive state: The controller is destroyed. */
+ static final @State String STATE_DESTROYED = "DESTROYED";
+
@NonNull private final ThreadingDomain mThreadingDomain;
@NonNull private final Object mSharedLock;
/**
@@ -102,6 +139,7 @@
*/
@NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
+ @NonNull private final MetricsLogger mMetricsLogger;
@NonNull private final LocationTimeZoneProvider mPrimaryProvider;
@NonNull private final LocationTimeZoneProvider mSecondaryProvider;
@@ -117,10 +155,22 @@
// Non-null after initialize()
private Callback mCallback;
- /** Indicates both providers have completed initialization. */
- @GuardedBy("mSharedLock")
- private boolean mProvidersInitialized;
+ /** Usually {@code false} but can be set to {@code true} to record state changes for testing. */
+ private final boolean mRecordStateChanges;
+ @GuardedBy("mSharedLock")
+ @NonNull
+ private final ArrayList<@State String> mRecordedStates = new ArrayList<>(0);
+
+ /**
+ * The current state. This is primarily for metrics / reporting of how long the controller
+ * spends active / inactive during a period. There is overlap with the provider states, but
+ * providers operate independently of each other, so this can help to understand how long the
+ * geo detection system overall was certain or uncertain when multiple providers might have been
+ * enabled concurrently.
+ */
+ @GuardedBy("mSharedLock")
+ private final ReferenceWithHistory<@State String> mState = new ReferenceWithHistory<>(10);
/** Contains the last suggestion actually made, if there is one. */
@GuardedBy("mSharedLock")
@@ -128,13 +178,21 @@
private GeolocationTimeZoneSuggestion mLastSuggestion;
LocationTimeZoneProviderController(@NonNull ThreadingDomain threadingDomain,
+ @NonNull MetricsLogger metricsLogger,
@NonNull LocationTimeZoneProvider primaryProvider,
- @NonNull LocationTimeZoneProvider secondaryProvider) {
+ @NonNull LocationTimeZoneProvider secondaryProvider,
+ boolean recordStateChanges) {
mThreadingDomain = Objects.requireNonNull(threadingDomain);
mSharedLock = threadingDomain.getLockObject();
mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
+ mMetricsLogger = Objects.requireNonNull(metricsLogger);
mPrimaryProvider = Objects.requireNonNull(primaryProvider);
mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
+ mRecordStateChanges = recordStateChanges;
+
+ synchronized (mSharedLock) {
+ mState.set(STATE_UNKNOWN);
+ }
}
/**
@@ -152,9 +210,10 @@
LocationTimeZoneProvider.ProviderListener providerListener =
LocationTimeZoneProviderController.this::onProviderStateChange;
+ setState(STATE_PROVIDERS_INITIALIZING);
mPrimaryProvider.initialize(providerListener);
mSecondaryProvider.initialize(providerListener);
- mProvidersInitialized = true;
+ setState(STATE_STOPPED);
alterProvidersStartedStateIfRequired(
null /* oldConfiguration */, mCurrentUserConfiguration);
@@ -209,8 +268,26 @@
synchronized (mSharedLock) {
stopProviders();
+
+ // Enter destroyed state.
mPrimaryProvider.destroy();
mSecondaryProvider.destroy();
+ setState(STATE_DESTROYED);
+ }
+ }
+
+ /**
+ * Updates {@link #mState} if needed, and performs all the record-keeping / callbacks associated
+ * with state changes.
+ */
+ @GuardedBy("mSharedLock")
+ private void setState(@State String state) {
+ if (!Objects.equals(mState.get(), state)) {
+ mState.set(state);
+ if (mRecordStateChanges) {
+ mRecordedStates.add(state);
+ }
+ mMetricsLogger.onStateChange(state);
}
}
@@ -226,11 +303,12 @@
// suggestion must now be made to indicate the controller {does not / no longer has}
// an opinion and will not be sending further updates (until at least the providers are
// re-started).
- if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
+ if (Objects.equals(mState.get(), STATE_CERTAIN)) {
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
- makeSuggestion(suggestion);
+ makeSuggestion(suggestion, STATE_UNCERTAIN);
}
+ setState(STATE_STOPPED);
}
@GuardedBy("mSharedLock")
@@ -300,6 +378,8 @@
// timeout started when the primary entered {started uncertain} should be cancelled.
if (newGeoDetectionEnabled) {
+ setState(STATE_INITIALIZING);
+
// Try to start the primary provider.
tryStartProvider(mPrimaryProvider, newConfiguration);
@@ -314,13 +394,13 @@
ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
if (!newSecondaryState.isStarted()) {
// If both providers are {perm failed} then the controller immediately
- // becomes uncertain.
+ // reports uncertain.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
mEnvironment.elapsedRealtimeMillis(),
"Providers are failed:"
+ " primary=" + mPrimaryProvider.getCurrentState()
+ " secondary=" + mPrimaryProvider.getCurrentState());
- makeSuggestion(suggestion);
+ makeSuggestion(suggestion, STATE_FAILED);
}
}
} else {
@@ -368,7 +448,7 @@
// Ignore provider state changes during initialization. e.g. if the primary provider
// moves to PROVIDER_STATE_PERM_FAILED during initialization, the secondary will not
// be ready to take over yet.
- if (!mProvidersInitialized) {
+ if (Objects.equals(mState.get(), STATE_PROVIDERS_INITIALIZING)) {
warnLog("onProviderStateChange: Ignoring provider state change because both"
+ " providers have not yet completed initialization."
+ " providerState=" + providerState);
@@ -453,13 +533,13 @@
cancelUncertaintyTimeout();
// If both providers are now terminated, then a suggestion must be sent informing the
- // time zone detector that there are no further updates coming in future.
+ // time zone detector that there are no further updates coming in the future.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
mEnvironment.elapsedRealtimeMillis(),
"Both providers are terminated:"
+ " primary=" + primaryCurrentState.provider
+ ", secondary=" + secondaryCurrentState.provider);
- makeSuggestion(suggestion);
+ makeSuggestion(suggestion, STATE_FAILED);
}
}
@@ -548,7 +628,7 @@
+ ", providerEvent=" + providerEvent
+ ", suggestionCreationTime=" + mEnvironment.elapsedRealtimeMillis();
geoSuggestion.addDebugInfo(debugInfo);
- makeSuggestion(geoSuggestion);
+ makeSuggestion(geoSuggestion, STATE_CERTAIN);
}
@Override
@@ -563,8 +643,14 @@
ipw.println("providerInitializationTimeoutFuzz="
+ mEnvironment.getProviderInitializationTimeoutFuzz());
ipw.println("uncertaintyDelay=" + mEnvironment.getUncertaintyDelay());
+ ipw.println("mState=" + mState.get());
ipw.println("mLastSuggestion=" + mLastSuggestion);
+ ipw.println("State history:");
+ ipw.increaseIndent(); // level 2
+ mState.dump(ipw);
+ ipw.decreaseIndent(); // level 2
+
ipw.println("Primary Provider:");
ipw.increaseIndent(); // level 2
mPrimaryProvider.dump(ipw, args);
@@ -579,12 +665,17 @@
}
}
- /** Sends an immediate suggestion, updating mLastSuggestion. */
+ /**
+ * Sends an immediate suggestion and enters a new state if needed. This method updates
+ * mLastSuggestion and changes mStateEnum / reports the new state for metrics.
+ */
@GuardedBy("mSharedLock")
- private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion) {
+ private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion,
+ @State String newState) {
debugLog("makeSuggestion: suggestion=" + suggestion);
mCallback.suggest(suggestion);
mLastSuggestion = suggestion;
+ setState(newState);
}
/** Clears the uncertainty timeout. */
@@ -604,7 +695,7 @@
* <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
* triggered later if nothing else preempts it. It can be preempted if the provider becomes
* certain (or does anything else that calls {@link
- * #makeSuggestion(GeolocationTimeZoneSuggestion)}) within {@link
+ * #makeSuggestion(GeolocationTimeZoneSuggestion, String)}) within {@link
* Environment#getUncertaintyDelay()}. Preemption causes the scheduled
* "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
* within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
@@ -666,7 +757,7 @@
+ Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
+ ", uncertaintyDelay=" + uncertaintyDelay
);
- makeSuggestion(suggestion);
+ makeSuggestion(suggestion, STATE_UNCERTAIN);
}
}
@@ -682,12 +773,13 @@
}
/**
- * Clears recorded provider state changes (for use during tests).
+ * Clears recorded controller and provider state changes (for use during tests).
*/
- void clearRecordedProviderStates() {
+ void clearRecordedStates() {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
+ mRecordedStates.clear();
mPrimaryProvider.clearRecordedStates();
mSecondaryProvider.clearRecordedStates();
}
@@ -706,7 +798,9 @@
if (mLastSuggestion != null) {
builder.setLastSuggestion(mLastSuggestion);
}
- builder.setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
+ builder.setControllerState(mState.get())
+ .setStateChanges(mRecordedStates)
+ .setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
.setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
return builder.build();
}
@@ -782,4 +876,12 @@
*/
abstract void suggest(@NonNull GeolocationTimeZoneSuggestion suggestion);
}
+
+ /**
+ * Used by {@link LocationTimeZoneProviderController} to record events for metrics / telemetry.
+ */
+ interface MetricsLogger {
+ /** Called when the controller's state changes. */
+ void onStateChange(@State String stateEnum);
+ }
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 5d40c23..9717201 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -341,7 +341,7 @@
if (!isEffectValid(effect)) {
return false;
}
- attrs = fixupVibrationAttributes(attrs);
+ attrs = fixupVibrationAttributes(attrs, effect);
synchronized (mLock) {
SparseArray<PrebakedSegment> effects = fixupAlwaysOnEffectsLocked(effect);
if (effects == null) {
@@ -385,7 +385,7 @@
if (!isEffectValid(effect)) {
return null;
}
- attrs = fixupVibrationAttributes(attrs);
+ attrs = fixupVibrationAttributes(attrs, effect);
Vibration vib = new Vibration(token, mNextVibrationId.getAndIncrement(), effect, attrs,
uid, opPkg, reason);
fillVibrationFallbacks(vib, effect);
@@ -895,21 +895,32 @@
* Return new {@link VibrationAttributes} that only applies flags that this user has permissions
* to use.
*/
- private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs) {
+ @NonNull
+ private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs,
+ CombinedVibration effect) {
if (attrs == null) {
attrs = DEFAULT_ATTRIBUTES;
}
+ int usage = attrs.getUsage();
+ if ((usage == VibrationAttributes.USAGE_UNKNOWN) && effect.isHapticFeedbackCandidate()) {
+ usage = VibrationAttributes.USAGE_TOUCH;
+ }
+ int flags = attrs.getFlags();
if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
|| hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
|| hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
- final int flags = attrs.getFlags()
- & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
- attrs = new VibrationAttributes.Builder(attrs)
- .setFlags(flags, attrs.getFlags()).build();
+ // Remove bypass policy flag from attributes if the app does not have permissions.
+ flags &= ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
}
}
- return attrs;
+ if ((usage == attrs.getUsage()) && (flags == attrs.getFlags())) {
+ return attrs;
+ }
+ return new VibrationAttributes.Builder(attrs)
+ .setUsage(usage)
+ .setFlags(flags, attrs.getFlags())
+ .build();
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 73a783e..bb7434d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2784,8 +2784,8 @@
// If it exist, we need to reparent target root task from TDA to launch root task.
final TaskDisplayArea tda = mTargetRootTask.getDisplayArea();
final Task launchRootTask = tda.getLaunchRootTask(mTargetRootTask.getWindowingMode(),
- mTargetRootTask.getActivityType(), null /** options */,
- mSourceRootTask, 0 /** launchFlags */);
+ mTargetRootTask.getActivityType(), null /** options */, mSourceRootTask,
+ mLaunchFlags);
// If target root task is created by organizer, let organizer handle reparent itself.
if (!mTargetRootTask.mCreatedByOrganizer && launchRootTask != null
&& launchRootTask != mTargetRootTask) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ede408..a72cf3a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -176,6 +176,7 @@
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.role.RoleServicePlatformHelper;
import com.android.server.rotationresolver.RotationResolverManagerService;
+import com.android.server.security.AttestationVerificationManagerService;
import com.android.server.security.FileIntegrityService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
@@ -2339,6 +2340,10 @@
t.traceEnd();
}
+ t.traceBegin("StartAttestationVerificationService");
+ mSystemServiceManager.startService(AttestationVerificationManagerService.class);
+ t.traceEnd();
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
t.traceBegin("StartCompanionDeviceManager");
mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index adf892a..5dc048b 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
@@ -150,7 +151,7 @@
PackageInfo packageInfo, @UserIdInt int userId, int uid) {
when(mPackageManagerInternal.getPackageInfo(
eq(CROSS_PROFILE_APP_PACKAGE_NAME),
- /* flags= */ anyInt(),
+ /* flags= */ anyLong(),
/* filterCallingUid= */ anyInt(),
eq(userId)))
.thenReturn(packageInfo);
@@ -469,7 +470,7 @@
private void mockUninstallCrossProfileAppFromWorkProfile() {
when(mPackageManagerInternal.getPackageInfo(
eq(CROSS_PROFILE_APP_PACKAGE_NAME),
- /* flags= */ anyInt(),
+ /* flags= */ anyLong(),
/* filterCallingUid= */ anyInt(),
eq(WORK_PROFILE_USER_ID)))
.thenReturn(null);
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationValidIntentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationValidIntentTest.kt
index 98634b2..ac6b679 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationValidIntentTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationValidIntentTest.kt
@@ -120,7 +120,7 @@
@Test
fun verify() {
val flags = if (params.matchDefaultOnly) PackageManager.MATCH_DEFAULT_ONLY else 0
- assertThat(DomainVerificationUtils.isDomainVerificationIntent(params.intent, flags))
- .isEqualTo(params.expected)
+ assertThat(DomainVerificationUtils.isDomainVerificationIntent(params.intent,
+ flags.toLong())).isEqualTo(params.expected)
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index a9099ae..5885470 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -2961,7 +2961,7 @@
private void registerAppIds(String[] packages, Integer[] ids) {
assertEquals(packages.length, ids.length);
- when(mPackageManagerInternal.getPackageUid(anyString(), anyInt(), anyInt())).thenAnswer(
+ when(mPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt())).thenAnswer(
invocation -> {
final String pkg = invocation.getArgument(0);
final int index = ArrayUtils.indexOf(packages, pkg);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
index b2847ce..783971a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -80,7 +81,7 @@
doReturn(mActivityManagerInternal).when(
() -> LocalServices.getService(ActivityManagerInternal.class));
doReturn(mIPackageManager).when(() -> AppGlobals.getPackageManager());
- when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyInt(), anyInt())).thenReturn(
+ when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyLong(), anyInt())).thenReturn(
TEST_CALLING_UID);
ActivityManagerConstants constants = mock(ActivityManagerConstants.class);
constants.PENDINGINTENT_WARNING_THRESHOLD = 2000;
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
index e2e7f5d..94dcdf9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
@@ -58,72 +58,86 @@
@Test
public void testLocationMonitoring() {
CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null);
- Object key1 = new Object();
- Object key2 = new Object();
CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null);
- Object key3 = new Object();
- Object key4 = new Object();
- mHelper.reportLocationStart(caller1, "gps", key1);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
+ mHelper.reportLocationStart(caller1);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller1));
- mHelper.reportLocationStart(caller1, "gps", key2);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
+ mHelper.reportLocationStart(caller1);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller1));
- mHelper.reportLocationStart(caller2, "gps", key3);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
+ mHelper.reportLocationStart(caller2);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller2));
- mHelper.reportLocationStart(caller2, "gps", key4);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
+ mHelper.reportLocationStart(caller2);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller2));
- mHelper.reportLocationStop(caller1, "gps", key2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
- mHelper.reportLocationStop(caller1, "gps", key1);
- verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller1);
+ mHelper.reportLocationStop(caller1);
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ mHelper.reportLocationStop(caller1);
+ verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller1));
- mHelper.reportLocationStop(caller2, "gps", key3);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
- mHelper.reportLocationStop(caller2, "gps", key4);
- verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller2);
+ mHelper.reportLocationStop(caller2);
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ mHelper.reportLocationStop(caller2);
+ verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller2));
}
@Test
public void testHighPowerLocationMonitoring() {
CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null);
- Object key1 = new Object();
- Object key2 = new Object();
CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null);
- Object key3 = new Object();
- Object key4 = new Object();
- mHelper.reportHighPowerLocationStart(caller1, "gps", key1);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+ mHelper.reportHighPowerLocationStart(caller1);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
- mHelper.reportHighPowerLocationStart(caller1, "gps", key2);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+ mHelper.reportHighPowerLocationStart(caller1);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
- mHelper.reportHighPowerLocationStart(caller2, "gps", key3);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+ mHelper.reportHighPowerLocationStart(caller2);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
- mHelper.reportHighPowerLocationStart(caller2, "gps", key4);
- verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+ mHelper.reportHighPowerLocationStart(caller2);
+ verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
- mHelper.reportHighPowerLocationStop(caller1, "gps", key2);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
- mHelper.reportHighPowerLocationStop(caller1, "gps", key1);
- verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+ mHelper.reportHighPowerLocationStop(caller1);
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
+ mHelper.reportHighPowerLocationStop(caller1);
+ verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller1));
- mHelper.reportHighPowerLocationStop(caller2, "gps", key3);
- verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
- mHelper.reportHighPowerLocationStop(caller2, "gps", key4);
- verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+ mHelper.reportHighPowerLocationStop(caller2);
+ verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
+ mHelper.reportHighPowerLocationStop(caller2);
+ verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+ CallerIdentity.forAggregation(caller2));
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index d0b2eda..890a549 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -845,6 +845,48 @@
}
@Test
+ public void testLocationMonitoring_multipleIdentities() {
+ CallerIdentity identity1 = CallerIdentity.forTest(CURRENT_USER, 1,
+ "mypackage", "attribution", "listener1");
+ CallerIdentity identity2 = CallerIdentity.forTest(CURRENT_USER, 1,
+ "mypackage", "attribution", "listener2");
+
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+ IDENTITY.getPackageName())).isFalse();
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+ IDENTITY.getPackageName())).isFalse();
+
+ ILocationListener listener1 = createMockLocationListener();
+ LocationRequest request1 = new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build();
+ mManager.registerLocationRequest(request1, identity1, PERMISSION_FINE, listener1);
+
+ ILocationListener listener2 = createMockLocationListener();
+ LocationRequest request2 = new LocationRequest.Builder(0).setWorkSource(
+ WORK_SOURCE).build();
+ mManager.registerLocationRequest(request2, identity2, PERMISSION_FINE, listener2);
+
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+ "mypackage")).isTrue();
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+ "mypackage")).isTrue();
+
+ mManager.unregisterLocationRequest(listener2);
+
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+ "mypackage")).isTrue();
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+ "mypackage")).isTrue();
+
+ mManager.unregisterLocationRequest(listener1);
+
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+ "mypackage")).isFalse();
+ assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+ "mypackage")).isFalse();
+ }
+
+ @Test
public void testProviderRequest() {
assertThat(mProvider.getRequest().isActive()).isFalse();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 63416c9..0e5640a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -47,6 +47,7 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito.any
import com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean
import com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt
+import com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong
import com.android.dx.mockito.inline.extended.ExtendedMockito.anyString
import com.android.dx.mockito.inline.extended.ExtendedMockito.argThat
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
@@ -617,7 +618,7 @@
private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
whenever(mocks.componentResolver.queryActivities(
argThat { intent: Intent? -> intent != null && (action == intent.action) },
- nullable(), anyInt(), anyInt())) {
+ nullable(), anyLong(), anyInt())) {
ArrayList(activities.asList().map { info: ActivityInfo? ->
ResolveInfo().apply { activityInfo = info }
})
@@ -627,7 +628,7 @@
private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
whenever(mocks.componentResolver.queryServices(
argThat { intent: Intent? -> intent != null && (action == intent.action) },
- nullable(), anyInt(), anyInt())) {
+ nullable(), anyLong(), anyInt())) {
ArrayList(services.asList().map { info ->
ResolveInfo().apply { serviceInfo = info }
})
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index fe23c14..9666758 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -41,6 +41,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -316,14 +317,14 @@
final int lastUserId = 5;
final ServiceInfo pi = mIpm.getServiceInfo(sDefaultWallpaperComponent,
PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, 0);
- doReturn(pi).when(mIpm).getServiceInfo(any(), anyInt(), anyInt());
+ doReturn(pi).when(mIpm).getServiceInfo(any(), anyLong(), anyInt());
final Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
final ParceledListSlice ris =
mIpm.queryIntentServices(intent,
intent.resolveTypeIfNeeded(sContext.getContentResolver()),
PackageManager.GET_META_DATA, 0);
- doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyInt(), anyInt());
+ doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyLong(), anyInt());
doReturn(PackageManager.PERMISSION_GRANTED).when(mIpm).checkPermission(
eq(android.Manifest.permission.AMBIENT_WALLPAPER), any(), anyInt());
@@ -348,7 +349,7 @@
final int lastUserId = 5;
final ServiceInfo pi = mIpm.getServiceInfo(sDefaultWallpaperComponent,
PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, 0);
- doReturn(pi).when(mIpm).getServiceInfo(any(), anyInt(), anyInt());
+ doReturn(pi).when(mIpm).getServiceInfo(any(), anyLong(), anyInt());
final Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
final ParceledListSlice ris =
@@ -362,7 +363,7 @@
mService.switchUser(userId, null);
verifyLastWallpaperData(userId, sImageWallpaperComponentName);
// Simulate user unlocked
- doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyInt(), eq(userId));
+ doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyLong(), eq(userId));
mService.onUnlockUser(userId);
verifyLastWallpaperData(userId, sDefaultWallpaperComponent);
verifyCurrentSystemData(userId);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 0863f9e..ec1a0c2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -155,7 +155,7 @@
verify(mScreenMagnificationController, never()).reset(anyInt(),
any(MagnificationAnimationCallback.class));
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(anyInt(),
- anyFloat(), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyFloat(),
nullable(IRemoteMagnificationAnimationCallback.class));
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
index 2a53504..0659a60 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
@@ -93,7 +93,7 @@
final float scale = invocation.getArgument(1);
mScale = Float.isNaN(scale) ? mScale : scale;
computeMirrorWindowFrame(invocation.getArgument(2), invocation.getArgument(3));
- setAnimationCallback(invocation.getArgument(4));
+ setAnimationCallback(invocation.getArgument(6));
computeSourceBounds();
mHasPendingCallback = true;
if (!mSuspendCallback) {
@@ -101,7 +101,7 @@
}
return null;
}).when(mConnection).enableWindowMagnification(anyInt(), anyFloat(), anyFloat(), anyFloat(),
- nullable(IRemoteMagnificationAnimationCallback.class));
+ anyFloat(), anyFloat(), nullable(IRemoteMagnificationAnimationCallback.class));
}
private void stubDisableWindowMagnification() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
index 1638563..3822dc3 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
@@ -67,7 +67,7 @@
@Test
public void enableWindowMagnification() throws RemoteException {
mConnectionWrapper.enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f,
- mAnimationCallback);
+ 0f, 0f, mAnimationCallback);
verify(mAnimationCallback).onResult(true);
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index 1b8aff5..b807c11 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -24,6 +24,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
@@ -58,10 +59,11 @@
public static final int STATE_SHOW_MAGNIFIER_SHORTCUT = 2;
public static final int STATE_TWO_FINGERS_DOWN = 3;
public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP = 4;
+ public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 5;
//TODO: Test it after can injecting Handler to GestureMatcher is available.
public static final int FIRST_STATE = STATE_IDLE;
- public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP;
+ public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD;
// Co-prime x and y, to potentially catch x-y-swapped errors
public static final float DEFAULT_TAP_X = 301;
@@ -178,6 +180,12 @@
== mWindowMagnificationGestureHandler.mDetectingState, state);
}
break;
+ case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+ check(isWindowMagnifierEnabled(DISPLAY_0), state);
+ check(mWindowMagnificationGestureHandler.mCurrentState
+ == mWindowMagnificationGestureHandler.mViewportDraggingState, state);
+ }
+ break;
case STATE_TWO_FINGERS_DOWN: {
check(isWindowMagnifierEnabled(DISPLAY_0), state);
check(mWindowMagnificationGestureHandler.mCurrentState
@@ -229,6 +237,13 @@
tap();
}
break;
+ case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+ // Perform triple tap and hold gesture
+ tap();
+ tap();
+ tapAndHold();
+ }
+ break;
default:
throw new IllegalArgumentException("Illegal state: " + state);
}
@@ -262,6 +277,10 @@
tap();
}
break;
+ case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+ send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+ }
+ break;
default:
throw new IllegalArgumentException("Illegal state: " + state);
}
@@ -308,6 +327,11 @@
send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
}
+ private void tapAndHold() {
+ send(downEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+ SystemClock.sleep(ViewConfiguration.getLongPressTimeout() + 100);
+ }
+
private String stateDump() {
return "\nCurrent state dump:\n" + mWindowMagnificationGestureHandler.mCurrentState;
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
index 02c0aca..85512f3 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -143,8 +143,7 @@
* new connection.
*/
@Test
- public void
- setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath()
+ public void setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath()
throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
MockWindowMagnificationConnection secondConnection =
@@ -177,7 +176,7 @@
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f);
verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f),
- eq(200f), eq(300f), notNull());
+ eq(200f), eq(300f), eq(0f), eq(0f), notNull());
}
@Test
@@ -189,7 +188,8 @@
mAnimationCallback);
verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f),
- eq(200f), eq(300f), any(IRemoteMagnificationAnimationCallback.class));
+ eq(200f), eq(300f), eq(0f), eq(0f),
+ any(IRemoteMagnificationAnimationCallback.class));
verify(mAnimationCallback).onResult(true);
}
@@ -411,6 +411,34 @@
}
@Test
+ public void centerGetter_enabledOnTestDisplayWindowAtCenter_expectedValues()
+ throws RemoteException {
+ mWindowMagnificationManager.requestConnection(true);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f,
+ 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
+
+ assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f);
+ assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f);
+
+ verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f),
+ eq(100f), eq(200f), eq(0f), eq(0f), notNull());
+ }
+
+ @Test
+ public void centerGetter_enabledOnTestDisplayWindowAtLeftTop_expectedValues()
+ throws RemoteException {
+ mWindowMagnificationManager.requestConnection(true);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f,
+ 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT);
+
+ assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f);
+ assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f);
+
+ verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f),
+ eq(100f), eq(200f), eq(-1f), eq(-1f), notNull());
+ }
+
+ @Test
public void onDisplayRemoved_enabledOnTestDisplay_disabled() {
mWindowMagnificationManager.requestConnection(true);
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f);
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 1c49e6e..e40f543 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -29,7 +29,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.ArgumentMatchers.longThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -135,7 +135,7 @@
packages.add(makePackageInfo(PACKAGE_NAME_2));
packages.add(makePackageInfo(PACKAGE_NAME_3));
doReturn(new ParceledListSlice<>(packages)).when(mIPackageManager).getInstalledPackages(
- intThat(arg -> (arg & MATCH_ANY_USER) != 0), anyInt());
+ longThat(arg -> (arg & MATCH_ANY_USER) != 0), anyInt());
mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
UserInfo userInfo = addUser(USER_ID_1);
@@ -412,7 +412,7 @@
UserInfo userInfo = new UserInfo(userId, "user_" + userId, 0 /* flags */);
mUserInfos.add(userInfo);
doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
- .getInstalledPackages(intThat(arg -> (arg & MATCH_ANY_USER) == 0), eq(userId));
+ .getInstalledPackages(longThat(arg -> (arg & MATCH_ANY_USER) == 0), eq(userId));
return userInfo;
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index e3e3900..d192697 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -143,8 +143,8 @@
final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class);
- final BiometricPromptClientMonitor client1 =
- new BiometricPromptClientMonitor(mContext, mToken, lazyDaemon1, listener1);
+ final TestAuthenticationClient client1 =
+ new TestAuthenticationClient(mContext, lazyDaemon1, mToken, listener1);
final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
@@ -180,8 +180,8 @@
@Test
public void testCancelNotInvoked_whenOperationWaitingForCookie() {
final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> mock(Object.class);
- final BiometricPromptClientMonitor client1 = new BiometricPromptClientMonitor(mContext,
- mToken, lazyDaemon1, mock(ClientMonitorCallbackConverter.class));
+ final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext,
+ lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class));
final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
// Schedule a BiometricPrompt authentication request
@@ -195,6 +195,8 @@
// should go back to idle, since in this case the framework has not even requested the HAL
// to authenticate yet.
mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
+ assertTrue(client1.isAlreadyDone());
+ assertTrue(client1.mDestroyed);
assertNull(mScheduler.mCurrentOperation);
}
@@ -316,6 +318,10 @@
eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
eq(0) /* vendorCode */);
assertNull(mScheduler.getCurrentClient());
+ assertTrue(client1.isAlreadyDone());
+ assertTrue(client1.mDestroyed);
+ assertTrue(client2.isAlreadyDone());
+ assertTrue(client2.mDestroyed);
}
@Test
@@ -465,39 +471,9 @@
return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
}
- private static class BiometricPromptClientMonitor extends AuthenticationClient<Object> {
-
- public BiometricPromptClientMonitor(@NonNull Context context, @NonNull IBinder token,
- @NonNull LazyDaemon<Object> lazyDaemon, ClientMonitorCallbackConverter listener) {
- super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
- false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
- TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
- 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
- false /* isKeyguard */, true /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */);
- }
-
- @Override
- protected void stopHalOperation() {
- }
-
- @Override
- protected void startHalOperation() {
- }
-
- @Override
- protected void handleLifecycleAfterAuth(boolean authenticated) {
-
- }
-
- @Override
- public boolean wasUserDetected() {
- return false;
- }
- }
-
private static class TestAuthenticationClient extends AuthenticationClient<Object> {
int mNumCancels = 0;
+ boolean mDestroyed = false;
public TestAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
@@ -530,6 +506,13 @@
return false;
}
+ @Override
+ public void destroy() {
+ mDestroyed = true;
+ super.destroy();
+ }
+
+ @Override
public void cancel() {
mNumCancels++;
super.cancel();
@@ -595,6 +578,7 @@
@Override
public void destroy() {
+ super.destroy();
mDestroyed = true;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 2777bdf..3c809f9 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1735,11 +1735,11 @@
pi.applicationInfo.flags = flags;
doReturn(pi).when(getServices().ipackageManager).getPackageInfo(
eq(packageName),
- anyInt(),
+ anyLong(),
eq(userId));
doReturn(pi.applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
eq(packageName),
- anyInt(),
+ anyLong(),
eq(userId));
doReturn(true).when(getServices().ipackageManager).isPackageAvailable(packageName, userId);
// Setup application UID with the PackageManager
@@ -4708,11 +4708,11 @@
// Ensure packages are *not* flagged as test_only.
doReturn(new ApplicationInfo()).when(getServices().ipackageManager).getApplicationInfo(
eq(admin1.getPackageName()),
- anyInt(),
+ anyLong(),
eq(CALLER_USER_HANDLE));
doReturn(new ApplicationInfo()).when(getServices().ipackageManager).getApplicationInfo(
eq(admin2.getPackageName()),
- anyInt(),
+ anyLong(),
eq(CALLER_USER_HANDLE));
// Initial state is disabled.
@@ -7078,7 +7078,7 @@
doReturn(ai).when(getServices().ipackageManager).getApplicationInfo(
eq(admin1.getPackageName()),
- anyInt(),
+ anyLong(),
eq(CALLER_USER_HANDLE));
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index fe0df58..b8824c3 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -21,7 +21,6 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@@ -221,7 +220,7 @@
doReturn(ai).when(mServices.ipackageManager).getApplicationInfo(
eq(admin.getPackageName()),
- anyInt(),
+ anyLong(),
eq(UserHandle.getUserId(packageUid)));
// Set up queryBroadcastReceivers().
@@ -248,7 +247,7 @@
doReturn(aci).when(mServices.ipackageManager).getReceiverInfo(
eq(admin),
- anyInt(),
+ anyLong(),
eq(UserHandle.getUserId(packageUid)));
doReturn(new String[] {admin.getPackageName()}).when(mServices.ipackageManager)
diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
index b3a513f..ddc58b2 100644
--- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -110,7 +111,7 @@
@Test(expected = SecurityException.class)
public void testSetApplicationLocales_arbitraryAppWithoutPermissions_fails() throws Exception {
doReturn(DEFAULT_UID)
- .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyInt(), anyInt());
+ .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
setUpFailingPermissionCheckFor(Manifest.permission.CHANGE_CONFIGURATION);
try {
@@ -153,7 +154,7 @@
@Test
public void testSetApplicationLocales_arbitraryAppWithPermission_succeeds() throws Exception {
doReturn(DEFAULT_UID)
- .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyInt(), anyInt());
+ .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
// if package is not owned by the caller, the calling app should have the following
// permission. We will mock this to succeed to imitate that.
setUpPassingPermissionCheckFor(Manifest.permission.CHANGE_CONFIGURATION);
@@ -168,7 +169,7 @@
@Test
public void testSetApplicationLocales_callerOwnsPackage_succeeds() throws Exception {
doReturn(Binder.getCallingUid())
- .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyInt(), anyInt());
+ .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
mLocaleManagerService.setApplicationLocales(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID,
DEFAULT_LOCALES);
@@ -179,7 +180,7 @@
@Test(expected = IllegalArgumentException.class)
public void testSetApplicationLocales_invalidPackageOrUserId_fails() throws Exception {
doReturn(INVALID_UID)
- .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyInt(), anyInt());
+ .when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
try {
mLocaleManagerService.setApplicationLocales(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID,
LocaleList.getEmptyLocaleList());
@@ -192,7 +193,7 @@
@Test(expected = SecurityException.class)
public void testGetApplicationLocales_arbitraryAppWithoutPermission_fails() throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
- .getPackageUid(anyString(), anyInt(), anyInt());
+ .getPackageUid(anyString(), anyLong(), anyInt());
setUpFailingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
try {
@@ -210,7 +211,7 @@
throws Exception {
// any valid app calling for its own package or having appropriate permission
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
- .getPackageUid(anyString(), anyInt(), anyInt());
+ .getPackageUid(anyString(), anyLong(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(null)
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
@@ -225,7 +226,7 @@
public void testGetApplicationLocales_appSpecificLocalesAbsent_returnsEmptyList()
throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
- .getPackageUid(anyString(), anyInt(), anyInt());
+ .getPackageUid(anyString(), anyLong(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(new PackageConfig(/* nightMode = */ 0, /* locales = */ null))
.when(mMockActivityTaskManager).getApplicationConfig(any(), anyInt());
@@ -240,7 +241,7 @@
public void testGetApplicationLocales_callerOwnsAppAndConfigPresent_returnsLocales()
throws Exception {
doReturn(Binder.getCallingUid()).when(mMockPackageManagerInternal)
- .getPackageUid(anyString(), anyInt(), anyInt());
+ .getPackageUid(anyString(), anyLong(), anyInt());
doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES))
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
@@ -254,7 +255,7 @@
public void testGetApplicationLocales_arbitraryCallerWithPermissions_returnsLocales()
throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
- .getPackageUid(anyString(), anyInt(), anyInt());
+ .getPackageUid(anyString(), anyLong(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES))
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f45c869..3722ba4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -27,6 +27,7 @@
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -2357,7 +2358,7 @@
protected void prepareIntentActivities(ComponentName cn) {
when(mMockPackageManagerInternal.queryIntentActivities(
- anyOrNull(Intent.class), anyStringOrNull(), anyInt(), anyInt(), anyInt()))
+ anyOrNull(Intent.class), anyStringOrNull(), anyLong(), anyInt(), anyInt()))
.thenReturn(Collections.singletonList(
ri(cn.getPackageName(), cn.getClassName(), false, 0)));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
index 764c504..6245f82 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
@@ -22,8 +22,9 @@
import static com.google.common.truth.Truth.assertThat;
import android.os.Bundle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.BundleUtils;
@@ -35,6 +36,7 @@
* Build/Install/Run:
* atest com.android.server.pm.BundleUtilsTest
*/
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class BundleUtilsTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
index b228c83..54ab133 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
@@ -32,6 +32,7 @@
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Build;
+import android.platform.test.annotations.Presubmit;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.pkg.PackageUserStateImpl;
@@ -40,6 +41,7 @@
import org.junit.Before;
import org.junit.Test;
+@Presubmit
public class CompatibilityModeTest {
private boolean mCompatibilityModeEnabled;;
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index e811c1f..3cb5d5f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -3,9 +3,10 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
@@ -14,7 +15,6 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-
import static org.testng.Assert.assertThrows;
import android.Manifest;
@@ -581,7 +581,7 @@
private void mockAppsInstalled(String packageName, int user, boolean installed) {
when(mPackageManagerInternal.getPackageInfo(
eq(packageName),
- anyInt(),
+ anyLong(),
anyInt(),
eq(user)))
.thenReturn(installed ? createInstalledPackageInfo() : null);
@@ -604,7 +604,7 @@
mActivityInfo = activityInfo;
when(mPackageManagerInternal.queryIntentActivities(
- any(Intent.class), nullable(String.class), anyInt(), anyInt(), anyInt()))
+ any(Intent.class), nullable(String.class), anyLong(), anyInt(), anyInt()))
.thenReturn(Collections.singletonList(resolveInfo));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index 9631863..6b6d84a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -20,6 +20,7 @@
import static android.content.pm.parsing.ParsingPackageUtils.parsePublicKey;
import android.content.pm.Signature;
+import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -33,6 +34,7 @@
import java.security.PublicKey;
import java.security.cert.CertificateException;
+@Presubmit
public class KeySetManagerServiceTest extends AndroidTestCase {
private WatchedArrayMap<String, PackageSetting> mPackagesMap;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
index 6a9ef8a..9ea7907 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageManager;
+import android.platform.test.annotations.Presubmit;
import android.test.InstrumentationTestCase;
import com.android.frameworks.servicestests.R;
@@ -30,6 +31,7 @@
import java.util.Collections;
import java.util.List;
+@Presubmit
public class ModuleInfoProviderTest extends InstrumentationTestCase {
@Mock private ApexManager mApexManager;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 6a85c8b..b81a4ef 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -37,6 +37,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
@@ -69,15 +70,21 @@
// atest PackageManagerServiceTest
// runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services
// bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest
+@Postsubmit
@RunWith(AndroidJUnit4.class)
public class PackageManagerServiceTest {
+ private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
+
private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/";
private static final String TEST_APP_APK = "StubTestApp.apk";
private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp";
+ private IPackageManager mIPackageManager;
+
@Before
public void setUp() throws Exception {
+ mIPackageManager = AppGlobals.getPackageManager();
}
@After
@@ -620,20 +627,19 @@
@Test
public void testInstallReason_afterUpdate_keepUnchanged() throws Exception {
- final IPackageManager pm = AppGlobals.getPackageManager();
final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
try {
// Try to install test APK with reason INSTALL_REASON_POLICY
runShellCommand("pm install --install-reason 1 " + testApk);
assertWithMessage("The install reason of test APK is incorrect.").that(
- pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo(
- PackageManager.INSTALL_REASON_POLICY);
+ mIPackageManager.getInstallReason(TEST_PKG_NAME,
+ UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
// Try to update test APK with different reason INSTALL_REASON_USER
runShellCommand("pm install --install-reason 4 " + testApk);
assertWithMessage("The install reason should keep unchanged after update.").that(
- pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo(
- PackageManager.INSTALL_REASON_POLICY);
+ mIPackageManager.getInstallReason(TEST_PKG_NAME,
+ UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
} finally {
runShellCommand("pm uninstall " + TEST_PKG_NAME);
}
@@ -642,7 +648,6 @@
@Test
public void testInstallReason_userRemainsUninstalled_keepUnknown() throws Exception {
Assume.assumeTrue(UserManager.supportsMultipleUsers());
- final IPackageManager pm = AppGlobals.getPackageManager();
final UserManager um = UserManager.get(
InstrumentationRegistry.getInstrumentation().getContext());
final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
@@ -651,21 +656,21 @@
// Try to install test APK with reason INSTALL_REASON_POLICY
runShellCommand("pm install --install-reason 1 " + testApk);
assertWithMessage("The install reason of test APK is incorrect.").that(
- pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo(
- PackageManager.INSTALL_REASON_POLICY);
+ mIPackageManager.getInstallReason(TEST_PKG_NAME,
+ UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
// Create and start the 2nd user.
userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier();
runShellCommand("am start-user -w " + userId);
// Since the test APK isn't installed on the 2nd user, the reason should be unknown.
assertWithMessage("The install reason in 2nd user should be unknown.").that(
- pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+ mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
PackageManager.INSTALL_REASON_UNKNOWN);
// Try to update test APK with different reason INSTALL_REASON_USER
runShellCommand("pm install --install-reason 4 " + testApk);
assertWithMessage("The install reason in 2nd user should keep unknown.").that(
- pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+ mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
PackageManager.INSTALL_REASON_UNKNOWN);
} finally {
runShellCommand("pm uninstall " + TEST_PKG_NAME);
@@ -678,7 +683,6 @@
@Test
public void testInstallReason_installForAllUsers_sameReason() throws Exception {
Assume.assumeTrue(UserManager.supportsMultipleUsers());
- final IPackageManager pm = AppGlobals.getPackageManager();
final UserManager um = UserManager.get(
InstrumentationRegistry.getInstrumentation().getContext());
final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
@@ -691,8 +695,9 @@
// Try to install test APK to all users with reason INSTALL_REASON_POLICY
runShellCommand("pm install --install-reason 1 " + testApk);
assertWithMessage("The install reason is inconsistent across users.").that(
- pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo(
- pm.getInstallReason(TEST_PKG_NAME, userId));
+ mIPackageManager.getInstallReason(TEST_PKG_NAME,
+ UserHandle.myUserId())).isEqualTo(
+ mIPackageManager.getInstallReason(TEST_PKG_NAME, userId));
} finally {
runShellCommand("pm uninstall " + TEST_PKG_NAME);
if (userId != UserHandle.USER_NULL) {
@@ -704,7 +709,6 @@
@Test
public void testInstallReason_installSeparately_withSeparatedReason() throws Exception {
Assume.assumeTrue(UserManager.supportsMultipleUsers());
- final IPackageManager pm = AppGlobals.getPackageManager();
final UserManager um = UserManager.get(
InstrumentationRegistry.getInstrumentation().getContext());
final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
@@ -717,13 +721,13 @@
// Try to install test APK on the current user with reason INSTALL_REASON_POLICY
runShellCommand("pm install --user cur --install-reason 1 " + testApk);
assertWithMessage("The install reason on the current user is incorrect.").that(
- pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo(
- PackageManager.INSTALL_REASON_POLICY);
+ mIPackageManager.getInstallReason(TEST_PKG_NAME,
+ UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
// Try to install test APK on the 2nd user with reason INSTALL_REASON_USER
runShellCommand("pm install --user " + userId + " --install-reason 4 " + testApk);
assertWithMessage("The install reason on the 2nd user is incorrect.").that(
- pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+ mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
PackageManager.INSTALL_REASON_USER);
} finally {
runShellCommand("pm uninstall " + TEST_PKG_NAME);
@@ -732,4 +736,26 @@
}
}
}
+
+ @Test
+ public void testSetSplashScreenTheme_samePackage_succeeds() throws Exception {
+ mIPackageManager.setSplashScreenTheme(PACKAGE_NAME, null /* themeName */,
+ UserHandle.myUserId());
+ // Invoking setSplashScreenTheme on the same package shouldn't get any exception.
+ }
+
+ @Test
+ public void testSetSplashScreenTheme_differentPackage_fails() throws Exception {
+ final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+ try {
+ runShellCommand("pm install " + testApk);
+ mIPackageManager.setSplashScreenTheme(TEST_PKG_NAME, null /* themeName */,
+ UserHandle.myUserId());
+ fail("setSplashScreenTheme did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ runShellCommand("pm uninstall " + TEST_PKG_NAME);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index ab37e9b..a9a3469 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -47,6 +47,7 @@
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
@@ -91,6 +92,7 @@
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageManagerSettingsTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
index b6d4b31..7e4474f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
+import android.platform.test.annotations.Presubmit;
import android.util.TypedXmlPullParser;
import android.util.Xml;
@@ -44,6 +45,7 @@
import java.util.Map;
import java.util.Set;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class PackageSignaturesTest {
private static final String TEST_RESOURCES_FOLDER = "PackageSignaturesTest";
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index c9f3cb2..828d419c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -28,6 +28,7 @@
import android.content.pm.SuspendDialogInfo;
import android.content.pm.overlay.OverlayPaths;
import android.os.PersistableBundle;
+import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -41,6 +42,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageUserStateTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index 1fff4f0..ecf7803 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -18,8 +18,10 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
+@Presubmit
public class PackageVerificationStateTest extends AndroidTestCase {
private static final int REQUIRED_UID = 1948;
diff --git a/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java b/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
index b73c9ea..e7adf7b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
@@ -28,6 +28,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
@@ -37,6 +38,7 @@
import java.util.List;
/** Test for {@link RestrictionsSet}. */
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class RestrictionsSetTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index ec5228f..32a88bd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -95,13 +95,15 @@
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
+import androidx.test.filters.SmallTest;
+
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
@@ -135,6 +137,7 @@
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest1 \
-w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
index e92c849..57ada9b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
@@ -15,10 +15,13 @@
*/
package com.android.server.pm;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
- .assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
@@ -26,9 +29,9 @@
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.os.Process;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
-import static org.mockito.Mockito.*;
+import androidx.test.filters.SmallTest;
/**
* Tests for {@link ShortcutManager#createShortcutResultIntent(ShortcutInfo)} and relevant APIs.
@@ -39,6 +42,7 @@
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest10 \
-w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest10 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
index c8a4052..98fa2d6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
@@ -30,6 +30,7 @@
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.ShortcutInfo;
import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
import com.android.server.pm.ShortcutService.ConfigConstants;
@@ -42,6 +43,7 @@
*
atest -c com.android.server.pm.ShortcutManagerTest11
*/
+@Presubmit
public class ShortcutManagerTest11 extends BaseShortcutManagerTest {
private static final ShortcutQuery QUERY_MATCH_ALL = createShortcutQuery(
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 90a1277..408d2c5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -43,8 +43,10 @@
import android.net.Uri;
import android.os.PersistableBundle;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutUser.PackageWithUser;
@@ -64,6 +66,7 @@
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \
-w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
// ShortcutInfo tests
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
index ba26f79..43e527c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -21,7 +21,9 @@
import android.content.ComponentName;
import android.content.pm.ShortcutInfo;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
@@ -31,6 +33,7 @@
/**
* Tests related to shortcut rank auto-adjustment.
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest3 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
index 7546c43..11a2a8a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -24,15 +24,17 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
import android.util.Xml;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
@@ -134,4 +136,4 @@
});
});
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
index 203b2ca..400d3a8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
@@ -25,7 +25,9 @@
import android.content.pm.ShortcutServiceInternal;
import android.content.res.XmlResourceParser;
import android.os.Looper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
import com.android.server.LocalServices;
@@ -38,6 +40,7 @@
* All the tests here actually talks to the real IPackageManager, so we can't test complicated
* cases. Instead we just make sure they all work reasonably without at least crashing.
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest5 extends BaseShortcutManagerTest {
private ShortcutService mShortcutService;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
index 63df4bc..6c10bfd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
@@ -15,12 +15,15 @@
*/
package com.android.server.pm;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
/**
* Tests for {@link ShortcutService#hasShortcutHostPermissionInner}, which includes
* {@link ShortcutService#getDefaultLauncher}.
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest6 extends BaseShortcutManagerTest {
public void testHasShortcutHostPermissionInner_with3pLauncher_complicated() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index b21b049..b2fd8aa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -33,7 +33,9 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
@@ -48,6 +50,7 @@
*
* Launcher related commands are tested in
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 58e00f2..2293808 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -40,11 +40,13 @@
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.Pair;
+import androidx.test.filters.SmallTest;
+
import com.android.frameworks.servicestests.R;
import org.mockito.ArgumentCaptor;
@@ -63,6 +65,7 @@
* - Reading icons from requested shortcuts.
* - Invalid pre-approved token.
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
private ShortcutRequestPinProcessor mProcessor;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 55b4b93..a47a8df 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -32,7 +32,9 @@
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.PinItemRequest;
import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
import org.mockito.ArgumentCaptor;
@@ -46,6 +48,7 @@
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest9 \
-w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
*/
+@Presubmit
@SmallTest
public class ShortcutManagerTest9 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
index 826a8d4..4af91c6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertNull;
import android.content.pm.SuspendDialogInfo;
+import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -31,6 +32,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SuspendDialogInfoTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
new file mode 100644
index 0000000..85a73bb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
@@ -0,0 +1,41 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm."
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm."
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Postsubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index 7916bd3..a4afe09 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -24,6 +24,7 @@
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -42,6 +43,7 @@
* To run the test:
* bit FrameworksServicesTests:com.android.server.pm.UserLifecycleStressTest
*/
+@Postsubmit
@RunWith(AndroidJUnit4.class)
@LargeTest
public class UserLifecycleStressTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index 35c513f..fdf94be 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -27,6 +27,7 @@
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -48,6 +49,7 @@
* runtest -c com.android.server.pm.UserManagerServiceCreateProfileTest frameworks-services
* </pre>
*/
+@Postsubmit
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserManagerServiceCreateProfileTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
index b0423bf..1f4c9f8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
@@ -23,6 +23,7 @@
import android.app.PropertyInvalidatedCache;
import android.content.pm.UserInfo;
import android.os.Looper;
+import android.platform.test.annotations.Postsubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -45,6 +46,7 @@
* -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
* </pre>
*/
+@Postsubmit
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserManagerServiceIdRecyclingTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 6c1c019..34b40c7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -22,18 +22,20 @@
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.support.test.uiautomator.UiDevice;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import android.util.AtomicFile;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
+@Postsubmit
@SmallTest
public class UserManagerServiceTest extends AndroidTestCase {
private static String[] STRING_ARRAY = new String[] {"<tag", "<![CDATA["};
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index dfc25e0..92fddc7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -46,6 +46,7 @@
import android.os.Parcel;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
import android.text.TextUtils;
import androidx.test.InstrumentationRegistry;
@@ -69,6 +70,7 @@
* runtest -c com.android.server.pm.UserManagerServiceUserInfoTest frameworks-services
* </pre>
*/
+@Presubmit
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserManagerServiceUserInfoTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
index f1acc66..971b036 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
@@ -39,6 +39,7 @@
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry;
@@ -58,6 +59,7 @@
*
* <p>Run with: atest UserManagerServiceUserTypeTest
*/
+@Presubmit
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserManagerServiceUserTypeTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index ea0c073..cf6165f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -35,14 +35,15 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.provider.Settings;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Slog;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.google.common.collect.Range;
@@ -63,6 +64,7 @@
import javax.annotation.concurrent.GuardedBy;
/** Test {@link UserManager} functionality. */
+@Postsubmit
@RunWith(AndroidJUnit4.class)
public final class UserManagerTest {
// Taken from UserManagerService
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index ddf0cd0..07a5303 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -22,10 +22,12 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.SparseArray;
+import androidx.test.filters.SmallTest;
+
/**
* Tests for {@link com.android.server.pm.UserRestrictionsUtils}.
*
@@ -37,6 +39,7 @@
-w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
* </pre>
*/
+@Presubmit
@SmallTest
public class UserRestrictionsUtilsTest extends AndroidTestCase {
public void testNonNull() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index b11bb85..ba7a103 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -43,6 +43,7 @@
import android.os.Looper;
import android.os.SystemProperties;
import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
import android.support.test.uiautomator.UiDevice;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -76,6 +77,7 @@
* atest com.android.server.pm.UserSystemPackageInstallerTest
* </pre>
*/
+@Postsubmit
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserSystemPackageInstallerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
index b2c3002..95af1e1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.IntentFilter;
+import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -29,6 +30,7 @@
import java.util.Iterator;
+@Presubmit
@SmallTest
public class WatchedIntentHandlingTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
index fdb6e9f5..a16ecb1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
@@ -18,6 +18,8 @@
import static org.mockito.Mockito.inOrder;
+import android.platform.test.annotations.Presubmit;
+
import com.android.internal.art.ArtStatsLog;
import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
@@ -44,6 +46,7 @@
*
* Run with "atest ArtStatsLogUtilsTest".
*/
+@Presubmit
@RunWith(JUnit4.class)
public final class ArtStatsLogUtilsTest {
private static final String TAG = ArtStatsLogUtilsTest.class.getSimpleName();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index 2a7a2ff..b7b55ba 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -30,6 +30,7 @@
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -61,6 +62,7 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DexMetadataHelperTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
index bc84e35..d5893c8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
@@ -23,6 +23,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.Presubmit;
+
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -32,6 +34,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DexoptOptionsTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 34cefec..1dcb0b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -24,6 +24,7 @@
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ParsingPackage;
+import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -46,6 +47,7 @@
import java.util.Collections;
import java.util.List;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DexoptUtilsTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
index 7992ba3..d55f967 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageInfo;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -51,6 +52,7 @@
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Stubber;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DynamicCodeLoggerTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 3450710..c98e7c3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.fail;
import android.os.Build;
+import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -49,6 +50,7 @@
import java.util.Map;
import java.util.Set;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageDexUsageTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
index f4cdc8c..e075379 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
@@ -30,6 +30,8 @@
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.platform.test.annotations.Presubmit;
+
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -50,6 +52,7 @@
import java.util.Objects;
import java.util.Set;
+@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageDynamicCodeLoadingTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
index 51c268e..4059a49 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
@@ -16,17 +16,18 @@
package com.android.server.pm.parsing
+import android.Manifest
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageParser
import android.platform.test.annotations.Postsubmit
+import com.android.internal.util.ArrayUtils
import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.appInfo
import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.pkgInfo
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -91,9 +92,18 @@
listOf(it.configPreferences, it.reqFeatures, it.featureGroups)
},
pkgInfo(PackageManager.GET_PERMISSIONS) {
- listOf(it.permissions, it.requestedPermissions, it.requestedPermissionsFlags)
+ listOf(
+ it.permissions,
+ // Strip compatibility permission added in T
+ it.requestedPermissions?.filter { x ->
+ x != Manifest.permission.POST_NOTIFICATIONS
+ }?.ifEmpty { null }?.toTypedArray(),
+ // Strip the flag from compatibility permission added in T
+ it.requestedPermissionsFlags?.filterIndexed { index, _ ->
+ index != ArrayUtils.indexOf(it.requestedPermissions,
+ Manifest.permission.POST_NOTIFICATIONS)
+ }?.ifEmpty { null }?.toTypedArray())
},
-
appInfo(PackageManager.GET_META_DATA) { listOf(it.metaData) },
appInfo(PackageManager.GET_SHARED_LIBRARY_FILES) {
listOf(it.sharedLibraryFiles, it.sharedLibraryFiles)
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index df8786f..122661e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -16,6 +16,7 @@
package com.android.server.pm.parsing
+import android.Manifest
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
@@ -34,6 +35,7 @@
import android.os.Process
import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.internal.util.ArrayUtils
import com.android.server.pm.PackageManagerService
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
@@ -145,8 +147,8 @@
flags: Int = 0,
userId: Int = 0
): ApplicationInfo? {
- return PackageInfoUtils.generateApplicationInfo(pkg, flags, dummyUserState, userId,
- mockPkgSetting(pkg))
+ return PackageInfoUtils.generateApplicationInfo(pkg, flags.toLong(), dummyUserState,
+ userId, mockPkgSetting(pkg))
}
fun newAppInfoWithoutState(
@@ -154,8 +156,8 @@
flags: Int = 0,
userId: Int = 0
): ApplicationInfo? {
- return PackageInfoUtils.generateApplicationInfo(pkg, flags, dummyUserState, userId,
- mockPkgSetting(pkg))
+ return PackageInfoUtils.generateApplicationInfo(pkg, flags.toLong(), dummyUserState,
+ userId, mockPkgSetting(pkg))
}
fun oldPackageInfo(pkg: PackageParser.Package, flags: Int = 0): PackageInfo? {
@@ -164,7 +166,7 @@
}
fun newPackageInfo(pkg: AndroidPackage, flags: Int = 0): PackageInfo? {
- return PackageInfoUtils.generate(pkg, intArrayOf(), flags, 5, 6, emptySet(),
+ return PackageInfoUtils.generate(pkg, intArrayOf(), flags.toLong(), 5, 6, emptySet(),
dummyUserState, 0, mockPkgSetting(pkg))
}
@@ -329,7 +331,10 @@
.ignored("Update for fixing b/128526493 and the testing is no longer valid")}
enabled=${this.enabled}
exported=${this.exported}
- flags=${Integer.toBinaryString(this.flags)}
+ flags=${Integer.toBinaryString(
+ // Strip flag added in T
+ this.flags and (ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES.inv()))
+ }
icon=${this.icon}
labelRes=${this.labelRes}
launchMode=${this.launchMode}
@@ -501,13 +506,22 @@
receivers=${this.receivers?.joinToString { it.dumpToString() }
.ignored("Checked separately in test")}
reqFeatures=${this.reqFeatures?.joinToString { it.dumpToString() }}
- requestedPermissions=${this.requestedPermissions?.contentToString()}
+ requestedPermissions=${
+ // Strip compatibility permission added in T
+ this.requestedPermissions?.filter { x ->
+ x != Manifest.permission.POST_NOTIFICATIONS
+ }?.ifEmpty { null }?.joinToString()
+ }
requestedPermissionsFlags=${
- this.requestedPermissionsFlags?.map {
+ // Strip the flag from compatibility permission added in T
+ this.requestedPermissionsFlags?.filterIndexed { index, _ ->
+ index != ArrayUtils.indexOf(requestedPermissions,
+ Manifest.permission.POST_NOTIFICATIONS)
+ }?.map {
// Newer flags are stripped
it and (PackageInfo.REQUESTED_PERMISSION_REQUIRED
or PackageInfo.REQUESTED_PERMISSION_GRANTED)
- }?.joinToString()
+ }?.ifEmpty { null }?.joinToString()
}
requiredAccountType=${this.requiredAccountType}
requiredForAllUsers=${this.requiredForAllUsers}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
index c4aa862..f530421 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
@@ -21,6 +21,7 @@
import android.content.pm.parsing.ParsingPackage
import android.content.pm.parsing.ParsingPackageUtils
import android.content.pm.parsing.result.ParseResult
+import android.platform.test.annotations.Presubmit
import androidx.test.InstrumentationRegistry
import com.android.frameworks.servicestests.R
import com.google.common.truth.Truth.assertThat
@@ -36,6 +37,7 @@
*
* This verifies these failures when the APK targets R.
*/
+@Presubmit
class PackageParsingDeferErrorTest {
companion object {
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
index 3261dfa..3551af8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Process;
+import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -41,6 +42,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class LegacyPermissionManagerServiceTest {
private static final int SYSTEM_UID = 1000;
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
index 9d1c74b..a97ad8c 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
@@ -151,12 +151,12 @@
}
@Override
- public void setRecordProviderStateChanges(boolean enabled) {
+ public void setRecordStateChangesForTests(boolean enabled) {
failUnimplemented();
}
@Override
- public boolean getRecordProviderStateChanges() {
+ public boolean getRecordStateChangesForTests() {
return failUnimplemented();
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
index 97b8360..97095c4 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* A test support class used for tracking a piece of state in test objects like fakes and mocks.
@@ -79,6 +80,11 @@
assertEquals(expectedCount, getChangeCount());
}
+ /** Asserts the value has been {@link #set} to the expected values in the order given. */
+ public void assertChanges(T... expected) {
+ assertEquals(Arrays.asList(expected), mValues);
+ }
+
/**
* Returns the latest value passed to {@link #set}. If {@link #set} hasn't been called then the
* initial value is returned.
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index 20c25a0..d54e1f1 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -21,6 +21,14 @@
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_PROVIDERS_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNKNOWN;
import static com.android.server.timezonedetector.location.TestSupport.USER1_CONFIG_GEO_DETECTION_DISABLED;
import static com.android.server.timezonedetector.location.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
import static com.android.server.timezonedetector.location.TestSupport.USER2_CONFIG_GEO_DETECTION_ENABLED;
@@ -45,7 +53,9 @@
import com.android.server.timezonedetector.ConfigurationInternal;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
import com.android.server.timezonedetector.TestState;
+import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderMetricsLogger;
import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +83,7 @@
TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test");
private TestThreadingDomain mTestThreadingDomain;
+ private TestMetricsLogger mTestMetricsLogger;
private TestCallback mTestCallback;
private TestLocationTimeZoneProvider mTestPrimaryLocationTimeZoneProvider;
private TestLocationTimeZoneProvider mTestSecondaryLocationTimeZoneProvider;
@@ -82,11 +93,12 @@
// For simplicity, the TestThreadingDomain uses the test's main thread. To execute posted
// runnables, the test must call methods on mTestThreadingDomain otherwise those runnables
// will never get a chance to execute.
- LocationTimeZoneProvider.ProviderMetricsLogger stubbedProviderMetricsLogger = stateEnum -> {
- // Stubbed.
- };
mTestThreadingDomain = new TestThreadingDomain();
+ mTestMetricsLogger = new TestMetricsLogger();
+
mTestCallback = new TestCallback(mTestThreadingDomain);
+
+ ProviderMetricsLogger stubbedProviderMetricsLogger = stateEnum -> {};
mTestPrimaryLocationTimeZoneProvider = new TestLocationTimeZoneProvider(
stubbedProviderMetricsLogger, mTestThreadingDomain, "primary");
mTestSecondaryLocationTimeZoneProvider = new TestLocationTimeZoneProvider(
@@ -94,10 +106,18 @@
}
@Test
+ public void controllerStartsInUnknownState() {
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+ assertControllerState(controller, STATE_UNKNOWN);
+ }
+
+ @Test
public void initializationFailure_primary() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
@@ -112,10 +132,13 @@
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -123,8 +146,8 @@
@Test
public void initializationFailure_secondary() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
@@ -139,10 +162,13 @@
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -150,8 +176,8 @@
@Test
public void initializationFailure_both() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -165,8 +191,11 @@
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
+ assertControllerState(controller, STATE_FAILED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING, STATE_FAILED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -174,8 +203,8 @@
@Test
public void initialState_started() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
@@ -188,10 +217,13 @@
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -199,8 +231,8 @@
@Test
public void initialState_disabled() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -211,8 +243,10 @@
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -220,8 +254,8 @@
@Test
public void enabled_uncertaintySuggestionSentIfNoEventReceived() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -231,18 +265,22 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_INITIALIZING);
// The primary should have reported uncertainty, which should trigger the controller to
// start the uncertainty timeout and start the secondary.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -250,12 +288,14 @@
// secondary.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_INITIALIZING);
// Now both initialization timeouts should have triggered. The uncertainty timeout should
// still not be triggered.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -263,10 +303,12 @@
// suggestion.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_UNCERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -274,17 +316,20 @@
@Test
public void enabled_eventReceivedBeforeInitializationTimeout() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -293,9 +338,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -304,27 +351,32 @@
@Test
public void enabled_eventReceivedFromPrimaryAfterInitializationTimeout() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -333,9 +385,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -344,27 +398,32 @@
@Test
public void enabled_eventReceivedFromSecondaryAfterInitializationTimeout() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -373,10 +432,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -385,17 +446,20 @@
@Test
public void enabled_repeatedPrimaryCertainty() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -404,9 +468,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -415,9 +481,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -425,9 +493,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -436,27 +506,32 @@
@Test
public void enabled_repeatedSecondaryCertainty() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -465,10 +540,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -477,10 +554,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -488,10 +567,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -500,17 +581,20 @@
@Test
public void enabled_uncertaintyTriggersASuggestionAfterUncertaintyTimeout() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -519,9 +603,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -532,10 +618,12 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -545,10 +633,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -559,10 +649,12 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -570,10 +662,12 @@
// suggestion should be made.
mTestThreadingDomain.executeNext();
+ assertControllerState(controller, STATE_UNCERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
mTestCallback.assertUncertainSuggestionMadeFromEventAndCommit(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -582,17 +676,20 @@
@Test
public void enabled_briefUncertaintyTriggersNoSuggestion() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -601,9 +698,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -613,10 +712,12 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -626,9 +727,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -637,33 +740,39 @@
@Test
public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -671,25 +780,29 @@
@Test
public void configChanges_enableAndDisableWithPreviousSuggestion() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -697,9 +810,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -710,8 +825,10 @@
// of the time zone.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN, STATE_STOPPED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -719,17 +836,20 @@
@Test
public void configChanges_userSwitch_enabledToEnabled() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -739,9 +859,11 @@
// Receiving a "success" provider event should cause a suggestion to be made synchronously,
// and also clear the scheduled uncertainty suggestion.
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -750,7 +872,7 @@
testEnvironment.simulateConfigChange(USER2_CONFIG_GEO_DETECTION_ENABLED);
// Confirm that the previous suggestion was overridden.
- mTestCallback.assertUncertainSuggestionMadeAndCommit();
+ assertControllerState(controller, STATE_INITIALIZING);
// We expect the provider to end up in PROVIDER_STATE_STARTED_INITIALIZING, but it should
// have been stopped when the user changed.
@@ -760,23 +882,29 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
PROVIDER_STATE_STARTED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_UNCERTAIN, STATE_STOPPED, STATE_INITIALIZING);
+ mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void primaryPermFailure_secondaryEventsReceived() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -785,9 +913,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -795,9 +925,11 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -806,9 +938,11 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -817,9 +951,11 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
}
@@ -827,17 +963,20 @@
@Test
public void primaryPermFailure_disableAndEnable() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -846,26 +985,32 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -873,17 +1018,20 @@
@Test
public void secondaryPermFailure_primaryEventsReceived() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -893,10 +1041,12 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -904,9 +1054,11 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -915,9 +1067,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -926,9 +1080,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
}
@@ -936,17 +1092,20 @@
@Test
public void secondaryPermFailure_disableAndEnable() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -956,10 +1115,12 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
@@ -967,17 +1128,21 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controller);
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
+ assertControllerState(controller, STATE_STOPPED);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -985,9 +1150,11 @@
// started.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -995,17 +1162,20 @@
@Test
public void bothPermFailure_disableAndEnable() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -1013,9 +1183,11 @@
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestMetricsLogger.assertStateChangesAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -1023,8 +1195,10 @@
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+ assertControllerState(controller, STATE_FAILED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_FAILED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controller.isUncertaintyTimeoutSet());
}
@@ -1033,8 +1207,8 @@
public void stateRecording() {
// The test provider enables state recording by default.
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, true /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -1043,12 +1217,15 @@
{
LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+ assertEquals(STATE_INITIALIZING, state.getControllerState());
assertNull(state.getLastSuggestion());
+ assertControllerRecordedStates(state,
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
assertProviderStates(state.getPrimaryProviderStates(),
PROVIDER_STATE_STOPPED, PROVIDER_STATE_STARTED_INITIALIZING);
assertProviderStates(state.getSecondaryProviderStates(), PROVIDER_STATE_STOPPED);
}
- controller.clearRecordedProviderStates();
+ controller.clearRecordedStates();
// Simulate some provider behavior that will show up in the state recording.
@@ -1058,13 +1235,15 @@
{
LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+ assertEquals(STATE_INITIALIZING, state.getControllerState());
assertNull(state.getLastSuggestion());
+ assertControllerRecordedStates(state);
assertProviderStates(
state.getPrimaryProviderStates(), PROVIDER_STATE_STARTED_UNCERTAIN);
assertProviderStates(
state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_INITIALIZING);
}
- controller.clearRecordedProviderStates();
+ controller.clearRecordedStates();
// Simulate a certain event from the secondary.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -1072,18 +1251,22 @@
{
LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+ assertEquals(STATE_CERTAIN, state.getControllerState());
assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
state.getLastSuggestion().getZoneIds());
+ assertControllerRecordedStates(state, STATE_CERTAIN);
assertProviderStates(state.getPrimaryProviderStates());
assertProviderStates(
state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_CERTAIN);
}
- controller.clearRecordedProviderStates();
+ controller.clearRecordedStates();
{
LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+ assertEquals(STATE_CERTAIN, state.getControllerState());
assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
state.getLastSuggestion().getZoneIds());
+ assertControllerRecordedStates(state);
assertProviderStates(state.getPrimaryProviderStates());
assertProviderStates(state.getSecondaryProviderStates());
}
@@ -1101,17 +1284,20 @@
@Test
public void destroy() {
LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
- mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
- mTestSecondaryLocationTimeZoneProvider);
+ mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
controller.initialize(testEnvironment, mTestCallback);
+ assertControllerState(controller, STATE_INITIALIZING);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
mTestCallback.assertNoSuggestionMade();
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -1121,9 +1307,11 @@
// Receiving a "success" provider event should cause a suggestion to be made synchronously,
// and also clear the scheduled uncertainty suggestion.
+ assertControllerState(controller, STATE_CERTAIN);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controller.isUncertaintyTimeoutSet());
@@ -1131,6 +1319,10 @@
// Trigger destroy().
controller.destroy();
+ assertControllerState(controller, STATE_DESTROYED);
+ mTestMetricsLogger.assertStateChangesAndCommit(
+ STATE_UNCERTAIN, STATE_STOPPED, STATE_DESTROYED);
+
// Confirm that the previous suggestion was overridden.
mTestCallback.assertUncertainSuggestionMadeAndCommit();
@@ -1158,6 +1350,17 @@
.build());
}
+ private static void assertControllerState(LocationTimeZoneProviderController controller,
+ @State String expectedState) {
+ assertEquals(expectedState, controller.getStateForTests().getControllerState());
+ }
+
+ private static void assertControllerRecordedStates(
+ LocationTimeZoneManagerServiceState state,
+ @State String... expectedStates) {
+ assertEquals(Arrays.asList(expectedStates), state.getControllerStates());
+ }
+
private static class TestEnvironment extends LocationTimeZoneProviderController.Environment {
// These timeouts are set deliberately so that:
@@ -1229,6 +1432,22 @@
}
}
+ private static class TestMetricsLogger
+ implements LocationTimeZoneProviderController.MetricsLogger {
+
+ private final TestState<@State String> mLatestStateEnum = new TestState<>();
+
+ @Override
+ public void onStateChange(@State String stateEnum) {
+ mLatestStateEnum.set(stateEnum);
+ }
+
+ public void assertStateChangesAndCommit(@State String... expectedStateEnums) {
+ mLatestStateEnum.assertChanges(expectedStateEnums);
+ mLatestStateEnum.commitLatest();
+ }
+ }
+
private static class TestCallback extends LocationTimeZoneProviderController.Callback {
private TestState<GeolocationTimeZoneSuggestion> mLatestSuggestion = new TestState<>();
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
index 3716507..7eb6c97 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
@@ -16,7 +16,7 @@
package com.android.server.uri;
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -121,47 +121,47 @@
LocalServices.addService(PackageManagerInternal.class, mPmInternal);
for (int userId : new int[] { USER_PRIMARY, USER_SECONDARY }) {
- when(mPmInternal.getPackageUid(eq(PKG_SOCIAL), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_SOCIAL), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_SOCIAL));
- when(mPmInternal.getPackageUid(eq(PKG_CAMERA), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_CAMERA), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_CAMERA));
- when(mPmInternal.getPackageUid(eq(PKG_PRIVATE), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_PRIVATE), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_PRIVATE));
- when(mPmInternal.getPackageUid(eq(PKG_PUBLIC), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_PUBLIC), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_PUBLIC));
- when(mPmInternal.getPackageUid(eq(PKG_FORCE), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_FORCE), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_FORCE));
- when(mPmInternal.getPackageUid(eq(PKG_COMPLEX), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_COMPLEX), anyLong(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_COMPLEX));
- when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyLong(), eq(userId),
eq(Process.SYSTEM_UID)))
.thenReturn(buildCameraProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyLong(), eq(userId),
eq(UserHandle.getUid(userId, UID_CAMERA))))
.thenReturn(buildCameraProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyLong(), eq(userId),
eq(Process.SYSTEM_UID)))
.thenReturn(buildPrivateProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyLong(), eq(userId),
eq(UserHandle.getUid(userId, UID_PRIVATE))))
.thenReturn(buildPrivateProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyLong(), eq(userId),
eq(Process.SYSTEM_UID)))
.thenReturn(buildPublicProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyLong(), eq(userId),
eq(UserHandle.getUid(userId, UID_PUBLIC))))
.thenReturn(buildPublicProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyLong(), eq(userId),
eq(Process.SYSTEM_UID)))
.thenReturn(buildForceProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyLong(), eq(userId),
eq(UserHandle.getUid(userId, UID_FORCE))))
.thenReturn(buildForceProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyLong(), eq(userId),
eq(Process.SYSTEM_UID)))
.thenReturn(buildComplexProvider(userId));
- when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId),
+ when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyLong(), eq(userId),
eq(UserHandle.getUid(userId, UID_COMPLEX))))
.thenReturn(buildComplexProvider(userId));
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 9e46e1f..949ee01 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -63,6 +63,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -530,8 +531,8 @@
eq(UserHandle.getAppId(ai.uid)), eq(userIdForTest), anyLong()))
.thenReturn(idle[i]);
}
- when(mInjector.mPackageManagerInternal.getInstalledApplications(anyInt(), eq(userIdForTest),
- anyInt())).thenReturn(installedApps);
+ when(mInjector.mPackageManagerInternal.getInstalledApplications(anyLong(),
+ eq(userIdForTest), anyInt())).thenReturn(installedApps);
final int[] returnedIdleUids = controllerUnderTest.getIdleUidsForUser(userIdForTest);
assertEquals(expectedIdleUids.length, returnedIdleUids.length);
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 4eb9c06..c0f7596 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -126,15 +126,23 @@
new VibrationAttributes.Builder().setUsage(
VibrationAttributes.USAGE_RINGTONE).build();
- @Rule public MockitoRule rule = MockitoJUnit.rule();
- @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+ @Rule
+ public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
- @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
- @Mock private PackageManagerInternal mPackageManagerInternalMock;
- @Mock private PowerManagerInternal mPowerManagerInternalMock;
- @Mock private PowerSaveState mPowerSaveStateMock;
- @Mock private AppOpsManager mAppOpsManagerMock;
- @Mock private IInputManager mIInputManagerMock;
+ @Mock
+ private VibratorManagerService.NativeWrapper mNativeWrapperMock;
+ @Mock
+ private PackageManagerInternal mPackageManagerInternalMock;
+ @Mock
+ private PowerManagerInternal mPowerManagerInternalMock;
+ @Mock
+ private PowerSaveState mPowerSaveStateMock;
+ @Mock
+ private AppOpsManager mAppOpsManagerMock;
+ @Mock
+ private IInputManager mIInputManagerMock;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
@@ -397,6 +405,7 @@
@Test
public void registerVibratorStateListener_multipleVibratorsAreTriggered() throws Exception {
mockVibrators(0, 1, 2);
+ mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
VibratorManagerService service = createSystemReadyService();
IVibratorStateListener[] listeners = new IVibratorStateListener[3];
for (int i = 0; i < 3; i++) {
@@ -601,8 +610,8 @@
VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY).build();
- VibrationAttributes vibrationAttributes = new VibrationAttributes.Builder(
- audioAttributes, effect).build();
+ VibrationAttributes vibrationAttributes =
+ new VibrationAttributes.Builder(audioAttributes).build();
vibrate(service, effect, vibrationAttributes);
@@ -621,7 +630,7 @@
vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
new VibrationAttributes.Builder().setUsage(
VibrationAttributes.USAGE_COMMUNICATION_REQUEST).build());
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK),
+ vibrate(service, VibrationEffect.createOneShot(2000, 200),
new VibrationAttributes.Builder().setUsage(
VibrationAttributes.USAGE_UNKNOWN).build());
@@ -642,6 +651,60 @@
}
@Test
+ public void vibrate_withAttributesUnknownUsage_usesEffectToIdentifyTouchUsage() {
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationAttributes unknownAttributes = VibrationAttributes.createForUsage(
+ VibrationAttributes.USAGE_UNKNOWN);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), unknownAttributes);
+ vibrate(service, VibrationEffect.createOneShot(200, 200), unknownAttributes);
+ vibrate(service, VibrationEffect.createWaveform(
+ new long[] { 100, 200, 300 }, new int[] {1, 2, 3}, -1), unknownAttributes);
+ vibrate(service,
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+ .compose(),
+ unknownAttributes);
+
+ verify(mAppOpsManagerMock, times(4))
+ .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+ eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString());
+ verify(mAppOpsManagerMock, never())
+ .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+ eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
+ }
+
+ @Test
+ public void vibrate_withAttributesUnknownUsage_ignoresEffectIfNotHapticFeedbackCandidate() {
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationAttributes unknownAttributes = VibrationAttributes.createForUsage(
+ VibrationAttributes.USAGE_UNKNOWN);
+ vibrate(service, VibrationEffect.get(VibrationEffect.RINGTONES[0]), unknownAttributes);
+ vibrate(service, VibrationEffect.createOneShot(2000, 200), unknownAttributes);
+ vibrate(service, VibrationEffect.createWaveform(
+ new long[] { 100, 200, 300 }, new int[] {1, 2, 3}, 0), unknownAttributes);
+ vibrate(service,
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .compose(),
+ unknownAttributes);
+
+ verify(mAppOpsManagerMock, never())
+ .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+ eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString());
+ verify(mAppOpsManagerMock, times(4))
+ .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+ eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
+ }
+
+ @Test
public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index cdb7230..2f054b00 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -26,6 +26,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -809,7 +810,7 @@
service.isComponentEnabledForCurrentProfiles(
unapprovedAdditionalComponent));
verify(mIpm, never()).getServiceInfo(
- eq(unapprovedAdditionalComponent), anyInt(), anyInt());
+ eq(unapprovedAdditionalComponent), anyLong(), anyInt());
}
}
@@ -953,7 +954,7 @@
service.isComponentEnabledForCurrentProfiles(
unapprovedAdditionalComponent));
verify(mIpm, never()).getServiceInfo(
- eq(unapprovedAdditionalComponent), anyInt(), anyInt());
+ eq(unapprovedAdditionalComponent), anyLong(), anyInt());
}
}
@@ -1702,14 +1703,14 @@
assertTrue(service.isComponentEnabledForCurrentProfiles(
componentName));
verify(mIpm, times(1)).getServiceInfo(
- eq(componentName), anyInt(), anyInt());
+ eq(componentName), anyLong(), anyInt());
}
} else {
ComponentName componentName =
ComponentName.unflattenFromString(packageOrComponent);
assertTrue(service.isComponentEnabledForCurrentProfiles(componentName));
verify(mIpm, times(1)).getServiceInfo(
- eq(componentName), anyInt(), anyInt());
+ eq(componentName), anyLong(), anyInt());
}
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 622669a..837850f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -397,7 +397,7 @@
// MockPackageManager - default returns ApplicationInfo with matching calling UID
mContext.setMockPackageManager(mPackageManagerClient);
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt()))
.thenAnswer((Answer<ApplicationInfo>) invocation -> {
Object[] args = invocation.getArguments();
return getApplicationInfo((String) args[0], mUid);
@@ -5043,7 +5043,7 @@
public void testIsCallerInstantApp_primaryUser() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
assertTrue(mService.isCallerInstantApp(45770, 0));
@@ -5056,8 +5056,8 @@
public void testIsCallerInstantApp_secondaryUser() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
assertTrue(mService.isCallerInstantApp(68638450, 10));
@@ -5067,7 +5067,7 @@
public void testIsCallerInstantApp_userAllNotification() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(USER_SYSTEM)))
.thenReturn(info);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
@@ -5081,8 +5081,8 @@
public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.uid = Binder.getCallingUid();
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
@@ -5093,7 +5093,7 @@
public void testResolveNotificationUid_sameApp() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.uid = Binder.getCallingUid();
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
@@ -5104,7 +5104,7 @@
public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.uid = Binder.getCallingUid();
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
@@ -5115,7 +5115,7 @@
public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
ApplicationInfo info = new ApplicationInfo();
info.uid = 1356347;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(info);
try {
mService.resolveNotificationUid("caller", "caller", 9, 0);
@@ -5154,7 +5154,7 @@
PackageManager.NameNotFoundException.class);
ApplicationInfo ai = new ApplicationInfo();
ai.uid = -1;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
try {
@@ -5174,7 +5174,7 @@
PackageManager.NameNotFoundException.class);
ApplicationInfo ai = new ApplicationInfo();
ai.uid = -1;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
// unlike the post case, ignore instead of throwing
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
index 29ef339..2e5cf3c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
@@ -44,6 +44,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
@@ -307,7 +308,7 @@
// MockPackageManager - default returns ApplicationInfo with matching calling UID
mContext.setMockPackageManager(mPackageManagerClient);
- when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
+ when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt()))
.thenAnswer((Answer<ApplicationInfo>) invocation -> {
Object[] args = invocation.getArguments();
return getApplicationInfo((String) args[0], mUid);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index 4cdae88..5800400 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -28,6 +28,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -42,7 +43,6 @@
import android.permission.IPermissionManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
-import android.util.Slog;
import androidx.test.runner.AndroidJUnit4;
@@ -169,7 +169,8 @@
ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>(
ImmutableList.of(notThis, none, first, second));
- when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS), anyInt())).thenReturn(infos);
+ when(mPackageManager.getInstalledPackages(eq((long) GET_PERMISSIONS), anyInt()))
+ .thenReturn(infos);
Set<Pair<Integer, String>> actual = mPermissionHelper.getAppsRequestingPermission(0);
@@ -181,7 +182,7 @@
int userId = 1;
ParceledListSlice<PackageInfo> infos = ParceledListSlice.emptyList();
when(mPackageManager.getPackagesHoldingPermissions(
- eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyInt(), eq(userId)))
+ eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId)))
.thenReturn(infos);
assertThat(mPermissionHelper.getAppsGrantedPermission(userId)).isNotNull();
}
@@ -206,7 +207,7 @@
ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>(
ImmutableList.of(first, second));
when(mPackageManager.getPackagesHoldingPermissions(
- eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyInt(), eq(userId)))
+ eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId)))
.thenReturn(infos);
Set<Pair<Integer, String>> expected =
@@ -305,11 +306,11 @@
ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>(
ImmutableList.of(first, second));
when(mPackageManager.getPackagesHoldingPermissions(
- eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyInt(), eq(userId)))
+ eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId)))
.thenReturn(infos);
ParceledListSlice<PackageInfo> requesting = new ParceledListSlice<>(
ImmutableList.of(first, second, third));
- when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS), anyInt()))
+ when(mPackageManager.getInstalledPackages(eq((long) GET_PERMISSIONS), anyInt()))
.thenReturn(requesting);
Map<Pair<Integer, String>, Boolean> expected = ImmutableMap.of(new Pair(1, "first"), true,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 0cab911..e2f0658f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -63,6 +63,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
@@ -352,7 +353,7 @@
doReturn(null).when(mMockPackageManager).getDefaultHomeActivity(anyInt());
doReturn(mMockPackageManager).when(mAtm).getPackageManagerInternalLocked();
doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any());
- doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyInt(), anyInt(),
+ doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyLong(), anyLong(),
anyInt(), anyBoolean(), anyInt());
doReturn(new ComponentName("", "")).when(mMockPackageManager).getSystemUiServiceComponent();
diff --git a/tests/AttestationVerificationTest/Android.bp b/tests/AttestationVerificationTest/Android.bp
new file mode 100644
index 0000000..a4741eed
--- /dev/null
+++ b/tests/AttestationVerificationTest/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "AttestationVerificationTest",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ defaults: ["cts_defaults"],
+ manifest: "AndroidManifest.xml",
+ test_config: "AndroidTest.xml",
+ platform_apis: true,
+ certificate: "platform",
+ optimize: {
+ enabled: false,
+ },
+ test_suites: ["device-tests"],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "platform-test-annotations",
+ ],
+}
diff --git a/tests/AttestationVerificationTest/AndroidManifest.xml b/tests/AttestationVerificationTest/AndroidManifest.xml
new file mode 100755
index 0000000..c42bde9
--- /dev/null
+++ b/tests/AttestationVerificationTest/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.attestationverification">
+
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+ <uses-permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE" />
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <activity android:name=".SystemAttestationVerificationTest$TestActivity" />
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.attestationverification">
+ </instrumentation>
+</manifest>
diff --git a/tests/AttestationVerificationTest/AndroidTest.xml b/tests/AttestationVerificationTest/AndroidTest.xml
new file mode 100644
index 0000000..1325760
--- /dev/null
+++ b/tests/AttestationVerificationTest/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Platform tests for Attestation Verification Framework">
+ <option name="test-tag" value="AttestationVerificationTest" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="AttestationVerificationTest.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.security.attestationverification" />
+ <option name="hidden-api-checks" value="false" />
+ </test>
+</configuration>
diff --git a/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt b/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt
new file mode 100644
index 0000000..48bfd6f
--- /dev/null
+++ b/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt
@@ -0,0 +1,90 @@
+package android.security.attestationverification
+
+import android.os.Bundle
+import android.app.Activity
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import org.junit.Assert.assertThrows
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import com.google.common.truth.Truth.assertThat
+import android.security.attestationverification.AttestationVerificationManager.PROFILE_SELF_TRUSTED
+import android.security.attestationverification.AttestationVerificationManager.TYPE_PUBLIC_KEY
+import android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN
+import java.lang.IllegalArgumentException
+import java.time.Duration
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+
+/** Test for system-defined attestation verifiers. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SystemAttestationVerificationTest {
+
+ @get:Rule
+ val rule = ActivityScenarioRule(TestActivity::class.java)
+
+ private lateinit var activity: Activity
+ private lateinit var avm: AttestationVerificationManager
+
+ @Before
+ fun setup() {
+ rule.getScenario().onActivity {
+ avm = it.getSystemService(AttestationVerificationManager::class.java)
+ activity = it
+ }
+ }
+
+ @Test
+ fun verifyAttestation_returnsUnknown() {
+ val future = CompletableFuture<Int>()
+ val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+ avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+ activity.mainExecutor) { result, _ ->
+ future.complete(result)
+ }
+
+ assertThat(future.getSoon()).isEqualTo(RESULT_UNKNOWN)
+ }
+
+ @Test
+ fun verifyToken_returnsUnknown() {
+ val future = CompletableFuture<Int>()
+ val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+ avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+ activity.mainExecutor) { _, token ->
+ val result = avm.verifyToken(profile, TYPE_PUBLIC_KEY, Bundle(), token, null)
+ future.complete(result)
+ }
+
+ assertThat(future.getSoon()).isEqualTo(RESULT_UNKNOWN)
+ }
+
+ @Test
+ fun verifyToken_tooBigMaxAgeThrows() {
+ val future = CompletableFuture<VerificationToken>()
+ val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+ avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+ activity.mainExecutor) { _, token ->
+ future.complete(token)
+ }
+
+ assertThrows(IllegalArgumentException::class.java) {
+ avm.verifyToken(profile, TYPE_PUBLIC_KEY, Bundle(), future.getSoon(),
+ Duration.ofSeconds(3601))
+ }
+ }
+
+ private fun <T> CompletableFuture<T>.getSoon(): T {
+ return this.get(1, TimeUnit.SECONDS)
+ }
+
+ class TestActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index cac7978..c18798f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -114,11 +114,16 @@
flickerRule.checkFlakyAssertions()
}
- /** {@inheritDoc} */
+ /**
+ * Windows maybe recreated when rotated. Checks that the focus does not change or if it does,
+ * focus returns to [testApp]
+ */
@FlakyTest(bugId = 190185577)
@Test
- override fun focusDoesNotChange() {
- super.focusDoesNotChange()
+ fun focusChanges() {
+ testSpec.assertEventLog {
+ this.focusChanges(testApp.`package`)
+ }
}
/**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index ce2347d..d1bdeed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -129,17 +129,6 @@
open fun entireScreenCovered() = testSpec.entireScreenCovered()
/**
- * Checks that the focus doesn't change during animation
- */
- @Presubmit
- @Test
- open fun focusDoesNotChange() {
- testSpec.assertEventLog {
- this.focusDoesNotChange()
- }
- }
-
- /**
* Checks that [testApp] layer covers the entire screen at the start of the transition
*/
@Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 3ca60e3..e44bee6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -146,15 +146,6 @@
}
}
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun focusDoesNotChange() {
- // This test doesn't work in shell transitions because of b/206101151
- assumeFalse(isShellTransitionsEnabled)
- super.focusDoesNotChange()
- }
-
/**
* Checks that [testApp] layer covers the entire screen during the whole transition
*/
@@ -196,6 +187,19 @@
}
}
+ /**
+ * Checks that the focus doesn't change during animation
+ */
+ @Presubmit
+ @Test
+ fun focusDoesNotChange() {
+ // This test doesn't work in shell transitions because of b/206101151
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.assertEventLog {
+ this.focusDoesNotChange()
+ }
+ }
+
/** {@inheritDoc} */
@FlakyTest
@Test
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
index 7ea2a62d..d4bc2a6 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
@@ -42,7 +42,7 @@
swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
frame.addView(swView);
final RectsView hwBothView = new RectsView(this, 850, Color.GREEN);
- // Don't actually need to render to a hw layer, but it's a good sanity-check that
+ // Don't actually need to render to a hw layer, but it's a good check that
// we're rendering to/from layers correctly
hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
frame.addView(hwBothView);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
index 7173a85..584ab59 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
@@ -42,7 +42,7 @@
swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
frame.addView(swView);
final LinesView hwBothView = new LinesView(this, 850, Color.GREEN);
- // Don't actually need to render to a hw layer, but it's a good sanity-check that
+ // Don't actually need to render to a hw layer, but it's a good check that
// we're rendering to/from layers correctly
hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
frame.addView(hwBothView);
diff --git a/tests/Internal/src/com/android/internal/util/ParcellingTests.java b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
new file mode 100644
index 0000000..65a3436
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 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.internal.util;
+
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.Parcelling.BuiltIn.ForInstant;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.time.Instant;
+
+/** Tests for {@link Parcelling}. */
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class ParcellingTests {
+
+ private Parcel mParcel = Parcel.obtain();
+
+ @Test
+ public void forInstant_normal() {
+ testForInstant(Instant.ofEpochSecond(500L, 10));
+ }
+
+ @Test
+ public void forInstant_minimum() {
+ testForInstant(Instant.MIN);
+ }
+
+ @Test
+ public void forInstant_maximum() {
+ testForInstant(Instant.MAX);
+ }
+
+ @Test
+ public void forInstant_null() {
+ testForInstant(null);
+ }
+
+ private void testForInstant(Instant instant) {
+ Parcelling<Instant> parcelling = new ForInstant();
+ parcelling.parcel(instant, mParcel, 0);
+ mParcel.setDataPosition(0);
+
+ Instant created = parcelling.unparcel(mParcel);
+
+ if (instant == null) {
+ assertNull(created);
+ } else {
+ assertEquals(instant, created);
+ }
+ }
+
+}