Merge "Adding unit tests"
diff --git a/Android.bp b/Android.bp
index b3c9e2a..2534140 100644
--- a/Android.bp
+++ b/Android.bp
@@ -688,6 +688,7 @@
srcs: [
"core/java/android/annotation/CallbackExecutor.java",
"core/java/android/annotation/CheckResult.java",
+ "core/java/android/annotation/CurrentTimeMillisLong.java",
"core/java/android/annotation/IntDef.java",
"core/java/android/annotation/IntRange.java",
"core/java/android/annotation/NonNull.java",
@@ -1127,7 +1128,6 @@
srcs: [
":framework-annotations",
"core/java/android/annotation/BytesLong.java",
- "core/java/android/annotation/CurrentTimeMillisLong.java",
"core/java/android/annotation/CurrentTimeSecondsLong.java",
"core/java/android/annotation/DurationMillisLong.java",
],
@@ -1327,7 +1327,6 @@
libs: [
"framework-minus-apex",
"unsupportedappusage",
- "ike-stubs",
],
static_libs: [
"libphonenumber-platform",
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 7b3764a..1cc1c5f 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -385,24 +385,27 @@
}
private void onStateChangedInternal(@NonNull BlobStoreSession session) {
- synchronized (mBlobsLock) {
- switch (session.getState()) {
- case STATE_ABANDONED:
- case STATE_VERIFIED_INVALID:
- session.getSessionFile().delete();
+ switch (session.getState()) {
+ case STATE_ABANDONED:
+ case STATE_VERIFIED_INVALID:
+ session.getSessionFile().delete();
+ synchronized (mBlobsLock) {
getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
.remove(session.getSessionId());
mKnownBlobIds.remove(session.getSessionId());
if (LOGV) {
Slog.v(TAG, "Session is invalid; deleted " + session);
}
- break;
- case STATE_COMMITTED:
- session.verifyBlobData();
- break;
- case STATE_VERIFIED_VALID:
+ }
+ break;
+ case STATE_COMMITTED:
+ session.verifyBlobData();
+ break;
+ case STATE_VERIFIED_VALID:
+ synchronized (mBlobsLock) {
final int userId = UserHandle.getUserId(session.getOwnerUid());
- final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
+ userId);
BlobMetadata blob = userBlobs.get(session.getBlobHandle());
if (blob == null) {
blob = new BlobMetadata(mContext,
@@ -425,11 +428,13 @@
if (LOGV) {
Slog.v(TAG, "Successfully committed session " + session);
}
- break;
- default:
- Slog.wtf(TAG, "Invalid session state: "
- + stateToString(session.getState()));
- }
+ }
+ break;
+ default:
+ Slog.wtf(TAG, "Invalid session state: "
+ + stateToString(session.getState()));
+ }
+ synchronized (mBlobsLock) {
try {
writeBlobSessionsLocked();
} catch (Exception e) {
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index dc72d6d..f8b598a 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -147,7 +147,7 @@
void postReportExemptedSyncStart(String packageName, int userId);
- void dumpUser(IndentingPrintWriter idpw, int userId, String pkg);
+ void dumpUser(IndentingPrintWriter idpw, int userId, List<String> pkgs);
void dumpState(String[] args, PrintWriter pw);
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 9d6e012..932c25d 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -41,6 +41,7 @@
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
@@ -58,6 +59,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.List;
/**
* Keeps track of recent active state changes in apps.
@@ -721,7 +723,7 @@
}
}
- public void dump(IndentingPrintWriter idpw, int userId, String pkg) {
+ public void dump(IndentingPrintWriter idpw, int userId, List<String> pkgs) {
idpw.println("App Standby States:");
idpw.increaseIndent();
ArrayMap<String, AppUsageHistory> userHistory = mIdleHistory.get(userId);
@@ -733,7 +735,7 @@
for (int p = 0; p < P; p++) {
final String packageName = userHistory.keyAt(p);
final AppUsageHistory appUsageHistory = userHistory.valueAt(p);
- if (pkg != null && !pkg.equals(packageName)) {
+ if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(packageName)) {
continue;
}
idpw.print("package=" + packageName);
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index e343478..bf61eb4 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1505,9 +1505,9 @@
}
@Override
- public void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
+ public void dumpUser(IndentingPrintWriter idpw, int userId, List<String> pkgs) {
synchronized (mAppIdleLock) {
- mAppIdleHistory.dump(idpw, userId, pkg);
+ mAppIdleHistory.dump(idpw, userId, pkgs);
}
}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index f7a8176..487c8e1 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -38,6 +38,13 @@
},
ndk: {
enabled: true,
- }
+ apex_available: [
+ // TODO(b/145923087): Remove this once statsd binary is in apex
+ "//apex_available:platform",
+
+ "com.android.os.statsd",
+ "test_com.android.os.statsd",
+ ],
+ },
}
}
diff --git a/api/current.txt b/api/current.txt
index 51ae4a8..702744d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9,6 +9,7 @@
ctor public Manifest.permission();
field public static final String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
field public static final String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
+ field public static final String ACCESS_CALL_AUDIO = "android.permission.ACCESS_CALL_AUDIO";
field public static final String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
field public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
field public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
@@ -23489,66 +23490,54 @@
}
public final class GnssAntennaInfo implements android.os.Parcelable {
- ctor public GnssAntennaInfo(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates, @Nullable android.location.GnssAntennaInfo.PhaseCenterVariationCorrections, @Nullable android.location.GnssAntennaInfo.SignalGainCorrections);
method public int describeContents();
- method public double getCarrierFrequencyMHz();
- method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates();
- method @Nullable public android.location.GnssAntennaInfo.PhaseCenterVariationCorrections getPhaseCenterVariationCorrections();
- method @Nullable public android.location.GnssAntennaInfo.SignalGainCorrections getSignalGainCorrections();
+ method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
+ method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
}
- public abstract static class GnssAntennaInfo.Callback {
- ctor public GnssAntennaInfo.Callback();
+ public static class GnssAntennaInfo.Builder {
+ ctor public GnssAntennaInfo.Builder();
+ method @NonNull public android.location.GnssAntennaInfo build();
+ method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ }
+
+ public static interface GnssAntennaInfo.Listener {
method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
- method public void onStatusChanged(int);
- field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
}
- public static final class GnssAntennaInfo.PhaseCenterOffsetCoordinates implements android.os.Parcelable {
- ctor public GnssAntennaInfo.PhaseCenterOffsetCoordinates(double, double, double, double, double, double);
+ public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
method public int describeContents();
- method public double getXCoordMillimeters();
- method public double getXCoordUncertaintyMillimeters();
- method public double getYCoordMillimeters();
- method public double getYCoordUncertaintyMillimeters();
- method public double getZCoordMillimeters();
- method public double getZCoordUncertaintyMillimeters();
+ method @FloatRange public double getXOffsetMm();
+ method @FloatRange public double getXOffsetUncertaintyMm();
+ method @FloatRange public double getYOffsetMm();
+ method @FloatRange public double getYOffsetUncertaintyMm();
+ method @FloatRange public double getZOffsetMm();
+ method @FloatRange public double getZOffsetUncertaintyMm();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
}
- public static final class GnssAntennaInfo.PhaseCenterVariationCorrections implements android.os.Parcelable {
- ctor public GnssAntennaInfo.PhaseCenterVariationCorrections(@NonNull double[][], @NonNull double[][]);
+ public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
method public int describeContents();
- method public double getDeltaPhi();
- method public double getDeltaTheta();
- method public int getNumColumns();
- method public int getNumRows();
- method public double getPhaseCenterVariationCorrectionMillimetersAt(int, int);
- method public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(int, int);
- method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
- method @NonNull public double[][] getRawCorrectionsArray();
+ method @NonNull public double[][] getCorrectionUncertaintiesArray();
+ method @NonNull public double[][] getCorrectionsArray();
+ method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
+ method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterVariationCorrections> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
}
- public static final class GnssAntennaInfo.SignalGainCorrections implements android.os.Parcelable {
- ctor public GnssAntennaInfo.SignalGainCorrections(@NonNull double[][], @NonNull double[][]);
- method public int describeContents();
- method public double getDeltaPhi();
- method public double getDeltaTheta();
- method public int getNumColumns();
- method public int getNumRows();
- method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
- method @NonNull public double[][] getRawCorrectionsArray();
- method public double getSignalGainCorrectionDbiAt(int, int);
- method public double getSignalGainCorrectionUncertaintyDbiAt(int, int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SignalGainCorrections> CREATOR;
+ public final class GnssCapabilities {
+ method public boolean hasGnssAntennaInfo();
}
public final class GnssClock implements android.os.Parcelable {
@@ -23859,6 +23848,7 @@
method @NonNull public java.util.List<java.lang.String> getAllProviders();
method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
method @Nullable public String getGnssHardwareModelName();
method public int getGnssYearOfHardware();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
@@ -23868,7 +23858,7 @@
method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
method public boolean isLocationEnabled();
method public boolean isProviderEnabled(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerAntennaInfoCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
@@ -23900,7 +23890,7 @@
method public void setTestProviderEnabled(@NonNull String, boolean);
method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
- method public void unregisterAntennaInfoCallback(@NonNull android.location.GnssAntennaInfo.Callback);
+ method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
@@ -31744,7 +31734,7 @@
method public android.net.wifi.hotspot2.pps.Credential getCredential();
method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
method public long getSubscriptionExpirationTimeMillis();
- method @NonNull public String getUniqueId() throws java.lang.IllegalStateException;
+ method @NonNull public String getUniqueId();
method public boolean isOsuProvisioned();
method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
@@ -43403,11 +43393,12 @@
public abstract class ControlsProviderService extends android.app.Service {
ctor public ControlsProviderService();
- method public abstract void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
- method public void loadSuggestedControls(int, @NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
+ method @Deprecated public void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void performControlAction(@NonNull String, @NonNull android.service.controls.actions.ControlAction, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherFor(@NonNull java.util.List<java.lang.String>);
+ method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForAllAvailable();
+ method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForSuggested();
field public static final String SERVICE_CONTROLS = "android.service.controls.ControlsProviderService";
field @NonNull public static final String TAG = "ControlsProviderService";
}
@@ -46813,59 +46804,6 @@
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_INT = "ims.wifi_off_deferring_time_int";
}
- public static final class CarrierConfigManager.Iwlan {
- field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
- field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
- field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
- field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
- field public static final int DH_GROUP_NONE = 0; // 0x0
- field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
- field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
- field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
- field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
- field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
- field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
- field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
- field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
- field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
- field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
- field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
- field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
- field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
- field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
- field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
- field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
- field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
- field public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.child_encryption_aes_ctr_key_size_int_array";
- field public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY = "iwlan.diffie_hellman_groups_int_array";
- field public static final String KEY_DPD_TIMER_SEC_INT = "iwlan.dpd_timer_sec_int";
- field public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY = "iwlan.epdg_address_priority_int_array";
- field public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT = "iwlan.epdg_authentication_method_int";
- field public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING = "iwlan.epdg_static_address_roaming_string";
- field public static final String KEY_EPDG_STATIC_ADDRESS_STRING = "iwlan.epdg_static_address_string";
- field public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL = "iwlan.ike_fragmentation_enabled_bool";
- field public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT = "iwlan.ike_rekey_hard_timer_in_sec";
- field public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT = "iwlan.ike_rekey_soft_timer_sec_int";
- field public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_cbc_key_size_int_array";
- field public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_aes_ctr_key_size_int_array";
- field public static final int KEY_LEN_AES_128 = 128; // 0x80
- field public static final int KEY_LEN_AES_192 = 192; // 0xc0
- field public static final int KEY_LEN_AES_256 = 256; // 0x100
- field public static final int KEY_LEN_UNUSED = 0; // 0x0
- field public static final String KEY_MAX_RETRIES_INT = "iwlan.max_retries_int";
- field public static final String KEY_MCC_MNCS_STRING_ARRAY = "iwlan.mcc_mncs_string_array";
- field public static final String KEY_NATT_ENABLED_BOOL = "iwlan.natt_enabled_bool";
- field public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT = "iwlan.natt_keep_alive_timer_sec_int";
- field public static final String KEY_PREFIX = "iwlan.";
- field public static final String KEY_RETRANSMIT_TIMER_SEC_INT = "iwlan.retransmit_timer_sec_int";
- field public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_child_session_encryption_algorithms_int_array";
- field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
- field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
- field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
- field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
- field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
- }
-
public abstract class CellIdentity implements android.os.Parcelable {
method public int describeContents();
method @Nullable public CharSequence getOperatorAlphaLong();
diff --git a/api/system-current.txt b/api/system-current.txt
index 7b8f717..202a939 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -376,6 +376,7 @@
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
field public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
+ field public static final String OPSTR_ACCESS_CALL_AUDIO = "android:access_call_audio";
field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
field public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
field public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
@@ -3823,7 +3824,6 @@
public final class GnssCapabilities {
method public boolean hasGeofencing();
- method public boolean hasGnssAntennaInfo();
method public boolean hasLowPowerMode();
method public boolean hasMeasurementCorrections();
method public boolean hasMeasurementCorrectionsExcessPathLength();
@@ -4163,7 +4163,6 @@
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @Nullable public String getExtraLocationControllerPackage();
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
- method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GnssCapabilities getGnssCapabilities();
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
method public boolean isExtraLocationControllerPackageEnabled();
method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
@@ -9769,6 +9768,7 @@
field public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
+ field public static final String AUTO_REVOKE_DISABLED = "auto_revoke_disabled";
field public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
field public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
field public static final String DOZE_ALWAYS_ON = "doze_always_on";
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 9ed4798..8f02f15 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1035,10 +1035,12 @@
public static final int OP_ACTIVATE_PLATFORM_VPN = 94;
/** @hide */
public static final int OP_LOADER_USAGE_STATS = 95;
+ /** @hide Access telephony call audio */
+ public static final int OP_ACCESS_CALL_AUDIO = 96;
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 96;
+ public static final int _NUM_OP = 97;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1329,6 +1331,9 @@
@SystemApi
public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
"android:manage_external_storage";
+ /** @hide Access telephony call audio */
+ @SystemApi
+ public static final String OPSTR_ACCESS_CALL_AUDIO = "android:access_call_audio";
/** @hide Communicate cross-profile within the same profile group. */
@SystemApi
@@ -1418,6 +1423,7 @@
OP_MANAGE_EXTERNAL_STORAGE,
OP_INTERACT_ACROSS_PROFILES,
OP_LOADER_USAGE_STATS,
+ OP_ACCESS_CALL_AUDIO,
};
/**
@@ -1525,6 +1531,7 @@
OP_INTERACT_ACROSS_PROFILES, //INTERACT_ACROSS_PROFILES
OP_ACTIVATE_PLATFORM_VPN, // ACTIVATE_PLATFORM_VPN
OP_LOADER_USAGE_STATS, // LOADER_USAGE_STATS
+ OP_ACCESS_CALL_AUDIO, // ACCESS_CALL_AUDIO
};
/**
@@ -1627,6 +1634,7 @@
OPSTR_INTERACT_ACROSS_PROFILES,
OPSTR_ACTIVATE_PLATFORM_VPN,
OPSTR_LOADER_USAGE_STATS,
+ OPSTR_ACCESS_CALL_AUDIO,
};
/**
@@ -1730,6 +1738,7 @@
"INTERACT_ACROSS_PROFILES",
"ACTIVATE_PLATFORM_VPN",
"LOADER_USAGE_STATS",
+ "ACCESS_CALL_AUDIO",
};
/**
@@ -1834,6 +1843,7 @@
android.Manifest.permission.INTERACT_ACROSS_PROFILES,
null, // no permission for OP_ACTIVATE_PLATFORM_VPN
android.Manifest.permission.LOADER_USAGE_STATS,
+ Manifest.permission.ACCESS_CALL_AUDIO,
};
/**
@@ -1938,6 +1948,7 @@
null, // INTERACT_ACROSS_PROFILES
null, // ACTIVATE_PLATFORM_VPN
null, // LOADER_USAGE_STATS
+ null, // ACCESS_CALL_AUDIO
};
/**
@@ -2041,6 +2052,7 @@
false, // INTERACT_ACROSS_PROFILES
false, // ACTIVATE_PLATFORM_VPN
false, // LOADER_USAGE_STATS
+ false, // ACCESS_CALL_AUDIO
};
/**
@@ -2143,6 +2155,7 @@
AppOpsManager.MODE_DEFAULT, // INTERACT_ACROSS_PROFILES
AppOpsManager.MODE_IGNORED, // ACTIVATE_PLATFORM_VPN
AppOpsManager.MODE_DEFAULT, // LOADER_USAGE_STATS
+ AppOpsManager.MODE_DEFAULT, // ACCESS_CALL_AUDIO
};
/**
@@ -2249,6 +2262,7 @@
false, // INTERACT_ACROSS_PROFILES
false, // ACTIVATE_PLATFORM_VPN
false, // LOADER_USAGE_STATS
+ false, // ACCESS_CALL_AUDIO
};
/**
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 130e2ec..6b1afda 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -256,10 +256,10 @@
};
@DataClass.Generated(
- time = 1580158740502L,
+ time = 1581728574427L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=95L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=96L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index 0287564..8eb7e72 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -19,7 +19,6 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
-import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
@@ -48,8 +47,8 @@
public abstract class SharedElementCallback {
private Matrix mTempMatrix;
private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap";
- private static final String BUNDLE_SNAPSHOT_GRAPHIC_BUFFER =
- "sharedElement:snapshot:graphicBuffer";
+ private static final String BUNDLE_SNAPSHOT_HARDWARE_BUFFER =
+ "sharedElement:snapshot:hardwareBuffer";
private static final String BUNDLE_SNAPSHOT_COLOR_SPACE = "sharedElement:snapshot:colorSpace";
private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType";
private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
@@ -186,8 +185,8 @@
if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
} else {
- GraphicBuffer graphicBuffer = bitmap.createGraphicBufferHandle();
- bundle.putParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER, graphicBuffer);
+ HardwareBuffer hardwareBuffer = bitmap.getHardwareBuffer();
+ bundle.putParcelable(BUNDLE_SNAPSHOT_HARDWARE_BUFFER, hardwareBuffer);
ColorSpace cs = bitmap.getColorSpace();
if (cs != null) {
bundle.putInt(BUNDLE_SNAPSHOT_COLOR_SPACE, cs.getId());
@@ -235,7 +234,7 @@
View view = null;
if (snapshot instanceof Bundle) {
Bundle bundle = (Bundle) snapshot;
- GraphicBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER);
+ HardwareBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_HARDWARE_BUFFER);
Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
if (buffer == null && bitmap == null) {
return null;
@@ -246,8 +245,7 @@
if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) {
colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]);
}
- bitmap = Bitmap.wrapHardwareBuffer(HardwareBuffer.createFromGraphicBuffer(buffer),
- colorSpace);
+ bitmap = Bitmap.wrapHardwareBuffer(buffer, colorSpace);
}
ImageView imageView = new ImageView(context);
view = imageView;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f1559f7..be87f5c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -186,6 +186,7 @@
import android.telephony.TelephonyRegistryManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Slog;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.WindowManager;
@@ -222,6 +223,8 @@
public final class SystemServiceRegistry {
private static final String TAG = "SystemServiceRegistry";
+ private static final boolean ENABLE_SERVICE_NOT_FOUND_WTF = true;
+
// Service registry information.
// This information is never changed once static initialization has completed.
private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
@@ -1373,8 +1376,29 @@
* @hide
*/
public static Object getSystemService(ContextImpl ctx, String name) {
- ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
- return fetcher != null ? fetcher.getService(ctx) : null;
+ if (name == null) {
+ return null;
+ }
+ final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
+ if (ENABLE_SERVICE_NOT_FOUND_WTF && fetcher == null) {
+ // This should be a caller bug.
+ Slog.wtf(TAG, "Unknown manager requested: " + name);
+ return null;
+ }
+
+ final Object ret = fetcher.getService(ctx);
+ if (ENABLE_SERVICE_NOT_FOUND_WTF && ret == null) {
+ // Some services do return null in certain situations, so don't do WTF for them.
+ switch (name) {
+ case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
+ case Context.APP_PREDICTION_SERVICE:
+ case Context.INCREMENTAL_SERVICE:
+ return null;
+ }
+ Slog.wtf(TAG, "Manager wrapper not available: " + name);
+ return null;
+ }
+ return ret;
}
/**
@@ -1382,7 +1406,15 @@
* @hide
*/
public static String getSystemServiceName(Class<?> serviceClass) {
- return SYSTEM_SERVICE_NAMES.get(serviceClass);
+ if (serviceClass == null) {
+ return null;
+ }
+ final String serviceName = SYSTEM_SERVICE_NAMES.get(serviceClass);
+ if (ENABLE_SERVICE_NOT_FOUND_WTF && serviceName == null) {
+ // This should be a caller bug.
+ Slog.wtf(TAG, "Unknown manager requested: " + serviceClass.getCanonicalName());
+ }
+ return serviceName;
}
/**
@@ -1679,7 +1711,9 @@
try {
cache.wait();
} catch (InterruptedException e) {
- Log.w(TAG, "getService() interrupted");
+ // This shouldn't normally happen, but if someone interrupts the
+ // thread, it will.
+ Slog.wtf(TAG, "getService() interrupted");
Thread.currentThread().interrupt();
return null;
}
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 4bd31f8..a2def7f 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.os.IVold;
+import java.util.Set;
+
/**
* Mount service local interface.
*
@@ -98,6 +100,12 @@
}
/**
+ * Check if fuse is running in target user, if it's running then setup its obb directories.
+ * TODO: System server should store a list of active pids that obb is not mounted and use it.
+ */
+ public abstract void prepareObbDirs(int userId, Set<String> packageList, String processName);
+
+ /**
* Add a listener to listen to reset event in StorageManagerService.
*
* @param listener The listener that will be notified on reset events.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4523acb..9511152 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8760,6 +8760,13 @@
"location_permissions_upgrade_to_q_mode";
/**
+ * Whether or not the system Auto Revoke feature is disabled.
+ * @hide
+ */
+ @SystemApi
+ public static final String AUTO_REVOKE_DISABLED = "auto_revoke_disabled";
+
+ /**
* Map of android.theme.customization.* categories to the enabled overlay package for that
* category, formatted as a serialized {@link org.json.JSONObject}. If there is no
* corresponding package included for a category, then all overlay packages in that
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index de4c056..cb20db9 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -16,6 +16,7 @@
package android.service.controls;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
@@ -34,7 +35,6 @@
import com.android.internal.util.Preconditions;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Flow.Publisher;
@@ -70,25 +70,48 @@
* Retrieve all available controls, using the stateless builder
* {@link Control.StatelessBuilder} to build each Control, then use the
* provided consumer to callback to the call originator.
+ *
+ * @deprecated Removing consumer-based load apis. Use publisherForAllAvailable() instead
*/
- public abstract void loadAvailableControls(@NonNull Consumer<List<Control>> consumer);
-
- /**
- * (Optional) The service may be asked to provide a small number of recommended controls, in
- * order to suggest some controls to the user for favoriting. The controls shall be built using
- * the stateless builder {@link Control.StatelessBuilder}, followed by an invocation to the
- * provided consumer to callback to the call originator. If the number of controls
- * is greater than maxNumber, the list will be truncated.
- */
- public void loadSuggestedControls(int maxNumber, @NonNull Consumer<List<Control>> consumer) {
- // Override to change the default behavior
+ @Deprecated
+ public void loadAvailableControls(@NonNull Consumer<List<Control>> consumer) {
+ // pending removal
consumer.accept(Collections.emptyList());
}
/**
- * Return a valid Publisher for the given controlIds. This publisher will be asked
- * to provide updates for the given list of controlIds as long as the Subscription
- * is valid.
+ * Publisher for all available controls
+ *
+ * Retrieve all available controls. Use the stateless builder {@link Control.StatelessBuilder}
+ * to build each Control. Call {@link Subscriber#onComplete} when done loading all unique
+ * controls, or {@link Subscriber#onError} for error scenarios. Duplicate Controls will
+ * replace the original.
+ */
+ @Nullable
+ public Publisher<Control> publisherForAllAvailable() {
+ // will be abstract and @nonnull when consumers are removed
+ return null;
+ }
+
+ /**
+ * (Optional) Publisher for suggested controls
+ *
+ * The service may be asked to provide a small number of recommended controls, in
+ * order to suggest some controls to the user for favoriting. The controls shall be built using
+ * the stateless builder {@link Control.StatelessBuilder}. The number of controls requested
+ * through {@link Subscription#request} will be limited. Call {@link Subscriber#onComplete}
+ * when done, or {@link Subscriber#onError} for error scenarios.
+ */
+ @Nullable
+ public Publisher<Control> publisherForSuggested() {
+ return null;
+ }
+
+ /**
+ * Return a valid Publisher for the given controlIds. This publisher will be asked to provide
+ * updates for the given list of controlIds as long as the {@link Subscription} is valid.
+ * Calls to {@link Subscriber#onComplete} will not be expected. Instead, wait for the call from
+ * {@link Subscription#cancel} to indicate that updates are no longer required.
*/
@NonNull
public abstract Publisher<Control> publisherFor(@NonNull List<String> controlIds);
@@ -113,13 +136,13 @@
mToken = bundle.getBinder(CALLBACK_TOKEN);
return new IControlsProvider.Stub() {
- public void load(IControlsLoadCallback cb) {
- mHandler.obtainMessage(RequestHandler.MSG_LOAD, cb).sendToTarget();
+ public void load(IControlsSubscriber subscriber) {
+ mHandler.obtainMessage(RequestHandler.MSG_LOAD, subscriber).sendToTarget();
}
- public void loadSuggested(int maxNumber, IControlsLoadCallback cb) {
- LoadMessage msg = new LoadMessage(maxNumber, cb);
- mHandler.obtainMessage(RequestHandler.MSG_LOAD_SUGGESTED, msg).sendToTarget();
+ public void loadSuggested(IControlsSubscriber subscriber) {
+ mHandler.obtainMessage(RequestHandler.MSG_LOAD_SUGGESTED, subscriber)
+ .sendToTarget();
}
public void subscribe(List<String> controlIds,
@@ -148,73 +171,56 @@
private static final int MSG_ACTION = 3;
private static final int MSG_LOAD_SUGGESTED = 4;
- /**
- * This the maximum number of controls that can be loaded via
- * {@link ControlsProviderService#loadAvailablecontrols}. Anything over this number
- * will be truncated.
- */
- private static final int MAX_NUMBER_OF_CONTROLS_ALLOWED = 1000;
-
RequestHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
switch(msg.what) {
- case MSG_LOAD:
- final IControlsLoadCallback cb = (IControlsLoadCallback) msg.obj;
- ControlsProviderService.this.loadAvailableControls(consumerFor(
- MAX_NUMBER_OF_CONTROLS_ALLOWED, cb));
- break;
+ case MSG_LOAD: {
+ final IControlsSubscriber cs = (IControlsSubscriber) msg.obj;
+ final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);
- case MSG_LOAD_SUGGESTED:
- final LoadMessage lMsg = (LoadMessage) msg.obj;
- ControlsProviderService.this.loadSuggestedControls(lMsg.mMaxNumber,
- consumerFor(lMsg.mMaxNumber, lMsg.mCb));
+ Publisher<Control> publisher =
+ ControlsProviderService.this.publisherForAllAvailable();
+ if (publisher == null) {
+ ControlsProviderService.this.loadAvailableControls(consumerFor(proxy));
+ } else {
+ publisher.subscribe(proxy);
+ }
break;
+ }
- case MSG_SUBSCRIBE:
+ case MSG_LOAD_SUGGESTED: {
+ final IControlsSubscriber cs = (IControlsSubscriber) msg.obj;
+ final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);
+
+ Publisher<Control> publisher =
+ ControlsProviderService.this.publisherForSuggested();
+ if (publisher == null) {
+ Log.i(TAG, "No publisher provided for suggested controls");
+ proxy.onComplete();
+ } else {
+ publisher.subscribe(proxy);
+ }
+ break;
+ }
+
+ case MSG_SUBSCRIBE: {
final SubscribeMessage sMsg = (SubscribeMessage) msg.obj;
- final IControlsSubscriber cs = sMsg.mSubscriber;
- Subscriber<Control> s = new Subscriber<Control>() {
- public void onSubscribe(Subscription subscription) {
- try {
- cs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
- } catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
- }
- }
- public void onNext(@NonNull Control statefulControl) {
- Preconditions.checkNotNull(statefulControl);
- try {
- cs.onNext(mToken, statefulControl);
- } catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
- }
- }
- public void onError(Throwable t) {
- try {
- cs.onError(mToken, t.toString());
- } catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
- }
- }
- public void onComplete() {
- try {
- cs.onComplete(mToken);
- } catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
- }
- }
- };
- ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(s);
- break;
+ final SubscriberProxy proxy = new SubscriberProxy(false, mToken,
+ sMsg.mSubscriber);
- case MSG_ACTION:
+ ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(proxy);
+ break;
+ }
+
+ case MSG_ACTION: {
final ActionMessage aMsg = (ActionMessage) msg.obj;
ControlsProviderService.this.performControlAction(aMsg.mControlId,
aMsg.mAction, consumerFor(aMsg.mControlId, aMsg.mCb));
break;
+ }
}
}
@@ -234,39 +240,88 @@
};
}
- private Consumer<List<Control>> consumerFor(int maxNumber, IControlsLoadCallback cb) {
- return (@NonNull List<Control> controls) -> {
+ /**
+ * Method will be removed during migration to publisher
+ */
+ private Consumer<List<Control>> consumerFor(final Subscriber<Control> subscriber) {
+ return (@NonNull final List<Control> controls) -> {
Preconditions.checkNotNull(controls);
- if (controls.size() > maxNumber) {
- Log.w(TAG, "Too many controls. Provided: " + controls.size() + ", Max allowed: "
- + maxNumber + ". Truncating the list.");
- controls = controls.subList(0, maxNumber);
- }
- List<Control> list = new ArrayList<>();
- for (Control control: controls) {
- if (control == null) {
- Log.e(TAG, "onLoad: null control.");
- }
- if (isStatelessControl(control)) {
- list.add(control);
- } else {
- Log.w(TAG, "onLoad: control is not stateless.");
- list.add(new Control.StatelessBuilder(control).build());
- }
- }
- try {
- cb.accept(mToken, list);
- } catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
- }
+ subscriber.onSubscribe(new Subscription() {
+ public void request(long n) {
+ for (Control control: controls) {
+ Control c;
+ if (control == null) {
+ Log.e(TAG, "onLoad: null control.");
+ }
+ if (isStatelessControl(control)) {
+ c = control;
+ } else {
+ Log.w(TAG, "onLoad: control is not stateless.");
+ c = new Control.StatelessBuilder(control).build();
+ }
+
+ subscriber.onNext(c);
+ }
+ subscriber.onComplete();
+ }
+
+ public void cancel() {}
+ });
};
}
+ }
- private boolean isStatelessControl(Control control) {
- return (control.getStatus() == Control.STATUS_UNKNOWN
- && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
- && TextUtils.isEmpty(control.getStatusText()));
+ private static boolean isStatelessControl(Control control) {
+ return (control.getStatus() == Control.STATUS_UNKNOWN
+ && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
+ && TextUtils.isEmpty(control.getStatusText()));
+ }
+
+ private static class SubscriberProxy implements Subscriber<Control> {
+ private IBinder mToken;
+ private IControlsSubscriber mCs;
+ private boolean mEnforceStateless;
+
+ SubscriberProxy(boolean enforceStateless, IBinder token, IControlsSubscriber cs) {
+ mEnforceStateless = enforceStateless;
+ mToken = token;
+ mCs = cs;
+ }
+
+ public void onSubscribe(Subscription subscription) {
+ try {
+ mCs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ public void onNext(@NonNull Control control) {
+ Preconditions.checkNotNull(control);
+ try {
+ if (mEnforceStateless && !isStatelessControl(control)) {
+ Log.w(TAG, "onNext(): control is not stateless. Use the "
+ + "Control.StatelessBuilder() to build the control.");
+ control = new Control.StatelessBuilder(control).build();
+ }
+ mCs.onNext(mToken, control);
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ public void onError(Throwable t) {
+ try {
+ mCs.onError(mToken, t.toString());
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ public void onComplete() {
+ try {
+ mCs.onComplete(mToken);
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
}
}
@@ -307,14 +362,4 @@
this.mSubscriber = subscriber;
}
}
-
- private static class LoadMessage {
- final int mMaxNumber;
- final IControlsLoadCallback mCb;
-
- LoadMessage(int maxNumber, IControlsLoadCallback cb) {
- this.mMaxNumber = maxNumber;
- this.mCb = cb;
- }
- }
}
diff --git a/core/java/android/service/controls/IControlsLoadCallback.aidl b/core/java/android/service/controls/IControlsLoadCallback.aidl
deleted file mode 100644
index bfc61cd..0000000
--- a/core/java/android/service/controls/IControlsLoadCallback.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls;
-
-import android.service.controls.Control;
-
-/**
- * @hide
- */
-oneway interface IControlsLoadCallback {
- void accept(in IBinder token, in List<Control> controls);
-}
\ No newline at end of file
diff --git a/core/java/android/service/controls/IControlsProvider.aidl b/core/java/android/service/controls/IControlsProvider.aidl
index 4375fbb..0cb06b4 100644
--- a/core/java/android/service/controls/IControlsProvider.aidl
+++ b/core/java/android/service/controls/IControlsProvider.aidl
@@ -17,7 +17,6 @@
package android.service.controls;
import android.service.controls.IControlsActionCallback;
-import android.service.controls.IControlsLoadCallback;
import android.service.controls.IControlsSubscriber;
import android.service.controls.actions.ControlActionWrapper;
@@ -25,9 +24,9 @@
* @hide
*/
oneway interface IControlsProvider {
- void load(IControlsLoadCallback cb);
+ void load(IControlsSubscriber subscriber);
- void loadSuggested(int maxNumber, IControlsLoadCallback cb);
+ void loadSuggested(IControlsSubscriber subscriber);
void subscribe(in List<String> controlIds,
IControlsSubscriber subscriber);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 12f245e..9de1222 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6012,7 +6012,13 @@
@VisibleForTesting
public class InsertionPointCursorController implements CursorController {
private InsertionHandleView mHandle;
+ // Tracks whether the cursor is currently being dragged.
private boolean mIsDraggingCursor;
+ // During a drag, tracks whether the user's finger has adjusted to be over the handle rather
+ // than the cursor bar.
+ private boolean mIsTouchSnappedToHandleDuringDrag;
+ // During a drag, tracks the line of text where the cursor was last positioned.
+ private int mPrevLineDuringDrag;
public void onTouchEvent(MotionEvent event) {
if (hasSelectionController() && getSelectionController().isCursorBeingModified()) {
@@ -6043,8 +6049,8 @@
}
private void positionCursorDuringDrag(MotionEvent event) {
- int line = mTextView.getLineAtCoordinate(event.getY());
- int offset = mTextView.getOffsetAtCoordinate(line, event.getX());
+ mPrevLineDuringDrag = getLineDuringDrag(event);
+ int offset = mTextView.getOffsetAtCoordinate(mPrevLineDuringDrag, event.getX());
int oldSelectionStart = mTextView.getSelectionStart();
int oldSelectionEnd = mTextView.getSelectionEnd();
if (offset == oldSelectionStart && offset == oldSelectionEnd) {
@@ -6057,11 +6063,58 @@
}
}
+ /**
+ * Returns the line where the cursor should be positioned during a cursor drag. Rather than
+ * simply returning the line directly at the touch position, this function has the following
+ * additional logic:
+ * 1) Apply some slop to avoid switching lines if the touch moves just slightly off the
+ * current line.
+ * 2) Allow the user's finger to slide down and "snap" to the handle to provide better
+ * visibility of the cursor and text.
+ */
+ private int getLineDuringDrag(MotionEvent event) {
+ final Layout layout = mTextView.getLayout();
+ if (mTouchState.isOnHandle()) {
+ // The drag was initiated from the handle, so no need to apply the snap logic. See
+ // InsertionHandleView.touchThrough().
+ return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
+ }
+ if (mIsTouchSnappedToHandleDuringDrag) {
+ float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
+ return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
+ }
+ int line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
+ if (mPrevLineDuringDrag == UNSET_LINE || line <= mPrevLineDuringDrag) {
+ // User's finger is on the same line or moving up; continue positioning the cursor
+ // directly at the touch location.
+ return line;
+ }
+ // User's finger is moving downwards; delay jumping to the lower line to allow the
+ // touch to move to the handle.
+ float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
+ line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
+ if (line < mPrevLineDuringDrag) {
+ return mPrevLineDuringDrag;
+ }
+ // User's finger is now over the handle, at the ideal offset from the cursor. From now
+ // on, position the cursor higher up from the actual touch location so that the user's
+ // finger stays "snapped" to the handle. This provides better visibility of the text.
+ mIsTouchSnappedToHandleDuringDrag = true;
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("InsertionPointCursorController",
+ "snapped touch to handle: eventY=%d, cursorY=%d, mLastLine=%d, line=%d",
+ (int) event.getY(), (int) cursorY, mPrevLineDuringDrag, line);
+ }
+ return line;
+ }
+
private void startCursorDrag(MotionEvent event) {
if (TextView.DEBUG_CURSOR) {
logCursor("InsertionPointCursorController", "start cursor drag");
}
mIsDraggingCursor = true;
+ mIsTouchSnappedToHandleDuringDrag = false;
+ mPrevLineDuringDrag = UNSET_LINE;
// We don't want the parent scroll/long-press handlers to take over while dragging.
mTextView.getParent().requestDisallowInterceptTouchEvent(true);
mTextView.cancelLongPress();
@@ -6084,6 +6137,8 @@
logCursor("InsertionPointCursorController", "end cursor drag");
}
mIsDraggingCursor = false;
+ mIsTouchSnappedToHandleDuringDrag = false;
+ mPrevLineDuringDrag = UNSET_LINE;
// Hide the magnifier and set the handle to be hidden after a delay.
getHandle().dismissMagnifier();
getHandle().hideAfterDelay();
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d91911c..e4141e0 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -105,10 +105,12 @@
using namespace std::placeholders;
using android::String8;
+using android::base::ReadFileToString;
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::base::GetBoolProperty;
+using android::base::GetProperty;
#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
append(StringPrintf(__VA_ARGS__))
@@ -174,6 +176,12 @@
static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.zygote.app_data_isolation";
+/**
+ * Property to enable app data isolation for sdcard obb or data in vold.
+ */
+static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.sys.vold_app_data_isolation_enabled";
+
static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
@@ -603,6 +611,15 @@
}
}
+static bool IsFilesystemSupported(const std::string& fsType) {
+ std::string supported;
+ if (!ReadFileToString("/proc/filesystems", &supported)) {
+ ALOGE("Failed to read supported filesystems");
+ return false;
+ }
+ return supported.find(fsType + "\n") != std::string::npos;
+}
+
static void PreApplicationInit() {
// The child process sets this to indicate it's not the zygote.
android_mallopt(M_SET_ZYGOTE_CHILD, nullptr, 0);
@@ -782,6 +799,31 @@
}
}
+static void BindMountObbPackage(std::string_view package_name, int userId, fail_fn_t fail_fn) {
+
+ // TODO(148772775): Pass primary volume name from zygote argument to here
+ std::string source;
+ if (IsFilesystemSupported("sdcardfs")) {
+ source = StringPrintf("/mnt/runtime/default/emulated/%d/Android/obb/%s",
+ userId, package_name.data());
+ } else {
+ source = StringPrintf("/mnt/pass_through/%d/emulated/%d/Android/obb/%s",
+ userId, userId, package_name.data());
+ }
+ std::string target(
+ StringPrintf("/storage/emulated/%d/Android/obb/%s", userId, package_name.data()));
+
+ if (access(source.c_str(), F_OK) != 0) {
+ fail_fn(CREATE_ERROR("Cannot access source %s: %s", source.c_str(), strerror(errno)));
+ }
+
+ if (access(target.c_str(), F_OK) != 0) {
+ fail_fn(CREATE_ERROR("Cannot access target %s: %s", target.c_str(), strerror(errno)));
+ }
+
+ BindMount(source, target, fail_fn);
+}
+
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -1504,6 +1546,60 @@
}
}
+// Bind mount all obb directories that are visible to this app.
+// If app data isolation is not enabled for this process, bind mount the whole obb
+// directory instead.
+static void BindMountAppObbDirs(JNIEnv* env, jobjectArray pkg_data_info_list,
+ uid_t uid, const char* process_name, jstring managed_nice_name, fail_fn_t fail_fn) {
+
+ auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+ const userid_t user_id = multiuser_get_user_id(uid);
+
+ // If FUSE is not ready for this user, skip it
+ // TODO(148772775): Pass primary volume name from zygote argument to here
+ std::string tmp = GetProperty("vold.fuse_running_users", "");
+ std::istringstream fuse_running_users(tmp);
+ bool user_found = false;
+ std::string s;
+ std::string user_id_str = std::to_string(user_id);
+ while (!user_found && std::getline(fuse_running_users, s, ',')) {
+ if (user_id_str == s) {
+ user_found = true;
+ }
+ }
+ if (!user_found) {
+ ALOGI("User %d is not running fuse yet, fuse_running_users=%s", user_id, tmp.c_str());
+ return;
+ }
+
+ // Fuse is ready, so we can start using fuse path.
+ int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+
+ if (size == 0) {
+ // App data isolation is not enabled for this process, so we bind mount to whole obb/ dir.
+ std::string source;
+ if (IsFilesystemSupported("sdcardfs")) {
+ source = StringPrintf("/mnt/runtime/default/emulated/%d/Android/obb", user_id);
+ } else {
+ source = StringPrintf("/mnt/pass_through/%d/emulated/%d/Android/obb", user_id, user_id);
+ }
+ std::string target(StringPrintf("/storage/emulated/%d/Android/obb", user_id));
+
+ if (access(source.c_str(), F_OK) != 0) {
+ fail_fn(CREATE_ERROR("Error accessing %s: %s", source.c_str(), strerror(errno)));
+ }
+ BindMount(source, target, fail_fn);
+ return;
+ }
+
+ // Bind mount each package obb directory
+ for (int i = 0; i < size; i += 3) {
+ jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
+ std::string packageName = extract_fn(package_str).value();
+ BindMountObbPackage(packageName, user_id, fail_fn);
+ }
+}
+
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
@@ -1552,6 +1648,12 @@
isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
}
+ if ((mount_external != MOUNT_EXTERNAL_INSTALLER) &&
+ GetBoolProperty(kPropFuse, false) &&
+ GetBoolProperty(ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false)) {
+ BindMountAppObbDirs(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+ }
+
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
if (!is_system_server && getuid() == 0) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c9fb25e..62e57e4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1200,6 +1200,15 @@
android:description="@string/permdesc_acceptHandovers"
android:protectionLevel="dangerous" />
+ <!-- Allows an application assigned to the Dialer role to be granted access to the telephony
+ call audio streams, both TX and RX.
+ <p>Protection level: signature|appop
+ -->
+ <permission android:name="android.permission.ACCESS_CALL_AUDIO"
+ android.label="@string/permlab_accessCallAudio"
+ android:description="@string/permdesc_accessCallAudio"
+ android:protectionLevel="signature|appop" />
+
<!-- ====================================================================== -->
<!-- Permissions for accessing the device microphone -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e6a93e5..d513e2b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5364,4 +5364,9 @@
<string name="resolver_no_apps_available_explanation">We couldn\u2019t find any apps</string>
<!-- Button which switches on the disabled work profile [CHAR LIMIT=NONE] -->
<string name="resolver_switch_on_work">Switch on work</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permlab_accessCallAudio">Record or play audio in telephony calls</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_accessCallAudio">Allows this app, when assigned as default dialer application, to record or play audio in telephony calls.</string>
</resources>
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
index a24b4e0..78c88d7 100644
--- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -62,8 +63,6 @@
@Mock
private IControlsActionCallback.Stub mActionCallback;
@Mock
- private IControlsLoadCallback.Stub mLoadCallback;
- @Mock
private IControlsSubscriber.Stub mSubscriber;
@Mock
private IIntentSender mIIntentSender;
@@ -79,8 +78,6 @@
when(mActionCallback.asBinder()).thenCallRealMethod();
when(mActionCallback.queryLocalInterface(any())).thenReturn(mActionCallback);
- when(mLoadCallback.asBinder()).thenCallRealMethod();
- when(mLoadCallback.queryLocalInterface(any())).thenReturn(mLoadCallback);
when(mSubscriber.asBinder()).thenCallRealMethod();
when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber);
@@ -102,22 +99,28 @@
Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
.setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
- @SuppressWarnings("unchecked")
- ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+ ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+ ArgumentCaptor<Control> controlCaptor =
+ ArgumentCaptor.forClass(Control.class);
ArrayList<Control> list = new ArrayList<>();
list.add(control1);
list.add(control2);
mControlsProviderService.setControls(list);
- mControlsProvider.load(mLoadCallback);
+ mControlsProvider.load(mSubscriber);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- verify(mLoadCallback).accept(eq(mToken), captor.capture());
- List<Control> l = captor.getValue();
- assertEquals(2, l.size());
- assertTrue(equals(control1, l.get(0)));
- assertTrue(equals(control2, l.get(1)));
+ verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+ subscriptionCaptor.getValue().request(1000);
+
+ verify(mSubscriber, times(2)).onNext(eq(mToken), controlCaptor.capture());
+ List<Control> values = controlCaptor.getAllValues();
+ assertTrue(equals(values.get(0), list.get(0)));
+ assertTrue(equals(values.get(1), list.get(1)));
+
+ verify(mSubscriber).onComplete(eq(mToken));
}
@Test
@@ -128,50 +131,57 @@
.build();
Control statelessControl = new Control.StatelessBuilder(control).build();
- @SuppressWarnings("unchecked")
- ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+ ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+ ArgumentCaptor<Control> controlCaptor =
+ ArgumentCaptor.forClass(Control.class);
ArrayList<Control> list = new ArrayList<>();
list.add(control);
mControlsProviderService.setControls(list);
- mControlsProvider.load(mLoadCallback);
+ mControlsProvider.load(mSubscriber);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- verify(mLoadCallback).accept(eq(mToken), captor.capture());
- List<Control> l = captor.getValue();
- assertEquals(1, l.size());
- assertFalse(equals(control, l.get(0)));
- assertTrue(equals(statelessControl, l.get(0)));
- assertEquals(Control.STATUS_UNKNOWN, l.get(0).getStatus());
+ verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+ subscriptionCaptor.getValue().request(1000);
+
+ verify(mSubscriber).onNext(eq(mToken), controlCaptor.capture());
+ Control c = controlCaptor.getValue();
+ assertFalse(equals(control, c));
+ assertTrue(equals(statelessControl, c));
+ assertEquals(Control.STATUS_UNKNOWN, c.getStatus());
+
+ verify(mSubscriber).onComplete(eq(mToken));
}
@Test
- public void testLoadSuggested_withMaxNumber() throws RemoteException {
+ public void testOnLoadSuggested_allStateless() throws RemoteException {
Control control1 = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
.setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
- @SuppressWarnings("unchecked")
- ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+ ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+ ArgumentCaptor<Control> controlCaptor =
+ ArgumentCaptor.forClass(Control.class);
ArrayList<Control> list = new ArrayList<>();
list.add(control1);
list.add(control2);
- final int maxSuggested = 1;
-
mControlsProviderService.setControls(list);
- mControlsProvider.loadSuggested(maxSuggested, mLoadCallback);
+ mControlsProvider.loadSuggested(mSubscriber);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- verify(mLoadCallback).accept(eq(mToken), captor.capture());
- List<Control> l = captor.getValue();
- assertEquals(maxSuggested, l.size());
+ verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+ subscriptionCaptor.getValue().request(1);
- for (int i = 0; i < maxSuggested; ++i) {
- assertTrue(equals(list.get(i), l.get(i)));
- }
+ verify(mSubscriber).onNext(eq(mToken), controlCaptor.capture());
+ Control c = controlCaptor.getValue();
+ assertTrue(equals(c, list.get(0)));
+
+ verify(mSubscriber).onComplete(eq(mToken));
}
@Test
@@ -244,22 +254,19 @@
}
@Override
- public void loadSuggestedControls(int maxNumber, Consumer<List<Control>> cb) {
- cb.accept(mControls);
- }
-
- @Override
public Publisher<Control> publisherFor(List<String> ids) {
return new Publisher<Control>() {
public void subscribe(final Subscriber s) {
- s.onSubscribe(new Subscription() {
- public void request(long n) {
- for (Control c : mControls) {
- s.onNext(c);
- }
- }
- public void cancel() {}
- });
+ s.onSubscribe(createSubscription(s, mControls));
+ }
+ };
+ }
+
+ @Override
+ public Publisher<Control> publisherForSuggested() {
+ return new Publisher<Control>() {
+ public void subscribe(final Subscriber s) {
+ s.onSubscribe(createSubscription(s, mControls));
}
};
}
@@ -269,7 +276,19 @@
Consumer<Integer> cb) {
cb.accept(ControlAction.RESPONSE_OK);
}
+
+ private Subscription createSubscription(Subscriber s, List<Control> controls) {
+ return new Subscription() {
+ public void request(long n) {
+ int i = 0;
+ for (Control c : mControls) {
+ if (i++ < n) s.onNext(c);
+ else break;
+ }
+ s.onComplete();
+ }
+ public void cancel() {}
+ };
+ }
}
}
-
-
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index a602fa3..d7abfcc 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -25,6 +25,9 @@
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertFalse;
@@ -32,11 +35,14 @@
import android.app.Activity;
import android.app.Instrumentation;
+import android.text.Layout;
+import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -50,9 +56,15 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.atomic.AtomicLong;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class EditorCursorDragTest {
+ private static final String LOG_TAG = EditorCursorDragTest.class.getSimpleName();
+
+ private static final AtomicLong sTicker = new AtomicLong(1);
+
@Rule
public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
TextViewActivity.class);
@@ -119,13 +131,11 @@
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
- // Swipe along a diagonal path. This should drag the cursor.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
-
- // Swipe along a steeper diagonal path. This should still drag the cursor.
+ // Swipe along a diagonal path. This should drag the cursor. Because we snap the finger to
+ // the handle as the touch moves downwards (and because we have some slop to avoid jumping
+ // across lines), the cursor position will end up higher than the finger position.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("1")));
// Swipe right-down along a very steep diagonal path. This should not drag the cursor.
// Normally this would trigger a scroll, but since the full view fits on the screen there
@@ -133,12 +143,15 @@
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
+ // Tap to clear the selection.
+ int index = text.indexOf("line9");
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+ onView(withId(R.id.textview)).check(hasSelection(emptyString()));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+
// Swipe right-up along a very steep diagonal path. This should not drag the cursor.
// Normally this would trigger a scroll, but since the full view fits on the screen there
// is nothing to scroll and the gesture will trigger a selection drag.
- int index = text.indexOf("line9");
- onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
}
@@ -154,13 +167,11 @@
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
- // Swipe along a diagonal path. This should drag the cursor.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
-
- // Swipe along a steeper diagonal path. This should still drag the cursor.
+ // Swipe along a diagonal path. This should drag the cursor. Because we snap the finger to
+ // the handle as the touch moves downwards (and because we have some slop to avoid jumping
+ // across lines), the cursor position will end up higher than the finger position.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("1")));
// Swipe right-down along a very steep diagonal path. This should not drag the cursor.
// Normally this would trigger a scroll up, but since the view is already at the top there
@@ -168,11 +179,14 @@
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
- // Swipe right-up along a very steep diagonal path. This should not drag the cursor. This
- // will trigger a downward scroll and the cursor position will not change.
+ // Tap to clear the selection.
int index = text.indexOf("line9");
onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+ onView(withId(R.id.textview)).check(hasSelection(emptyString()));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+
+ // Swipe right-up along a very steep diagonal path. This should not drag the cursor. This
+ // will trigger a downward scroll and the cursor position will not change.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
}
@@ -387,12 +401,14 @@
assertFalse(editor.getSelectionController().isCursorBeingModified());
}
+ @Suppress // b/149712851
@Test // Reproduces b/147366705
public void testCursorDrag_nonSelectableTextView() throws Throwable {
String text = "Hello world!";
TextView tv = mActivity.findViewById(R.id.nonselectable_textview);
tv.setText(text);
Editor editor = tv.getEditorForTesting();
+ assertThat(editor).isNotNull();
// Simulate a tap. No error should be thrown.
long event1Time = 1001;
@@ -404,6 +420,68 @@
dragOnText(text.indexOf("llo"), text.indexOf("!")));
}
+ @Test
+ public void testCursorDrag_slop() throws Throwable {
+ String text = "line1: This is the 1st line: A\n"
+ + "line2: This is the 2nd line: B\n"
+ + "line3: This is the 3rd line: C\n";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ TextView tv = mActivity.findViewById(R.id.textview);
+
+ // Simulate a drag where the finger moves slightly up and down (above and below the original
+ // line where the drag started). The cursor should just move along the original line without
+ // jumping up or down across lines.
+ MotionEventInfo[] events = new MotionEventInfo[]{
+ // Start dragging along the second line
+ motionEventInfo(text.indexOf("line2"), 1.0f),
+ motionEventInfo(text.indexOf("This is the 2nd"), 1.0f),
+ // Move to the bottom of the first line; cursor should remain on second line
+ motionEventInfo(text.indexOf("he 1st"), 0.0f, text.indexOf("he 2nd")),
+ // Move to the top of the third line; cursor should remain on second line
+ motionEventInfo(text.indexOf("e: C"), 1.0f, text.indexOf("e: B")),
+ motionEventInfo(text.indexOf("B"), 0.0f)
+ };
+ simulateDrag(tv, events, true);
+ }
+
+ @Test
+ public void testCursorDrag_snapToHandle() throws Throwable {
+ String text = "line1: This is the 1st line: A\n"
+ + "line2: This is the 2nd line: B\n"
+ + "line3: This is the 3rd line: C\n";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ TextView tv = mActivity.findViewById(R.id.textview);
+
+ // When the drag motion moves downward, we delay jumping to the lower line to allow the
+ // user's touch to snap to the cursor's handle. Once the finger is over the handle, we
+ // position the cursor above the user's actual touch (offset such that the finger remains
+ // over the handle rather than on top of the cursor vertical bar). This improves the
+ // visibility of the cursor and the text underneath.
+ MotionEventInfo[] events = new MotionEventInfo[]{
+ // Start dragging along the first line
+ motionEventInfo(text.indexOf("line1"), 1.0f),
+ motionEventInfo(text.indexOf("This is the 1st"), 1.0f),
+ // Move to the bottom of the third line; cursor should end up on second line
+ motionEventInfo(text.indexOf("he 3rd"), 0.0f, text.indexOf("he 2nd")),
+ // Move to the middle of the second line; cursor should end up on the first line
+ motionEventInfo(text.indexOf("he 2nd"), 0.5f, text.indexOf("he 1st"))
+ };
+ simulateDrag(tv, events, true);
+
+ // If the drag motion hasn't moved downward (ie, we haven't had a chance to snap to the
+ // handle), we position the cursor directly at the touch position.
+ events = new MotionEventInfo[]{
+ // Start dragging along the third line
+ motionEventInfo(text.indexOf("line3"), 1.0f),
+ motionEventInfo(text.indexOf("This is the 3rd"), 1.0f),
+ // Move to the middle of the second line; cursor should end up on the second line
+ motionEventInfo(text.indexOf("he 2nd"), 0.5f, text.indexOf("he 2nd")),
+ };
+ simulateDrag(tv, events, true);
+ }
+
private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
}
@@ -436,4 +514,89 @@
event.setButtonState(MotionEvent.BUTTON_PRIMARY);
return event;
}
+
+ public static MotionEventInfo motionEventInfo(int index, float ratioToLineTop) {
+ return new MotionEventInfo(index, ratioToLineTop, index);
+ }
+
+ public static MotionEventInfo motionEventInfo(int index, float ratioToLineTop,
+ int expectedCursorIndex) {
+ return new MotionEventInfo(index, ratioToLineTop, expectedCursorIndex);
+ }
+
+ private static class MotionEventInfo {
+ public final int index;
+ public final float ratioToLineTop; // 0.0 = bottom of line, 0.5 = middle of line, etc
+ public final int expectedCursorIndex;
+
+ private MotionEventInfo(int index, float ratioToLineTop, int expectedCursorIndex) {
+ this.index = index;
+ this.ratioToLineTop = ratioToLineTop;
+ this.expectedCursorIndex = expectedCursorIndex;
+ }
+
+ public float[] getCoordinates(TextView textView) {
+ Layout layout = textView.getLayout();
+ int line = layout.getLineForOffset(index);
+ float x = layout.getPrimaryHorizontal(index) + textView.getTotalPaddingLeft();
+ int bottom = layout.getLineBottom(line);
+ int top = layout.getLineTop(line);
+ float y = bottom - ((bottom - top) * ratioToLineTop) + textView.getTotalPaddingTop();
+ return new float[]{x, y};
+ }
+ }
+
+ private void simulateDrag(TextView tv, MotionEventInfo[] events, boolean runAssertions)
+ throws Exception {
+ Editor editor = tv.getEditorForTesting();
+
+ float[] downCoords = events[0].getCoordinates(tv);
+ long downEventTime = sTicker.addAndGet(10_000);
+ MotionEvent downEvent = downEvent(downEventTime, downEventTime,
+ downCoords[0], downCoords[1]);
+ mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(downEvent));
+
+ for (int i = 1; i < events.length; i++) {
+ float[] moveCoords = events[i].getCoordinates(tv);
+ long eventTime = downEventTime + i;
+ MotionEvent event = moveEvent(downEventTime, eventTime, moveCoords[0], moveCoords[1]);
+ mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event));
+ assertCursorPosition(tv, events[i].expectedCursorIndex, runAssertions);
+ }
+
+ MotionEventInfo lastEvent = events[events.length - 1];
+ float[] upCoords = lastEvent.getCoordinates(tv);
+ long upEventTime = downEventTime + events.length;
+ MotionEvent upEvent = upEvent(downEventTime, upEventTime, upCoords[0], upCoords[1]);
+ mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(upEvent));
+ }
+
+ private static void assertCursorPosition(TextView tv, int expectedPosition,
+ boolean runAssertions) {
+ String textAfterExpectedPos = getTextAfterIndex(tv, expectedPosition, 15);
+ String textAfterActualPos = getTextAfterIndex(tv, tv.getSelectionStart(), 15);
+ String msg = "Expected cursor at " + expectedPosition + ", just before \""
+ + textAfterExpectedPos + "\". Cursor is at " + tv.getSelectionStart()
+ + ", just before \"" + textAfterActualPos + "\".";
+ Log.d(LOG_TAG, msg);
+ if (runAssertions) {
+ assertWithMessage(msg).that(tv.getSelectionStart()).isEqualTo(expectedPosition);
+ assertThat(tv.getSelectionEnd()).isEqualTo(expectedPosition);
+ }
+ }
+
+ private static String getTextAfterIndex(TextView tv, int position, int maxLength) {
+ int end = Math.min(position + maxLength, tv.getText().length());
+ try {
+ String afterPosition = tv.getText().subSequence(position, end).toString();
+ if (afterPosition.indexOf('\n') > 0) {
+ afterPosition = afterPosition.substring(0, afterPosition.indexOf('\n'));
+ }
+ return afterPosition;
+ } catch (StringIndexOutOfBoundsException e) {
+ Log.d(LOG_TAG, "Invalid target position: position=" + position + ", length="
+ + tv.getText().length() + ", end=" + end);
+ return "";
+ }
+ }
}
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java
index dfcaf81..b2f9a0f 100644
--- a/location/java/android/location/GnssAntennaInfo.java
+++ b/location/java/android/location/GnssAntennaInfo.java
@@ -16,72 +16,37 @@
package android.location;
-import android.annotation.IntDef;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A class that contains information about a GNSS antenna. GNSS antenna characteristics can change
* with device configuration, such as when a device is folded open or closed. Antenna information is
- * delivered to registered instances of {@link Callback}.
+ * delivered to registered instances of {@link Listener}.
*/
public final class GnssAntennaInfo implements Parcelable {
private final double mCarrierFrequencyMHz;
- private final PhaseCenterOffsetCoordinates mPhaseCenterOffsetCoordinates;
- private final PhaseCenterVariationCorrections mPhaseCenterVariationCorrections;
- private final SignalGainCorrections mSignalGainCorrections;
+ private final PhaseCenterOffset mPhaseCenterOffset;
+ private final SphericalCorrections mPhaseCenterVariationCorrections;
+ private final SphericalCorrections mSignalGainCorrections;
/**
* Used for receiving GNSS antenna info from the GNSS engine. You can implement this interface
- * and call {@link LocationManager#registerAntennaInfoCallback};
+ * and call {@link LocationManager#registerAntennaInfoListener};
*/
- public abstract static class Callback {
+ public interface Listener {
/**
- * The status of GNSS antenna info.
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
- public @interface GnssAntennaInfoStatus {
- }
-
- /**
- * The system does not support GNSS antenna info.
- *
- * This status will not change in the future.
- */
- public static final int STATUS_NOT_SUPPORTED = 0;
-
- /**
- * GNSS antenna info updates are being successfully tracked.
- */
- public static final int STATUS_READY = 1;
-
- /**
- * GNSS provider or Location is disabled, updated will not be received until they are
- * enabled.
- */
- public static final int STATUS_LOCATION_DISABLED = 2;
-
- /**
- * Returns the latest GNSS antenna info. This event is triggered when a callback is
+ * Returns the latest GNSS antenna info. This event is triggered when a listener is
* registered, and whenever the antenna info changes (due to a device configuration change).
*/
- public void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos) {}
-
- /**
- * Returns the latest status of the GNSS antenna info sub-system.
- */
- public void onStatusChanged(@GnssAntennaInfoStatus int status) {}
+ void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos);
}
/**
@@ -90,37 +55,31 @@
* for mobiles - see sensor or form factor documents for details. Uncertainties are reported
* to 1-sigma.
*/
- public static final class PhaseCenterOffsetCoordinates implements Parcelable {
- private final double mPhaseCenterOffsetCoordinateXMillimeters;
- private final double mPhaseCenterOffsetCoordinateXUncertaintyMillimeters;
- private final double mPhaseCenterOffsetCoordinateYMillimeters;
- private final double mPhaseCenterOffsetCoordinateYUncertaintyMillimeters;
- private final double mPhaseCenterOffsetCoordinateZMillimeters;
- private final double mPhaseCenterOffsetCoordinateZUncertaintyMillimeters;
+ public static final class PhaseCenterOffset implements Parcelable {
+ private final double mOffsetXMm;
+ private final double mOffsetXUncertaintyMm;
+ private final double mOffsetYMm;
+ private final double mOffsetYUncertaintyMm;
+ private final double mOffsetZMm;
+ private final double mOffsetZUncertaintyMm;
- @VisibleForTesting
- public PhaseCenterOffsetCoordinates(double phaseCenterOffsetCoordinateXMillimeters,
- double phaseCenterOffsetCoordinateXUncertaintyMillimeters,
- double phaseCenterOffsetCoordinateYMillimeters,
- double phaseCenterOffsetCoordinateYUncertaintyMillimeters,
- double phaseCenterOffsetCoordinateZMillimeters,
- double phaseCenterOffsetCoordinateZUncertaintyMillimeters) {
- mPhaseCenterOffsetCoordinateXMillimeters = phaseCenterOffsetCoordinateXMillimeters;
- mPhaseCenterOffsetCoordinateYMillimeters = phaseCenterOffsetCoordinateYMillimeters;
- mPhaseCenterOffsetCoordinateZMillimeters = phaseCenterOffsetCoordinateZMillimeters;
- mPhaseCenterOffsetCoordinateXUncertaintyMillimeters =
- phaseCenterOffsetCoordinateXUncertaintyMillimeters;
- mPhaseCenterOffsetCoordinateYUncertaintyMillimeters =
- phaseCenterOffsetCoordinateYUncertaintyMillimeters;
- mPhaseCenterOffsetCoordinateZUncertaintyMillimeters =
- phaseCenterOffsetCoordinateZUncertaintyMillimeters;
+ public PhaseCenterOffset(
+ double offsetXMm, double offsetXUncertaintyMm,
+ double offsetYMm, double offsetYUncertaintyMm,
+ double offsetZMm, double offsetZUncertaintyMm) {
+ mOffsetXMm = offsetXMm;
+ mOffsetYMm = offsetYMm;
+ mOffsetZMm = offsetZMm;
+ mOffsetXUncertaintyMm = offsetXUncertaintyMm;
+ mOffsetYUncertaintyMm = offsetYUncertaintyMm;
+ mOffsetZUncertaintyMm = offsetZUncertaintyMm;
}
- public static final @NonNull Creator<PhaseCenterOffsetCoordinates> CREATOR =
- new Creator<PhaseCenterOffsetCoordinates>() {
+ public static final @NonNull Creator<PhaseCenterOffset> CREATOR =
+ new Creator<PhaseCenterOffset>() {
@Override
- public PhaseCenterOffsetCoordinates createFromParcel(Parcel in) {
- return new PhaseCenterOffsetCoordinates(
+ public PhaseCenterOffset createFromParcel(Parcel in) {
+ return new PhaseCenterOffset(
in.readDouble(),
in.readDouble(),
in.readDouble(),
@@ -131,33 +90,39 @@
}
@Override
- public PhaseCenterOffsetCoordinates[] newArray(int size) {
- return new PhaseCenterOffsetCoordinates[size];
+ public PhaseCenterOffset[] newArray(int size) {
+ return new PhaseCenterOffset[size];
}
};
- public double getXCoordMillimeters() {
- return mPhaseCenterOffsetCoordinateXMillimeters;
+ @FloatRange()
+ public double getXOffsetMm() {
+ return mOffsetXMm;
}
- public double getXCoordUncertaintyMillimeters() {
- return mPhaseCenterOffsetCoordinateXUncertaintyMillimeters;
+ @FloatRange()
+ public double getXOffsetUncertaintyMm() {
+ return mOffsetXUncertaintyMm;
}
- public double getYCoordMillimeters() {
- return mPhaseCenterOffsetCoordinateYMillimeters;
+ @FloatRange()
+ public double getYOffsetMm() {
+ return mOffsetYMm;
}
- public double getYCoordUncertaintyMillimeters() {
- return mPhaseCenterOffsetCoordinateYUncertaintyMillimeters;
+ @FloatRange()
+ public double getYOffsetUncertaintyMm() {
+ return mOffsetYUncertaintyMm;
}
- public double getZCoordMillimeters() {
- return mPhaseCenterOffsetCoordinateZMillimeters;
+ @FloatRange()
+ public double getZOffsetMm() {
+ return mOffsetZMm;
}
- public double getZCoordUncertaintyMillimeters() {
- return mPhaseCenterOffsetCoordinateZUncertaintyMillimeters;
+ @FloatRange()
+ public double getZOffsetUncertaintyMm() {
+ return mOffsetZUncertaintyMm;
}
@Override
@@ -167,30 +132,27 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeDouble(mPhaseCenterOffsetCoordinateXMillimeters);
- dest.writeDouble(mPhaseCenterOffsetCoordinateXUncertaintyMillimeters);
- dest.writeDouble(mPhaseCenterOffsetCoordinateYMillimeters);
- dest.writeDouble(mPhaseCenterOffsetCoordinateYUncertaintyMillimeters);
- dest.writeDouble(mPhaseCenterOffsetCoordinateZMillimeters);
- dest.writeDouble(mPhaseCenterOffsetCoordinateZUncertaintyMillimeters);
+ dest.writeDouble(mOffsetXMm);
+ dest.writeDouble(mOffsetXUncertaintyMm);
+ dest.writeDouble(mOffsetYMm);
+ dest.writeDouble(mOffsetYUncertaintyMm);
+ dest.writeDouble(mOffsetZMm);
+ dest.writeDouble(mOffsetZUncertaintyMm);
}
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("PhaseCenteroffset:\n");
- builder.append("X: " + mPhaseCenterOffsetCoordinateXMillimeters + " +/- "
- + mPhaseCenterOffsetCoordinateXUncertaintyMillimeters + "\n");
- builder.append("Y: " + mPhaseCenterOffsetCoordinateYMillimeters + " +/- "
- + mPhaseCenterOffsetCoordinateYUncertaintyMillimeters + "\n");
- builder.append("Z: " + mPhaseCenterOffsetCoordinateZMillimeters + " +/- "
- + mPhaseCenterOffsetCoordinateZUncertaintyMillimeters + "\n");
- return builder.toString();
+ return "PhaseCenterOffset{"
+ + "OffsetXMm=" + mOffsetXMm + " +/-" + mOffsetXUncertaintyMm
+ + ", OffsetYMm=" + mOffsetYMm + " +/-" + mOffsetYUncertaintyMm
+ + ", OffsetZMm=" + mOffsetZMm + " +/-" + mOffsetZUncertaintyMm
+ + '}';
}
}
/**
- * Class containing information about the phase center variation (PCV) corrections. The PCV
- * correction is added to the phase measurement to obtain the corrected value.
+ * Represents corrections on a spherical mapping. Corrections are added to measurements to
+ * obtain the corrected values.
*
* The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays.
*
@@ -203,229 +165,7 @@
* at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
* i.e., deltaPhi = 180 / (number of columns - 1).
*/
- public static final class PhaseCenterVariationCorrections extends SphericalCorrections {
-
- @VisibleForTesting
- public PhaseCenterVariationCorrections(
- @NonNull double[][] phaseCenterVariationCorrectionsMillimeters,
- @NonNull double[][] phaseCenterVariationCorrectionUncertaintiesMillimeters) {
- super(phaseCenterVariationCorrectionsMillimeters,
- phaseCenterVariationCorrectionUncertaintiesMillimeters);
- }
-
- private PhaseCenterVariationCorrections(@NonNull Parcel in) {
- super(in);
- }
-
- /**
- * Get the phase center variation correction in millimeters at the specified row and column
- * in the underlying 2D array.
- * @param row zero-based major index in the array
- * @param column zero-based minor index in the array
- * @return phase center correction in millimeters
- */
- public double getPhaseCenterVariationCorrectionMillimetersAt(int row, int column) {
- return super.getCorrectionAt(row, column);
- }
-
- /**
- * Get the phase center variation correction uncertainty in millimeters at the specified row
- * and column in the underlying 2D array.
- * @param row zero-based major index in the array
- * @param column zero-based minor index in the array
- * @return 1-sigma phase center correction uncertainty in millimeters
- */
- public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(
- int row, int column) {
- return super.getCorrectionUncertaintyAt(row, column);
- }
-
- public @NonNull double[][] getRawCorrectionsArray() {
- return super.getRawCorrectionsArray().clone();
- }
-
- public @NonNull double[][] getRawCorrectionUncertaintiesArray() {
- return super.getRawCorrectionUncertaintiesArray().clone();
- }
-
- public int getNumRows() {
- return super.getNumRows();
- }
-
- public int getNumColumns() {
- return super.getNumColumns();
- }
-
- /**
- * The fixed theta angle separation between successive rows.
- */
- public double getDeltaTheta() {
- return super.getDeltaTheta();
- }
-
- /**
- * The fixed phi angle separation between successive columns.
- */
- public double getDeltaPhi() {
- return super.getDeltaPhi();
- }
-
- public static final @NonNull Creator<PhaseCenterVariationCorrections> CREATOR =
- new Creator<PhaseCenterVariationCorrections>() {
- @Override
- public PhaseCenterVariationCorrections createFromParcel(Parcel in) {
- return new PhaseCenterVariationCorrections(in);
- }
-
- @Override
- public PhaseCenterVariationCorrections[] newArray(int size) {
- return new PhaseCenterVariationCorrections[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("PhaseCenterVariationCorrections:\n");
- builder.append(super.toString());
- return builder.toString();
- }
- }
-
- /**
- * Class containing information about the signal gain (SG) corrections. The SG
- * correction is added to the signal gain to obtain the corrected value.
- *
- * The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays.
- *
- * Each row (major indices) represents a fixed theta. The first row corresponds to a
- * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
- * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta
- * = 360 / (number of rows).
- *
- * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending
- * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
- * i.e., deltaPhi = 180 / (number of columns - 1).
- */
- public static final class SignalGainCorrections extends SphericalCorrections {
-
- @VisibleForTesting
- public SignalGainCorrections(
- @NonNull double[][] signalGainCorrectionsDbi,
- @NonNull double[][] signalGainCorrectionUncertaintiesDbi) {
- super(signalGainCorrectionsDbi,
- signalGainCorrectionUncertaintiesDbi);
- }
-
- private SignalGainCorrections(@NonNull Parcel in) {
- super(in);
- }
-
- /**
- * Get the signal gain correction in dbi at the specified row and column
- * in the underlying 2D array.
- * @param row zero-based major index in the array
- * @param column zero-based minor index in the array
- * @return signal gain correction in dbi
- */
- public double getSignalGainCorrectionDbiAt(int row, int column) {
- return super.getCorrectionAt(row, column);
- }
-
- /**
- * Get the signal gain correction correction uncertainty in dbi at the specified row
- * and column in the underlying 2D array.
- * @param row zero-based major index in the array
- * @param column zero-based minor index in the array
- * @return 1-sigma signal gain correction uncertainty in dbi
- */
- public double getSignalGainCorrectionUncertaintyDbiAt(int row, int column) {
- return super.getCorrectionUncertaintyAt(row, column);
- }
-
- public @NonNull double[][] getRawCorrectionsArray() {
- return super.getRawCorrectionsArray().clone();
- }
-
- public @NonNull double[][] getRawCorrectionUncertaintiesArray() {
- return super.getRawCorrectionUncertaintiesArray().clone();
- }
-
- public int getNumRows() {
- return super.getNumRows();
- }
-
- public int getNumColumns() {
- return super.getNumColumns();
- }
-
- /**
- * The fixed theta angle separation between successive rows.
- */
- public double getDeltaTheta() {
- return super.getDeltaTheta();
- }
-
- /**
- * The fixed phi angle separation between successive columns.
- */
- public double getDeltaPhi() {
- return super.getDeltaPhi();
- }
-
- public static final @NonNull Creator<SignalGainCorrections> CREATOR =
- new Creator<SignalGainCorrections>() {
- @Override
- public SignalGainCorrections createFromParcel(Parcel in) {
- return new SignalGainCorrections(in);
- }
-
- @Override
- public SignalGainCorrections[] newArray(int size) {
- return new SignalGainCorrections[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("SignalGainCorrections:\n");
- builder.append(super.toString());
- return builder.toString();
- }
- }
-
- /**
- * Represents corrections on a spherical mapping.
- *
- * Each row (major indices) represents a fixed theta. The first row corresponds to a
- * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
- * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta
- * = 360 / (number of rows).
- *
- * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending
- * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
- * i.e., deltaPhi = 180 / (number of columns - 1).
- */
- private abstract static class SphericalCorrections implements Parcelable {
+ public static final class SphericalCorrections implements Parcelable{
private final double[][] mCorrections;
private final double[][] mCorrectionUncertainties;
private final double mDeltaTheta;
@@ -433,7 +173,7 @@
private final int mNumRows;
private final int mNumColumns;
- SphericalCorrections(@NonNull double[][] corrections,
+ public SphericalCorrections(@NonNull double[][] corrections,
@NonNull double[][] correctionUncertainties) {
if (corrections.length != correctionUncertainties.length
|| corrections[0].length != correctionUncertainties[0].length) {
@@ -474,54 +214,84 @@
in.readDoubleArray(correctionUncertainties[row]);
}
- mNumRows = corrections.length;
- mNumColumns = corrections[0].length;
+ mNumRows = numRows;
+ mNumColumns = numColumns;
mCorrections = corrections;
mCorrectionUncertainties = correctionUncertainties;
mDeltaTheta = 360.0d / mNumRows;
mDeltaPhi = 180.0d / (mNumColumns - 1);
}
- private double getCorrectionAt(int row, int column) {
- return mCorrections[row][column];
- }
-
- private double getCorrectionUncertaintyAt(int row, int column) {
- return mCorrectionUncertainties[row][column];
- }
-
+ /**
+ * Array representing corrections on a spherical mapping. Corrections are added to
+ * measurements to obtain the corrected values.
+ *
+ * Each row (major indices) represents a fixed theta. The first row corresponds to a
+ * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
+ * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e.,
+ * deltaTheta = 360 / (number of rows).
+ *
+ * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and
+ * ending at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith
+ * angles, i.e., deltaPhi = 180 / (number of columns - 1).
+ */
@NonNull
- private double[][] getRawCorrectionsArray() {
+ public double[][] getCorrectionsArray() {
return mCorrections;
}
+ /**
+ * Array representing uncertainty on corrections on a spherical mapping.
+ *
+ * Each row (major indices) represents a fixed theta. The first row corresponds to a
+ * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
+ * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e.,
+ * deltaTheta = 360 / (number of rows).
+ *
+ * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and
+ * ending at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith
+ * angles, i.e., deltaPhi = 180 / (number of columns - 1).
+ */
@NonNull
- private double[][] getRawCorrectionUncertaintiesArray() {
+ public double[][] getCorrectionUncertaintiesArray() {
return mCorrectionUncertainties;
}
- private int getNumRows() {
- return mNumRows;
- }
-
- private int getNumColumns() {
- return mNumColumns;
- }
-
/**
* The fixed theta angle separation between successive rows.
*/
- private double getDeltaTheta() {
+ @FloatRange(from = 0.0f, to = 360.0f)
+ public double getDeltaTheta() {
return mDeltaTheta;
}
/**
* The fixed phi angle separation between successive columns.
*/
- private double getDeltaPhi() {
+ @FloatRange(from = 0.0f, to = 180.0f)
+ public double getDeltaPhi() {
return mDeltaPhi;
}
+
+ public static final @NonNull Creator<SphericalCorrections> CREATOR =
+ new Creator<SphericalCorrections>() {
+ @Override
+ public SphericalCorrections createFromParcel(Parcel in) {
+ return new SphericalCorrections(in);
+ }
+
+ @Override
+ public SphericalCorrections[] newArray(int size) {
+ return new SphericalCorrections[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mNumRows);
@@ -534,62 +304,114 @@
}
}
- private String arrayToString(double[][] array) {
- StringBuilder builder = new StringBuilder();
- for (int row = 0; row < mNumRows; row++) {
- builder.append("[ ");
- for (int column = 0; column < mNumColumns - 1; column++) {
- builder.append(array[row][column] + ", ");
- }
- builder.append(array[row][mNumColumns - 1] + " ]\n");
- }
- return builder.toString();
- }
-
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("DeltaTheta: " + mDeltaTheta + "\n");
- builder.append("DeltaPhi: " + mDeltaPhi + "\n");
- builder.append("CorrectionsArray:\n");
- builder.append(arrayToString(mCorrections));
- builder.append("CorrectionUncertaintiesArray:\n");
- builder.append(arrayToString(mCorrectionUncertainties));
- return builder.toString();
+ return "SphericalCorrections{"
+ + "Corrections=" + Arrays.toString(mCorrections)
+ + ", CorrectionUncertainties=" + Arrays.toString(mCorrectionUncertainties)
+ + ", DeltaTheta=" + mDeltaTheta
+ + ", DeltaPhi=" + mDeltaPhi
+ + '}';
}
}
- @VisibleForTesting
- public GnssAntennaInfo(
+ private GnssAntennaInfo(
double carrierFrequencyMHz,
- @NonNull PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates,
- @Nullable PhaseCenterVariationCorrections phaseCenterVariationCorrections,
- @Nullable SignalGainCorrections signalGainCorrectionDbi) {
- if (phaseCenterOffsetCoordinates == null) {
+ @NonNull PhaseCenterOffset phaseCenterOffset,
+ @Nullable SphericalCorrections phaseCenterVariationCorrections,
+ @Nullable SphericalCorrections signalGainCorrectionDbi) {
+ if (phaseCenterOffset == null) {
throw new IllegalArgumentException("Phase Center Offset Coordinates cannot be null.");
}
mCarrierFrequencyMHz = carrierFrequencyMHz;
- mPhaseCenterOffsetCoordinates = phaseCenterOffsetCoordinates;
+ mPhaseCenterOffset = phaseCenterOffset;
mPhaseCenterVariationCorrections = phaseCenterVariationCorrections;
mSignalGainCorrections = signalGainCorrectionDbi;
}
+ /**
+ * Builder class for GnssAntennaInfo.
+ */
+ public static class Builder {
+ private double mCarrierFrequencyMHz;
+ private PhaseCenterOffset mPhaseCenterOffset;
+ private SphericalCorrections mPhaseCenterVariationCorrections;
+ private SphericalCorrections mSignalGainCorrections;
+
+ /**
+ * Set antenna carrier frequency (MHz).
+ * @param carrierFrequencyMHz antenna carrier frequency (MHz)
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setCarrierFrequencyMHz(@FloatRange(from = 0.0f) double carrierFrequencyMHz) {
+ mCarrierFrequencyMHz = carrierFrequencyMHz;
+ return this;
+ }
+
+ /**
+ * Set antenna phase center offset.
+ * @param phaseCenterOffset phase center offset object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setPhaseCenterOffset(@NonNull PhaseCenterOffset phaseCenterOffset) {
+ mPhaseCenterOffset = Objects.requireNonNull(phaseCenterOffset);
+ return this;
+ }
+
+ /**
+ * Set phase center variation corrections.
+ * @param phaseCenterVariationCorrections phase center variation corrections object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setPhaseCenterVariationCorrections(
+ @Nullable SphericalCorrections phaseCenterVariationCorrections) {
+ mPhaseCenterVariationCorrections = phaseCenterVariationCorrections;
+ return this;
+ }
+
+ /**
+ * Set signal gain corrections.
+ * @param signalGainCorrections signal gain corrections object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setSignalGainCorrections(
+ @Nullable SphericalCorrections signalGainCorrections) {
+ mSignalGainCorrections = signalGainCorrections;
+ return this;
+ }
+
+ /**
+ * Build GnssAntennaInfo object.
+ * @return instance of GnssAntennaInfo
+ */
+ @NonNull
+ public GnssAntennaInfo build() {
+ return new GnssAntennaInfo(mCarrierFrequencyMHz, mPhaseCenterOffset,
+ mPhaseCenterVariationCorrections, mSignalGainCorrections);
+ }
+ }
+
+ @FloatRange(from = 0.0f)
public double getCarrierFrequencyMHz() {
return mCarrierFrequencyMHz;
}
@NonNull
- public PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates() {
- return mPhaseCenterOffsetCoordinates;
+ public PhaseCenterOffset getPhaseCenterOffset() {
+ return mPhaseCenterOffset;
}
@Nullable
- public PhaseCenterVariationCorrections getPhaseCenterVariationCorrections() {
+ public SphericalCorrections getPhaseCenterVariationCorrections() {
return mPhaseCenterVariationCorrections;
}
@Nullable
- public SignalGainCorrections getSignalGainCorrections() {
+ public SphericalCorrections getSignalGainCorrections() {
return mSignalGainCorrections;
}
@@ -600,16 +422,18 @@
double carrierFrequencyMHz = in.readDouble();
ClassLoader classLoader = getClass().getClassLoader();
- PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates =
+ PhaseCenterOffset phaseCenterOffset =
in.readParcelable(classLoader);
- PhaseCenterVariationCorrections phaseCenterVariationCorrections =
+ SphericalCorrections phaseCenterVariationCorrections =
in.readParcelable(classLoader);
- SignalGainCorrections signalGainCorrections =
+ SphericalCorrections signalGainCorrections =
in.readParcelable(classLoader);
- return new GnssAntennaInfo(carrierFrequencyMHz,
- phaseCenterOffsetCoordinates,
- phaseCenterVariationCorrections, signalGainCorrections);
+ return new GnssAntennaInfo(
+ carrierFrequencyMHz,
+ phaseCenterOffset,
+ phaseCenterVariationCorrections,
+ signalGainCorrections);
}
@Override
@@ -626,29 +450,18 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeDouble(mCarrierFrequencyMHz);
-
- // Write Phase Center Offset
- parcel.writeParcelable(mPhaseCenterOffsetCoordinates, flags);
-
- // Write Phase Center Variation Corrections
+ parcel.writeParcelable(mPhaseCenterOffset, flags);
parcel.writeParcelable(mPhaseCenterVariationCorrections, flags);
-
- // Write Signal Gain Corrections
parcel.writeParcelable(mSignalGainCorrections, flags);
}
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("[ GnssAntennaInfo:\n");
- builder.append("CarrierFrequencyMHz: " + mCarrierFrequencyMHz + "\n");
- builder.append(mPhaseCenterOffsetCoordinates.toString());
- builder.append(mPhaseCenterVariationCorrections == null
- ? "PhaseCenterVariationCorrections: null\n"
- : mPhaseCenterVariationCorrections.toString());
- builder.append(mSignalGainCorrections == null
- ? "SignalGainCorrections: null\n"
- : mSignalGainCorrections.toString());
- builder.append("]");
- return builder.toString();
+ return "GnssAntennaInfo{"
+ + "CarrierFrequencyMHz=" + mCarrierFrequencyMHz
+ + ", PhaseCenterOffset=" + mPhaseCenterOffset
+ + ", PhaseCenterVariationCorrections=" + mPhaseCenterVariationCorrections
+ + ", SignalGainCorrections=" + mSignalGainCorrections
+ + '}';
}
}
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index 930180c..5734bf2 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -16,15 +16,11 @@
package android.location;
-import android.annotation.NonNull;
import android.annotation.SystemApi;
/**
* A container of supported GNSS chipset capabilities.
- *
- * @hide
*/
-@SystemApi
public final class GnssCapabilities {
/**
* Bit mask indicating GNSS chipset supports low power mode.
@@ -105,7 +101,10 @@
/**
* Returns {@code true} if GNSS chipset supports low power mode, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasLowPowerMode() {
return hasCapability(LOW_POWER_MODE);
}
@@ -113,28 +112,40 @@
/**
* Returns {@code true} if GNSS chipset supports blacklisting satellites, {@code false}
* otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasSatelliteBlacklist() {
return hasCapability(SATELLITE_BLACKLIST);
}
/**
* Returns {@code true} if GNSS chipset supports geofencing, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasGeofencing() {
return hasCapability(GEOFENCING);
}
/**
* Returns {@code true} if GNSS chipset supports measurements, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasMeasurements() {
return hasCapability(MEASUREMENTS);
}
/**
* Returns {@code true} if GNSS chipset supports navigation messages, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasNavMessages() {
return hasCapability(NAV_MESSAGES);
}
@@ -142,7 +153,10 @@
/**
* Returns {@code true} if GNSS chipset supports measurement corrections, {@code false}
* otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasMeasurementCorrections() {
return hasCapability(MEASUREMENT_CORRECTIONS);
}
@@ -150,7 +164,10 @@
/**
* Returns {@code true} if GNSS chipset supports line-of-sight satellite identification
* measurement corrections, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasMeasurementCorrectionsLosSats() {
return hasCapability(MEASUREMENT_CORRECTIONS_LOS_SATS);
}
@@ -158,7 +175,10 @@
/**
* Returns {@code true} if GNSS chipset supports per satellite excess-path-length measurement
* corrections, {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasMeasurementCorrectionsExcessPathLength() {
return hasCapability(MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH);
}
@@ -166,7 +186,10 @@
/**
* Returns {@code true} if GNSS chipset supports reflecting planes measurement corrections,
* {@code false} otherwise.
+ *
+ * @hide
*/
+ @SystemApi
public boolean hasMeasurementCorrectionsReflectingPane() {
return hasCapability(MEASUREMENT_CORRECTIONS_REFLECTING_PLANE);
}
@@ -178,28 +201,6 @@
return hasCapability(ANTENNA_INFO);
}
- @NonNull
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("GnssCapabilities: ( ");
- if (hasLowPowerMode()) sb.append("LOW_POWER_MODE ");
- if (hasSatelliteBlacklist()) sb.append("SATELLITE_BLACKLIST ");
- if (hasGeofencing()) sb.append("GEOFENCING ");
- if (hasGnssAntennaInfo()) sb.append("ANTENNA_INFO ");
- if (hasMeasurements()) sb.append("MEASUREMENTS ");
- if (hasNavMessages()) sb.append("NAV_MESSAGES ");
- if (hasMeasurementCorrections()) sb.append("MEASUREMENT_CORRECTIONS ");
- if (hasMeasurementCorrectionsLosSats()) sb.append("MEASUREMENT_CORRECTIONS_LOS_SATS ");
- if (hasMeasurementCorrectionsExcessPathLength()) {
- sb.append("MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH ");
- }
- if (hasMeasurementCorrectionsReflectingPane()) {
- sb.append("MEASUREMENT_CORRECTIONS_REFLECTING_PLANE ");
- }
- sb.append(")");
- return sb.toString();
- }
-
private boolean hasCapability(long capability) {
return (mGnssCapabilities & capability) == capability;
}
diff --git a/location/java/android/location/IGnssAntennaInfoListener.aidl b/location/java/android/location/IGnssAntennaInfoListener.aidl
index 30bf5467..603ed6a 100644
--- a/location/java/android/location/IGnssAntennaInfoListener.aidl
+++ b/location/java/android/location/IGnssAntennaInfoListener.aidl
@@ -23,5 +23,4 @@
*/
oneway interface IGnssAntennaInfoListener {
void onGnssAntennaInfoReceived(in List<GnssAntennaInfo> gnssAntennaInfo);
- void onStatusChanged(in int status);
}
\ No newline at end of file
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 03e1c75..19085bf 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1813,13 +1813,7 @@
/**
* Returns the supported capabilities of the GNSS chipset.
- *
- * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present.
- *
- * @hide
*/
- @SystemApi
- @RequiresPermission(ACCESS_FINE_LOCATION)
public @NonNull GnssCapabilities getGnssCapabilities() {
try {
long gnssCapabilities = mService.getGnssCapabilities(mContext.getPackageName());
@@ -2264,35 +2258,36 @@
}
/**
- * Registers a Gnss Antenna Info callback.
+ * Registers a Gnss Antenna Info listener. Only expect results if
+ * {@link GnssCapabilities#hasGnssAntennaInfo()} shows that antenna info is supported.
*
- * @param executor the executor that the callback runs on.
- * @param callback a {@link GnssAntennaInfo.Callback} object to register.
- * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+ * @param executor the executor that the listener runs on.
+ * @param listener a {@link GnssAntennaInfo.Listener} object to register.
+ * @return {@code true} if the listener was added successfully, {@code false} otherwise.
*
* @throws IllegalArgumentException if executor is null
- * @throws IllegalArgumentException if callback is null
+ * @throws IllegalArgumentException if listener is null
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerAntennaInfoCallback(
+ public boolean registerAntennaInfoListener(
@NonNull @CallbackExecutor Executor executor,
- @NonNull GnssAntennaInfo.Callback callback) {
+ @NonNull GnssAntennaInfo.Listener listener) {
try {
- return mGnssAntennaInfoListenerManager.addListener(callback, executor);
+ return mGnssAntennaInfoListenerManager.addListener(listener, executor);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Unregisters a GNSS Antenna Info callback.
+ * Unregisters a GNSS Antenna Info listener.
*
- * @param callback a {@link GnssAntennaInfo.Callback} object to remove.
+ * @param listener a {@link GnssAntennaInfo.Listener} object to remove.
*/
- public void unregisterAntennaInfoCallback(@NonNull GnssAntennaInfo.Callback callback) {
+ public void unregisterAntennaInfoListener(@NonNull GnssAntennaInfo.Listener listener) {
try {
- mGnssAntennaInfoListenerManager.removeListener(callback);
+ mGnssAntennaInfoListenerManager.removeListener(listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3043,7 +3038,7 @@
}
private class GnssAntennaInfoListenerManager extends
- AbstractListenerManager<Void, GnssAntennaInfo.Callback> {
+ AbstractListenerManager<Void, GnssAntennaInfo.Listener> {
@Nullable
private IGnssAntennaInfoListener mListenerTransport;
@@ -3075,11 +3070,6 @@
public void onGnssAntennaInfoReceived(final List<GnssAntennaInfo> gnssAntennaInfos) {
execute((callback) -> callback.onGnssAntennaInfoReceived(gnssAntennaInfos));
}
-
- @Override
- public void onStatusChanged(int status) {
- execute((listener) -> listener.onStatusChanged(status));
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 8a5aad8..cf5a4d3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -443,20 +443,7 @@
mStateChange.orderChanged |= repackAll();
}
- if (reason == BubbleController.DISMISS_AGED) {
- if (DEBUG_BUBBLE_DATA) {
- Log.d(TAG, "overflowing bubble: " + bubbleToRemove);
- }
- mOverflowBubbles.add(0, bubbleToRemove);
- if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
- // Remove oldest bubble.
- if (DEBUG_BUBBLE_DATA) {
- Log.d(TAG, "Overflow full. Remove bubble: " + mOverflowBubbles.get(
- mOverflowBubbles.size() - 1));
- }
- mOverflowBubbles.remove(mOverflowBubbles.size() - 1);
- }
- }
+ overflowBubble(reason, bubbleToRemove);
// Note: If mBubbles.isEmpty(), then mSelectedBubble is now null.
if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
@@ -468,6 +455,25 @@
maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
}
+ void overflowBubble(@DismissReason int reason, Bubble bubble) {
+ if (reason == BubbleController.DISMISS_AGED
+ || reason == BubbleController.DISMISS_USER_GESTURE) {
+ if (DEBUG_BUBBLE_DATA) {
+ Log.d(TAG, "overflowing bubble: " + bubble);
+ }
+ mOverflowBubbles.add(0, bubble);
+
+ if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
+ // Remove oldest bubble.
+ if (DEBUG_BUBBLE_DATA) {
+ Log.d(TAG, "Overflow full. Remove bubble: " + mOverflowBubbles.get(
+ mOverflowBubbles.size() - 1));
+ }
+ mOverflowBubbles.remove(mOverflowBubbles.size() - 1);
+ }
+ }
+ }
+
public void dismissAll(@DismissReason int reason) {
if (DEBUG_BUBBLE_DATA) {
Log.d(TAG, "dismissAll: reason=" + reason);
@@ -478,9 +484,7 @@
setExpandedInternal(false);
setSelectedBubbleInternal(null);
while (!mBubbles.isEmpty()) {
- Bubble bubble = mBubbles.remove(0);
- maybeSendDeleteIntent(reason, bubble.getEntry());
- mStateChange.bubbleRemoved(bubble, reason);
+ doRemove(mBubbles.get(0).getKey(), reason);
}
dispatchPendingChanges();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 756c598..eb836b1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -55,7 +55,6 @@
private BubbleOverflowAdapter mAdapter;
private RecyclerView mRecyclerView;
private List<Bubble> mOverflowBubbles = new ArrayList<>();
- private int mMaxBubbles;
@Inject
public BubbleOverflowActivity(BubbleController controller) {
@@ -68,7 +67,6 @@
setContentView(R.layout.bubble_overflow_activity);
setBackgroundColor();
- mMaxBubbles = getResources().getInteger(R.integer.bubbles_max_rendered);
mEmptyState = findViewById(R.id.bubble_overflow_empty_state);
mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
mRecyclerView.setLayoutManager(
@@ -95,11 +93,7 @@
void onDataChanged(List<Bubble> bubbles) {
mOverflowBubbles.clear();
- if (bubbles.size() > mMaxBubbles) {
- mOverflowBubbles.addAll(bubbles.subList(mMaxBubbles, bubbles.size()));
- } else {
- mOverflowBubbles.addAll(bubbles);
- }
+ mOverflowBubbles.addAll(bubbles);
mAdapter.notifyDataSetChanged();
if (mOverflowBubbles.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
index 7f45cc8..0329183 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
@@ -38,10 +38,10 @@
class DistanceClassifier extends FalsingClassifier {
private static final float HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN = 1;
- private static final float VERTICAL_FLING_THRESHOLD_DISTANCE_IN = 1;
+ private static final float VERTICAL_FLING_THRESHOLD_DISTANCE_IN = 1.5f;
private static final float HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
private static final float VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
- private static final float VELOCITY_TO_DISTANCE = 80f;
+ private static final float VELOCITY_TO_DISTANCE = 30f;
private static final float SCREEN_FRACTION_MAX_DISTANCE = 0.8f;
private final float mVerticalFlingThresholdPx;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
index 957ea8d..a796f3c 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
@@ -42,8 +42,8 @@
// most swipes will follow somewhat of a 'C' or 'S' shape, we allow more deviance along the
// `SECONDARY` axis.
private static final float MAX_X_PRIMARY_DEVIANCE = .05f;
- private static final float MAX_Y_PRIMARY_DEVIANCE = .1f;
- private static final float MAX_X_SECONDARY_DEVIANCE = .6f;
+ private static final float MAX_Y_PRIMARY_DEVIANCE = .15f;
+ private static final float MAX_X_SECONDARY_DEVIANCE = .4f;
private static final float MAX_Y_SECONDARY_DEVIANCE = .3f;
private final float mMaxXPrimaryDeviance;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 87bdfa8..6ff1bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -22,7 +22,6 @@
import android.os.UserHandle
import android.service.controls.Control
import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
import android.service.controls.actions.ControlAction
@@ -63,12 +62,6 @@
private val componentMap: MutableMap<Key, ControlsProviderLifecycleManager> =
ArrayMap<Key, ControlsProviderLifecycleManager>()
- private val loadCallbackService = object : IControlsLoadCallback.Stub() {
- override fun accept(token: IBinder, controls: MutableList<Control>) {
- backgroundExecutor.execute(OnLoadRunnable(token, controls))
- }
- }
-
private val actionCallbackService = object : IControlsActionCallback.Stub() {
override fun accept(
token: IBinder,
@@ -106,7 +99,6 @@
return ControlsProviderLifecycleManager(
context,
backgroundExecutor,
- loadCallbackService,
actionCallbackService,
subscriberService,
currentUser,
@@ -130,7 +122,7 @@
callback: ControlsBindingController.LoadCallback
) {
val provider = retrieveLifecycleManager(component)
- provider.maybeBindAndLoad(callback)
+ provider.maybeBindAndLoad(LoadSubscriber(callback))
}
override fun subscribe(controls: List<ControlInfo>) {
@@ -216,7 +208,8 @@
private inner class OnLoadRunnable(
token: IBinder,
- val list: List<Control>
+ val list: List<Control>,
+ val callback: ControlsBindingController.LoadCallback
) : CallbackRunnable(token) {
override fun run() {
if (provider == null) {
@@ -233,9 +226,7 @@
return
}
}
- provider.lastLoadCallback?.accept(list) ?: run {
- Log.w(TAG, "Null callback")
- }
+ callback.accept(list)
provider.unbindService()
}
}
@@ -277,7 +268,7 @@
) : CallbackRunnable(token) {
override fun run() {
provider?.let {
- Log.i(TAG, "onComplete receive from '${provider.componentName}'")
+ Log.i(TAG, "onComplete receive from '${it.componentName}'")
}
}
}
@@ -288,7 +279,7 @@
) : CallbackRunnable(token) {
override fun run() {
provider?.let {
- Log.e(TAG, "onError receive from '${provider.componentName}': $error")
+ Log.e(TAG, "onError receive from '${it.componentName}': $error")
}
}
}
@@ -308,6 +299,44 @@
}
}
}
+
+ private inner class OnLoadErrorRunnable(
+ token: IBinder,
+ val error: String,
+ val callback: ControlsBindingController.LoadCallback
+ ) : CallbackRunnable(token) {
+ override fun run() {
+ callback.error(error)
+ provider?.let {
+ Log.e(TAG, "onError receive from '${it.componentName}': $error")
+ }
+ }
+ }
+
+ private inner class LoadSubscriber(
+ val callback: ControlsBindingController.LoadCallback
+ ) : IControlsSubscriber.Stub() {
+ val loadedControls = ArrayList<Control>()
+ var hasError = false
+
+ override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
+ backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
+ }
+
+ override fun onNext(token: IBinder, c: Control) {
+ backgroundExecutor.execute { loadedControls.add(c) }
+ }
+ override fun onError(token: IBinder, s: String) {
+ hasError = true
+ backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback))
+ }
+
+ override fun onComplete(token: IBinder) {
+ if (!hasError) {
+ backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback))
+ }
+ }
+ }
}
-private data class Key(val component: ComponentName, val user: UserHandle)
\ No newline at end of file
+private data class Key(val component: ComponentName, val user: UserHandle)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
index d7f3c73..883f8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
@@ -135,7 +135,7 @@
}
private fun parseXml(parser: XmlPullParser): List<ControlInfo> {
- var type = 0
+ var type: Int
val infos = mutableListOf<ControlInfo>()
while (parser.next().also { type = it } != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 9ec71c7..a53fcd4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -29,7 +29,6 @@
import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE
import android.service.controls.ControlsProviderService.CALLBACK_TOKEN
import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
@@ -48,8 +47,6 @@
*
* @property context A SystemUI context for binding to the services
* @property executor A delayable executor for posting timeouts
- * @property loadCallbackService a callback interface to hand the remote service for loading
- * controls
* @property actionCallbackService a callback interface to hand the remote service for sending
* action responses
* @property subscriberService an "subscriber" interface for requesting and accepting updates for
@@ -60,15 +57,12 @@
class ControlsProviderLifecycleManager(
private val context: Context,
private val executor: DelayableExecutor,
- private val loadCallbackService: IControlsLoadCallback.Stub,
private val actionCallbackService: IControlsActionCallback.Stub,
private val subscriberService: IControlsSubscriber.Stub,
val user: UserHandle,
val componentName: ComponentName
) : IBinder.DeathRecipient {
- var lastLoadCallback: ControlsBindingController.LoadCallback? = null
- private set
val token: IBinder = Binder()
@GuardedBy("subscriptions")
private val subscriptions = mutableListOf<IControlsSubscription>()
@@ -156,9 +150,12 @@
bindService(false)
return
}
- if (Message.Load in queue) {
- load()
+
+ queue.filter { it is Message.Load }.forEach {
+ val msg = it as Message.Load
+ load(msg.subscriber)
}
+
queue.filter { it is Message.Subscribe }.flatMap { (it as Message.Subscribe).list }.run {
if (this.isNotEmpty()) {
subscribe(this)
@@ -193,12 +190,12 @@
}
}
- private fun load() {
+ private fun load(subscriber: IControlsSubscriber.Stub) {
if (DEBUG) {
Log.d(TAG, "load $componentName")
}
- if (!(wrapper?.load(loadCallbackService) ?: false)) {
- queueMessage(Message.Load)
+ if (!(wrapper?.load(subscriber) ?: false)) {
+ queueMessage(Message.Load(subscriber))
binderDied()
}
}
@@ -213,27 +210,23 @@
}
/**
- * Request a call to [ControlsProviderService.loadAvailableControls].
+ * Request a call to [IControlsProvider.load].
*
* If the service is not bound, the call will be queued and the service will be bound first.
- * The service will be bound after the controls are returned or the call times out.
+ * The service will be unbound after the controls are returned or the call times out.
*
- * @param callback a callback in which to return the result back. If the call times out
- * [ControlsBindingController.LoadCallback.error] will be called instead.
+ * @param subscriber the subscriber that manages coordination for loading controls
*/
- fun maybeBindAndLoad(callback: ControlsBindingController.LoadCallback) {
+ fun maybeBindAndLoad(subscriber: IControlsSubscriber.Stub) {
unqueueMessage(Message.Unbind)
- lastLoadCallback = callback
onLoadCanceller = executor.executeDelayed({
// Didn't receive a response in time, log and send back error
Log.d(TAG, "Timeout waiting onLoad for $componentName")
- callback.error("Timeout waiting onLoad")
- // Don't accept load callbacks after this
- lastLoadCallback = null
+ subscriber.onError(token, "Timeout waiting onLoad")
unbindService()
}, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS)
- invokeOrQueue(::load, Message.Load)
+ invokeOrQueue({ load(subscriber) }, Message.Load(subscriber))
}
/**
@@ -324,7 +317,6 @@
* Request unbind from the service.
*/
fun unbindService() {
- lastLoadCallback = null
onLoadCanceller?.run()
onLoadCanceller = null
@@ -344,7 +336,7 @@
*/
sealed class Message {
abstract val type: Int
- object Load : Message() {
+ class Load(val subscriber: IControlsSubscriber.Stub) : Message() {
override val type = MSG_LOAD
}
object Unbind : Message() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
index b90f892..b2afd3c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -18,7 +18,6 @@
import android.service.controls.actions.ControlAction
import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
@@ -45,9 +44,9 @@
}
}
- fun load(cb: IControlsLoadCallback): Boolean {
+ fun load(subscriber: IControlsSubscriber): Boolean {
return callThroughService {
- service.load(cb)
+ service.load(subscriber)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
index 89caace..ac5e089 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
@@ -58,13 +58,13 @@
private var listOfServices = emptyList<CandidateInfo>()
private val callback = object : ControlsListingController.ControlsListingCallback {
- override fun onServicesUpdated(list: List<CandidateInfo>) {
+ override fun onServicesUpdated(candidates: List<CandidateInfo>) {
backgroundExecutor.execute {
- val collator = Collator.getInstance(resources.getConfiguration().locale)
+ val collator = Collator.getInstance(resources.configuration.locales[0])
val localeComparator = compareBy<CandidateInfo, CharSequence>(collator) {
it.loadLabel()
}
- listOfServices = list.sortedWith(localeComparator)
+ listOfServices = candidates.sortedWith(localeComparator)
uiExecutor.execute(::notifyDataSetChanged)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 9952b97..af4a977 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -70,7 +70,7 @@
target: RecyclerView.ViewHolder
): Boolean {
return currentModel?.onMoveItem(
- viewHolder.adapterPosition, target.adapterPosition) != null
+ viewHolder.layoutPosition, target.layoutPosition) != null
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
index d893caa..8e47f64 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
@@ -45,6 +45,6 @@
@FunctionalInterface
interface ControlsListingCallback {
- fun onServicesUpdated(list: List<CandidateInfo>)
+ fun onServicesUpdated(candidates: List<CandidateInfo>)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 98cdf28..f4fd375 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -130,8 +130,7 @@
private val listingCallback = object : ControlsListingController.ControlsListingCallback {
override fun onServicesUpdated(candidates: List<CandidateInfo>) {
bgExecutor.execute {
- val collator = Collator.getInstance(context.getResources()
- .getConfiguration().locale)
+ val collator = Collator.getInstance(context.resources.configuration.locales[0])
val localeComparator = compareBy<CandidateInfo, CharSequence>(collator) {
it.loadLabel()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 071198b..d3d4287 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -42,7 +42,7 @@
val intent: PendingIntent
) : Dialog(parentContext) {
- lateinit var activityView: ActivityView
+ var activityView: ActivityView
val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() {
override fun onActivityViewReady(view: ActivityView) {
@@ -61,24 +61,28 @@
override fun onTaskRemovalStarted(taskId: Int) {}
}
- init {
- val window = getWindow()
- window.requestFeature(Window.FEATURE_NO_TITLE)
+ @Suppress("DEPRECATION")
+ private fun Window.setWindowParams() {
+ requestFeature(Window.FEATURE_NO_TITLE)
// Inflate the decor view, so the attributes below are not overwritten by the theme.
- window.getDecorView()
- window.getAttributes().systemUiVisibility =
- (window.getAttributes().systemUiVisibility
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
+ decorView
+ attributes.systemUiVisibility =
+ (attributes.systemUiVisibility
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
- window.setLayout(MATCH_PARENT, MATCH_PARENT)
- window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
- window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
- window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
- window.getAttributes().setFitInsetsTypes(0 /* types */)
+ setLayout(MATCH_PARENT, MATCH_PARENT)
+ clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+ addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+ or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
+ setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
+ getAttributes().setFitInsetsTypes(0 /* types */)
+ }
+
+ init {
+ getWindow()?.setWindowParams()
setContentView(R.layout.controls_detail_dialog)
@@ -89,9 +93,9 @@
}
override fun show() {
- val attrs = getWindow().getAttributes()
- attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- getWindow().setAttributes(attrs)
+ val attrs = getWindow()?.attributes
+ attrs?.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ getWindow()?.attributes = attrs
activityView.setCallback(stateCallback)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 45d7397..cca56c2 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -60,7 +60,7 @@
val gestureListener = ToggleRangeGestureListener(cvh.layout)
val gestureDetector = GestureDetector(context, gestureListener)
- cvh.layout.setOnTouchListener({ v: View, e: MotionEvent ->
+ cvh.layout.setOnTouchListener { _: View, e: MotionEvent ->
if (gestureDetector.onTouchEvent(e)) {
return@setOnTouchListener true
}
@@ -72,7 +72,7 @@
}
return@setOnTouchListener false
- })
+ }
}
override fun bind(cws: ControlWithState) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b1db7df..374153c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -80,7 +80,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.Dependency;
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
@@ -144,7 +145,7 @@
* directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
* thread of the keyguard.
*/
-public class KeyguardViewMediator extends SystemUI {
+public class KeyguardViewMediator extends SystemUI implements Dumpable {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
@@ -222,10 +223,10 @@
private final FalsingManager mFalsingManager;
/** High level access to the power manager for WakeLocks */
- private PowerManager mPM;
+ private final PowerManager mPM;
/** TrustManager for letting it know when we change visibility */
- private TrustManager mTrustManager;
+ private final TrustManager mTrustManager;
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -283,7 +284,7 @@
// the properties of the keyguard
- private KeyguardUpdateMonitor mUpdateMonitor;
+ private final KeyguardUpdateMonitor mUpdateMonitor;
/**
* Last SIM state reported by the telephony system.
@@ -610,6 +611,7 @@
@Override
public void keyguardGone() {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardGone");
+ mNotificationShadeWindowController.setKeyguardGoingAway(false);
mKeyguardDisplayManager.hide();
Trace.endSection();
}
@@ -696,7 +698,9 @@
NotificationShadeWindowController notificationShadeWindowController,
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
DismissCallbackRegistry dismissCallbackRegistry,
- @UiBackground Executor uiBgExecutor) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor, DumpController dumpController,
+ @UiBackground Executor uiBgExecutor, PowerManager powerManager,
+ TrustManager trustManager) {
super(context);
mFalsingManager = falsingManager;
mLockPatternUtils = lockPatternUtils;
@@ -705,6 +709,10 @@
mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
mDismissCallbackRegistry = dismissCallbackRegistry;
mUiBgExecutor = uiBgExecutor;
+ mUpdateMonitor = keyguardUpdateMonitor;
+ mPM = powerManager;
+ mTrustManager = trustManager;
+ dumpController.registerDumpable(this);
mShowHomeOverLockscreen = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
@@ -731,9 +739,6 @@
}
private void setupLocked() {
- mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mTrustManager = mContext.getSystemService(TrustManager.class);
-
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -754,8 +759,6 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
-
KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 2c023ca..2ba0315 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -16,9 +16,13 @@
package com.android.systemui.keyguard.dagger;
+import android.app.trust.TrustManager;
import android.content.Context;
+import android.os.PowerManager;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -54,6 +58,10 @@
NotificationShadeWindowController notificationShadeWindowController,
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
DismissCallbackRegistry dismissCallbackRegistry,
+ KeyguardUpdateMonitor updateMonitor,
+ DumpController dumpController,
+ PowerManager powerManager,
+ TrustManager trustManager,
@UiBackground Executor uiBgExecutor) {
return new KeyguardViewMediator(
context,
@@ -63,6 +71,10 @@
notificationShadeWindowController,
statusBarKeyguardViewManagerLazy,
dismissCallbackRegistry,
- uiBgExecutor);
+ updateMonitor,
+ dumpController,
+ uiBgExecutor,
+ powerManager,
+ trustManager);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index aaf4849..711d6a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -19,7 +19,6 @@
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
-import android.graphics.Point
import android.graphics.Rect
import android.renderscript.Allocation
import android.renderscript.Element
@@ -27,9 +26,11 @@
import android.renderscript.ScriptIntrinsicBlur
import android.util.Log
import android.util.MathUtils
+import android.util.Size
+import android.view.WindowManager
+import com.android.internal.annotations.VisibleForTesting
import com.android.internal.graphics.ColorUtils
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
-
import javax.inject.Inject
import javax.inject.Singleton
@@ -41,10 +42,9 @@
@Singleton
class MediaArtworkProcessor @Inject constructor() {
- private val mTmpSize = Point()
private var mArtworkCache: Bitmap? = null
- fun processArtwork(context: Context, artwork: Bitmap): Bitmap? {
+ fun processArtwork(context: Context, artwork: Bitmap, windowType: Int): Bitmap? {
if (mArtworkCache != null) {
return mArtworkCache
}
@@ -54,9 +54,9 @@
var output: Allocation? = null
var inBitmap: Bitmap? = null
try {
- context.display.getSize(mTmpSize)
+ val size = getWindowSize(context, windowType)
val rect = Rect(0, 0, artwork.width, artwork.height)
- MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
+ MathUtils.fitRect(rect, Math.max(size.width / DOWNSAMPLE, size.height / DOWNSAMPLE))
inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
true /* filter */)
// Render script blurs only support ARGB_8888, we need a conversion if we got a
@@ -98,4 +98,15 @@
mArtworkCache?.recycle()
mArtworkCache = null
}
+
+ @VisibleForTesting
+ internal fun getWindowSize(context: Context, windowType: Int): Size {
+ val windowContext = context.display?.let {
+ context.createDisplayContext(it)
+ .createWindowContext(windowType, null)
+ } ?: run { throw NullPointerException("Display is null") }
+ val windowManager = windowContext.getSystemService(WindowManager::class.java)
+ ?: run { throw NullPointerException("Null window manager") }
+ return windowManager.currentWindowMetrics.size
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d0af106..f8db922 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.statusbar;
-import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
@@ -36,7 +35,6 @@
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.AsyncTask;
-import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
@@ -44,6 +42,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
+import android.view.WindowManager;
import android.widget.ImageView;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -52,6 +51,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -73,6 +73,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Executor;
import dagger.Lazy;
@@ -110,7 +111,7 @@
@Nullable
private LockscreenWallpaper mLockscreenWallpaper;
- private final Handler mHandler = Dependency.get(MAIN_HANDLER);
+ private final Executor mMainExecutor;
private final Context mContext;
private final MediaSessionManager mMediaSessionManager;
@@ -181,7 +182,8 @@
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
NotificationEntryManager notificationEntryManager,
MediaArtworkProcessor mediaArtworkProcessor,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ @Main Executor mainExecutor) {
mContext = context;
mMediaArtworkProcessor = mediaArtworkProcessor;
mKeyguardBypassController = keyguardBypassController;
@@ -194,6 +196,7 @@
mStatusBarLazy = statusBarLazy;
mNotificationShadeWindowController = notificationShadeWindowController;
mEntryManager = notificationEntryManager;
+ mMainExecutor = mainExecutor;
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
@@ -623,7 +626,7 @@
mBackdrop.setVisibility(View.GONE);
mBackdropFront.animate().cancel();
mBackdropBack.setImageDrawable(null);
- mHandler.post(mHideBackdropFront);
+ mMainExecutor.execute(mHideBackdropFront);
});
if (mKeyguardStateController.isKeyguardFadingAway()) {
mBackdrop.animate()
@@ -668,7 +671,8 @@
};
private Bitmap processArtwork(Bitmap artwork) {
- return mMediaArtworkProcessor.processArtwork(mContext, artwork);
+ return mMediaArtworkProcessor.processArtwork(mContext, artwork,
+ WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE);
}
@MainThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index 0b37c22..cd5bb77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -43,6 +43,8 @@
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.tracing.ProtoTracer;
+import java.util.concurrent.Executor;
+
import javax.inject.Singleton;
import dagger.Lazy;
@@ -88,14 +90,16 @@
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
NotificationEntryManager notificationEntryManager,
MediaArtworkProcessor mediaArtworkProcessor,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ @Main Executor mainExecutor) {
return new NotificationMediaManager(
context,
statusBarLazy,
notificationShadeWindowController,
notificationEntryManager,
mediaArtworkProcessor,
- keyguardBypassController);
+ keyguardBypassController,
+ mainExecutor);
}
/** */
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 234ab93..5008133 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
@@ -482,6 +482,7 @@
* once per notification as the packageInfo can't technically change for a notification row.
*/
private void cacheIsSystemNotification() {
+ //TODO: This probably shouldn't be in ExpandableNotificationRow
if (mEntry != null && mEntry.mIsSystemNotification == null) {
if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
// Run async task once, only if it hasn't already been executed. Note this is
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index d016217..2dd42c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -40,6 +40,7 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -101,7 +102,8 @@
IActivityManager activityManager, DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
+ KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
+ DumpController dumpController) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
@@ -111,6 +113,7 @@
mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
mColorExtractor = colorExtractor;
+ dumpController.registerDumpable(this);
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
@@ -594,7 +597,7 @@
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("StatusBarWindowController:");
+ pw.println(TAG + ":");
pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode);
pw.println(mCurrentState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
index 0487ce6..ca4b67d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
@@ -132,7 +132,6 @@
*
* @param content The content that has moved.
*/
- @JvmOverloads
fun onContentMoved(content: FloatingContent) {
// Ignore calls when we are currently resolving conflicts, since those calls are from
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index daea7a7..5e4f971 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -203,7 +203,8 @@
// Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mDumpController);
mNotificationShadeWindowController.setNotificationShadeView(
mSuperStatusBarViewFactory.getNotificationShadeWindowView());
mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index b412ca5..6677b80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -197,7 +197,8 @@
// Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mDumpController);
mNotificationShadeWindowController.setNotificationShadeView(
mSuperStatusBarViewFactory.getNotificationShadeWindowView());
mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
index 44454d9..e5ab9be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
@@ -60,10 +60,10 @@
mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
- mClassifier.onTouchEvent(appendMoveEvent(1, 2));
+ mClassifier.onTouchEvent(appendMoveEvent(1, 40));
assertThat(mClassifier.isFalseTouch(), is(true));
- mClassifier.onTouchEvent(appendUpEvent(1, 40));
+ mClassifier.onTouchEvent(appendUpEvent(1, 80));
assertThat(mClassifier.isFalseTouch(), is(false));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index 40075c8..02bfc19e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -45,7 +45,7 @@
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class ControlsBindingControllerTest : SysuiTestCase() {
+class ControlsBindingControllerImplTest : SysuiTestCase() {
companion object {
fun <T> any(): T = Mockito.any<T>()
@@ -95,7 +95,7 @@
assertEquals(1, providers.size)
val provider = providers.first()
- verify(provider).maybeBindAndLoad(callback)
+ verify(provider).maybeBindAndLoad(any())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index ddd6b12..a3e59e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -19,7 +19,6 @@
import android.content.ComponentName
import android.os.UserHandle
import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.actions.ControlAction
@@ -32,13 +31,13 @@
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
@@ -54,8 +53,6 @@
@Mock
private lateinit var actionCallbackService: IControlsActionCallback.Stub
@Mock
- private lateinit var loadCallbackService: IControlsLoadCallback.Stub
- @Mock
private lateinit var subscriberService: IControlsSubscriber.Stub
@Mock
private lateinit var service: IControlsProvider.Stub
@@ -85,7 +82,6 @@
manager = ControlsProviderLifecycleManager(
context,
executor,
- loadCallbackService,
actionCallbackService,
subscriberService,
UserHandle.of(0),
@@ -113,31 +109,29 @@
@Test
fun testMaybeBindAndLoad() {
- manager.maybeBindAndLoad(loadCallback)
+ manager.maybeBindAndLoad(subscriberService)
- verify(service).load(loadCallbackService)
+ verify(service).load(subscriberService)
assertTrue(mContext.isBound(componentName))
- assertEquals(loadCallback, manager.lastLoadCallback)
}
@Test
fun testMaybeUnbind_bindingAndCallback() {
- manager.maybeBindAndLoad(loadCallback)
+ manager.maybeBindAndLoad(subscriberService)
manager.unbindService()
assertFalse(mContext.isBound(componentName))
- assertNull(manager.lastLoadCallback)
}
@Test
fun testMaybeBindAndLoad_timeout() {
- manager.maybeBindAndLoad(loadCallback)
+ manager.maybeBindAndLoad(subscriberService)
executor.advanceClockToLast()
executor.runAllReady()
- verify(loadCallback).error(anyString())
+ verify(subscriberService).onError(any(), anyString())
}
@Test
@@ -160,4 +154,4 @@
eq(actionCallbackService))
assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
index 9e7ce06..cd82844 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
@@ -18,7 +18,6 @@
import android.os.RemoteException
import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
@@ -56,9 +55,6 @@
private lateinit var subscriber: IControlsSubscriber
@Mock
- private lateinit var loadCallback: IControlsLoadCallback
-
- @Mock
private lateinit var actionCallback: IControlsActionCallback
@Captor
@@ -81,16 +77,16 @@
@Test
fun testLoad_happyPath() {
- val result = wrapper.load(loadCallback)
+ val result = wrapper.load(subscriber)
assertTrue(result)
- verify(service).load(loadCallback)
+ verify(service).load(subscriber)
}
@Test
fun testLoad_error() {
`when`(service.load(any())).thenThrow(exception)
- val result = wrapper.load(loadCallback)
+ val result = wrapper.load(subscriber)
assertFalse(result)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index acc30d9..9a707caa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -18,24 +18,30 @@
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -60,6 +66,9 @@
private @Mock NotificationShadeWindowController mNotificationShadeWindowController;
private @Mock BroadcastDispatcher mBroadcastDispatcher;
private @Mock DismissCallbackRegistry mDismissCallbackRegistry;
+ private @Mock DumpController mDumpController;
+ private @Mock PowerManager mPowerManager;
+ private @Mock TrustManager mTrustManager;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private FalsingManagerFake mFalsingManager;
@@ -69,24 +78,33 @@
MockitoAnnotations.initMocks(this);
mFalsingManager = new FalsingManagerFake();
- mDependency.injectTestDependency(FalsingManager.class, mFalsingManager);
- mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
-
when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+ when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
- TestableLooper.get(this).runWithLooper(() -> {
- mViewMediator = new KeyguardViewMediator(
- mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
- mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager,
- mDismissCallbackRegistry, mUiBgExecutor);
- });
+ mViewMediator = new KeyguardViewMediator(
+ mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
+ mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager,
+ mDismissCallbackRegistry, mUpdateMonitor, mDumpController, mUiBgExecutor,
+ mPowerManager, mTrustManager);
+ mViewMediator.start();
}
@Test
public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
- mViewMediator.start();
mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
verify(mUpdateMonitor).setKeyguardGoingAway(false);
verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean());
}
+
+ @Test
+ public void testRegisterDumpable() {
+ verify(mDumpController).registerDumpable(eq(mViewMediator));
+ verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean());
+ }
+
+ @Test
+ public void testKeyguardGone_notGoingaway() {
+ mViewMediator.mViewMediatorCallback.keyguardGone();
+ verify(mNotificationShadeWindowController).setKeyguardGoingAway(eq(false));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
index 72e6df2..a27c085 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
@@ -16,15 +16,14 @@
package com.android.systemui.statusbar
-import com.google.common.truth.Truth.assertThat
-
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
-import android.graphics.Point
import android.testing.AndroidTestingRunner
+import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -32,6 +31,7 @@
private const val WIDTH = 200
private const val HEIGHT = 200
+private const val WINDOW_TYPE = TYPE_NOTIFICATION_SHADE
@RunWith(AndroidTestingRunner::class)
@SmallTest
@@ -46,10 +46,10 @@
fun setUp() {
processor = MediaArtworkProcessor()
- val point = Point()
- context.display.getSize(point)
- screenWidth = point.x
- screenHeight = point.y
+ val size = processor.getWindowSize(context, WINDOW_TYPE)
+
+ screenWidth = size.width
+ screenHeight = size.height
}
@After
@@ -63,7 +63,7 @@
val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
Canvas(artwork).drawColor(Color.BLUE)
// WHEN the background is created from the artwork
- val background = processor.processArtwork(context, artwork)!!
+ val background = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
// THEN the background has the size of the screen that has been downsamples
assertThat(background.height).isLessThan(screenHeight)
assertThat(background.width).isLessThan(screenWidth)
@@ -76,8 +76,8 @@
val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
Canvas(artwork).drawColor(Color.BLUE)
// WHEN the background is processed twice
- val background1 = processor.processArtwork(context, artwork)!!
- val background2 = processor.processArtwork(context, artwork)!!
+ val background1 = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
+ val background2 = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
// THEN the two bitmaps are the same
// Note: This is currently broken and trying to use caching causes issues
assertThat(background1).isNotSameAs(background2)
@@ -89,7 +89,7 @@
val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ALPHA_8)
Canvas(artwork).drawColor(Color.BLUE)
// WHEN the background is created from the artwork
- val background = processor.processArtwork(context, artwork)!!
+ val background = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
// THEN the background has Config ARGB_8888
assertThat(background.config).isEqualTo(Bitmap.Config.ARGB_8888)
}
@@ -102,7 +102,7 @@
// AND the artwork is recycled
artwork.recycle()
// WHEN the background is created from the artwork
- val background = processor.processArtwork(context, artwork)
+ val background = processor.processArtwork(context, artwork, WINDOW_TYPE)
// THEN the processed bitmap is null
assertThat(background).isNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 6a6e5c8..98f12ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -52,73 +52,55 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
-import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.internal.util.NotificationMessagingUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
-import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
-import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.RowContentBindParams;
-import com.android.systemui.statusbar.notification.row.RowContentBindStage;
+import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
-import com.android.systemui.util.time.FakeSystemClock;
-import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+/**
+ * Unit tests for {@link NotificationEntryManager}. This test will not test any interactions with
+ * inflation. Instead, for functional inflation tests, see
+ * {@link NotificationEntryManagerInflationTest}.
+ */
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
@@ -129,17 +111,11 @@
@Mock private NotificationPresenter mPresenter;
@Mock private KeyguardEnvironment mEnvironment;
@Mock private ExpandableNotificationRow mRow;
- @Mock private NotificationListContainer mListContainer;
@Mock private NotificationEntryListener mEntryListener;
@Mock private NotificationRemoveInterceptor mRemoveInterceptor;
- @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private RankingMap mRankingMap;
- @Mock private RemoteInputController mRemoteInputController;
- @Mock private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
- @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGroupManager mGroupManager;
- @Mock private NotificationGutsManager mGutsManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private RowInflaterTask mAsyncInflationTask;
@@ -147,18 +123,12 @@
@Mock private FeatureFlags mFeatureFlags;
@Mock private LeakDetector mLeakDetector;
@Mock private NotificationMediaManager mNotificationMediaManager;
- @Mock private ExpandableNotificationRowComponent.Builder
- mExpandableNotificationRowComponentBuilder;
- @Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
- @Mock private FalsingManager mFalsingManager;
- @Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private NotificationRowBinder mNotificationRowBinder;
private int mId;
private NotificationEntry mEntry;
private StatusBarNotification mSbn;
- private TestableNotificationEntryManager mEntryManager;
- private CountDownLatch mCountDownLatch;
+ private NotificationEntryManager mEntryManager;
private void setUserSentiment(String key, int sentiment) {
doAnswer(invocationOnMock -> {
@@ -202,41 +172,16 @@
MockitoAnnotations.initMocks(this);
mDependency.injectMockDependency(SmartReplyController.class);
- mCountDownLatch = new CountDownLatch(1);
-
allowTestableLooperAsMainThread();
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
Handler.createAsync(TestableLooper.get(this).getLooper()));
- when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
- when(mListContainer.getViewParentForNotification(any())).thenReturn(
- new FrameLayout(mContext));
mEntry = createNotification();
mSbn = mEntry.getSbn();
- mEntry.expandedIcon = mock(StatusBarIconView.class);
-
- RowContentBindStage bindStage = mock(RowContentBindStage.class);
- when(bindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
- NotificationRowBinderImpl notificationRowBinder =
- new NotificationRowBinderImpl(mContext,
- new NotificationMessagingUtil(mContext),
- mRemoteInputManager,
- mLockscreenUserManager,
- mock(NotifBindPipeline.class),
- bindStage,
- true, /* allowLongPress */
- mKeyguardBypassController,
- mStatusBarStateController,
- mGroupManager,
- mGutsManager,
- mNotificationInterruptionStateProvider,
- RowInflaterTask::new,
- mExpandableNotificationRowComponentBuilder);
-
when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
- mEntryManager = new TestableNotificationEntryManager(
+ mEntryManager = new NotificationEntryManager(
mLogger,
mGroupManager,
new NotificationRankingManager(
@@ -250,7 +195,7 @@
mock(HighPriorityProvider.class)),
mEnvironment,
mFeatureFlags,
- () -> notificationRowBinder,
+ () -> mNotificationRowBinder,
() -> mRemoteInputManager,
mLeakDetector,
mock(ForegroundServiceDismissalFeatureController.class)
@@ -259,152 +204,45 @@
mEntryManager.addNotificationEntryListener(mEntryListener);
mEntryManager.addNotificationRemoveInterceptor(mRemoveInterceptor);
- notificationRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
- notificationRowBinder.setInflationCallback(mEntryManager);
- notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
-
- setUserSentiment(
- mEntry.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
-
- ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
- ArgumentCaptor.forClass(ExpandableNotificationRow.class);
- when(mExpandableNotificationRowComponentBuilder
- .expandableNotificationRow(viewCaptor.capture()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .notificationEntry(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .onDismissRunnable(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .inflationCallback(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .rowContentBindStage(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .onExpandClickListener(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
-
- when(mExpandableNotificationRowComponentBuilder.build())
- .thenReturn(mExpandableNotificationRowComponent);
- when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
- .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
- new ExpandableNotificationRowController(
- viewCaptor.getValue(),
- mock(ActivatableNotificationViewController.class),
- mNotificationMediaManager,
- mock(PluginManager.class),
- new FakeSystemClock(),
- "FOOBAR", "FOOBAR",
- mKeyguardBypassController,
- mGroupManager,
- bindStage,
- mock(NotificationLogger.class),
- mHeadsUpManager,
- mPresenter,
- mStatusBarStateController,
- mEntryManager,
- mGutsManager,
- true,
- null,
- mFalsingManager
- ));
+ setUserSentiment(mSbn.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
}
- @After
- public void tearDown() {
- // CLEAN UP inflation tasks so they don't callback in a future test
- mEntry.abortTask();
- }
-
- // TODO: These tests are closer to functional tests and we should move them to their own file.
- // and also strip some of the verifies that make the test too complex
@Test
- @Ignore
- public void testAddNotification() throws Exception {
- TestableLooper.get(this).processAllMessages();
-
- doAnswer(invocation -> {
- mCountDownLatch.countDown();
- return null;
- }).when(mBindCallback).onBindRow(any(), any(), any(), any());
-
- // Post on main thread, otherwise we will be stuck waiting here for the inflation finished
- // callback forever, since it won't execute until the tests ends.
+ public void testAddNotification_setsUserSentiment() {
mEntryManager.addNotification(mSbn, mRankingMap);
- TestableLooper.get(this).processMessages(1);
- assertTrue(mCountDownLatch.await(10, TimeUnit.SECONDS));
- assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
- // Check that no inflation error occurred.
- verify(mEntryListener, never()).onInflationError(any(), any());
-
- // Row inflation:
ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
NotificationEntry.class);
- verify(mBindCallback).onBindRow(entryCaptor.capture(), any(), eq(mSbn), any());
+ verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
NotificationEntry entry = entryCaptor.getValue();
- verify(mRemoteInputManager).bindRow(entry.getRow());
- // Row content inflation:
- verify(mEntryListener).onNotificationAdded(entry);
- verify(mPresenter).updateNotificationViews();
-
- assertEquals(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()), entry);
- assertNotNull(entry.getRow());
- assertEquals(mEntry.getUserSentiment(),
- Ranking.USER_SENTIMENT_NEUTRAL);
+ assertEquals(entry.getUserSentiment(), Ranking.USER_SENTIMENT_NEUTRAL);
}
@Test
- @Ignore
- public void testUpdateNotification() throws Exception {
- TestableLooper.get(this).processAllMessages();
-
+ public void testUpdateNotification_updatesUserSentiment() {
mEntryManager.addActiveNotificationForTest(mEntry);
-
setUserSentiment(
mEntry.getKey(), Ranking.USER_SENTIMENT_NEGATIVE);
mEntryManager.updateNotification(mSbn, mRankingMap);
- TestableLooper.get(this).processMessages(1);
- // Wait for content update.
- assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
- verify(mEntryListener, never()).onInflationError(any(), any());
-
- verify(mEntryListener).onPreEntryUpdated(mEntry);
- verify(mPresenter).updateNotificationViews();
- verify(mEntryListener).onPostEntryUpdated(mEntry);
-
- assertNotNull(mEntry.getRow());
- assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
- mEntry.getUserSentiment());
+ assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, mEntry.getUserSentiment());
}
@Test
- @Ignore
public void testUpdateNotification_prePostEntryOrder() throws Exception {
TestableLooper.get(this).processAllMessages();
mEntryManager.addActiveNotificationForTest(mEntry);
mEntryManager.updateNotification(mSbn, mRankingMap);
- TestableLooper.get(this).processMessages(1);
- // Wait for content update.
- assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
-
- verify(mEntryListener, never()).onInflationError(any(), any());
// Ensure that update callbacks happen in correct order
InOrder order = inOrder(mEntryListener, mPresenter, mEntryListener);
order.verify(mEntryListener).onPreEntryUpdated(mEntry);
order.verify(mPresenter).updateNotificationViews();
order.verify(mEntryListener).onPostEntryUpdated(mEntry);
-
- assertNotNull(mEntry.getRow());
}
@Test
@@ -414,8 +252,6 @@
mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
- verify(mEntryListener, never()).onInflationError(any(), any());
-
verify(mPresenter).updateNotificationViews();
verify(mEntryListener).onEntryRemoved(
eq(mEntry), any(), eq(false) /* removedByUser */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
new file mode 100644
index 0000000..ac40808
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2020 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.notification.row;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.os.Handler;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.NotificationMessagingUtil;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.SbnBuilder;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotificationClicker;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
+import com.android.systemui.statusbar.notification.NotificationFilter;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
+import com.android.systemui.util.leak.LeakDetector;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Functional tests for notification inflation from {@link NotificationEntryManager}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class NotificationEntryManagerInflationTest extends SysuiTestCase {
+
+ private static final String TEST_TITLE = "Title";
+ private static final String TEST_TEXT = "Text";
+ private static final long TIMEOUT_TIME = 10000;
+ private static final Runnable TIMEOUT_RUNNABLE = () -> {
+ throw new RuntimeException("Timed out waiting to inflate");
+ };
+
+ @Mock private NotificationPresenter mPresenter;
+ @Mock private NotificationEntryManager.KeyguardEnvironment mEnvironment;
+ @Mock private NotificationListContainer mListContainer;
+ @Mock private NotificationEntryListener mEntryListener;
+ @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
+ @Mock private HeadsUpManager mHeadsUpManager;
+ @Mock private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+ @Mock private NotificationGutsManager mGutsManager;
+ @Mock private NotificationRemoteInputManager mRemoteInputManager;
+ @Mock private NotificationMediaManager mNotificationMediaManager;
+ @Mock private ExpandableNotificationRowComponent.Builder
+ mExpandableNotificationRowComponentBuilder;
+ @Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
+ @Mock private FalsingManager mFalsingManager;
+ @Mock private KeyguardBypassController mKeyguardBypassController;
+ @Mock private StatusBarStateController mStatusBarStateController;
+
+ @Mock private NotificationGroupManager mGroupManager;
+ @Mock private FeatureFlags mFeatureFlags;
+ @Mock private LeakDetector mLeakDetector;
+
+ @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
+ @Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
+
+ private StatusBarNotification mSbn;
+ private NotificationListenerService.RankingMap mRankingMap;
+ private NotificationEntryManager mEntryManager;
+ private NotificationRowBinderImpl mRowBinder;
+ private Handler mHandler;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDependency.injectMockDependency(SmartReplyController.class);
+
+ mHandler = Handler.createAsync(TestableLooper.get(this).getLooper());
+
+ Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle(TEST_TITLE)
+ .setContentText(TEST_TEXT)
+ .build();
+ mSbn = new SbnBuilder()
+ .setNotification(notification)
+ .build();
+
+ when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
+ when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+
+ mEntryManager = new NotificationEntryManager(
+ mock(NotificationEntryManagerLogger.class),
+ mGroupManager,
+ new NotificationRankingManager(
+ () -> mock(NotificationMediaManager.class),
+ mGroupManager,
+ mHeadsUpManager,
+ mock(NotificationFilter.class),
+ mock(NotificationEntryManagerLogger.class),
+ mock(NotificationSectionsFeatureManager.class),
+ mock(PeopleNotificationIdentifier.class),
+ mock(HighPriorityProvider.class)),
+ mEnvironment,
+ mFeatureFlags,
+ () -> mRowBinder,
+ () -> mRemoteInputManager,
+ mLeakDetector,
+ mock(ForegroundServiceDismissalFeatureController.class)
+ );
+
+ NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
+ NotifBindPipeline pipeline = new NotifBindPipeline(
+ mEntryManager,
+ mock(NotifBindPipelineLogger.class));
+ NotificationContentInflater binder = new NotificationContentInflater(
+ cache,
+ mRemoteInputManager,
+ () -> mock(SmartReplyConstants.class),
+ () -> mock(SmartReplyController.class));
+ RowContentBindStage stage = new RowContentBindStage(
+ binder,
+ mock(NotifInflationErrorManager.class),
+ mock(RowContentBindStageLogger.class));
+ pipeline.setStage(stage);
+
+ ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
+ ArgumentCaptor.forClass(ExpandableNotificationRow.class);
+ when(mExpandableNotificationRowComponentBuilder
+ .expandableNotificationRow(viewCaptor.capture()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+ when(mExpandableNotificationRowComponentBuilder
+ .notificationEntry(any()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+ when(mExpandableNotificationRowComponentBuilder
+ .onDismissRunnable(any()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+ when(mExpandableNotificationRowComponentBuilder
+ .inflationCallback(any()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+ when(mExpandableNotificationRowComponentBuilder
+ .rowContentBindStage(any()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+ when(mExpandableNotificationRowComponentBuilder
+ .onExpandClickListener(any()))
+ .thenReturn(mExpandableNotificationRowComponentBuilder);
+
+ when(mExpandableNotificationRowComponentBuilder.build())
+ .thenReturn(mExpandableNotificationRowComponent);
+ when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
+ .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
+ new ExpandableNotificationRowController(
+ viewCaptor.getValue(),
+ mock(ActivatableNotificationViewController.class),
+ mNotificationMediaManager,
+ mock(PluginManager.class),
+ new FakeSystemClock(),
+ "FOOBAR", "FOOBAR",
+ mKeyguardBypassController,
+ mGroupManager,
+ stage,
+ mock(NotificationLogger.class),
+ mHeadsUpManager,
+ mPresenter,
+ mStatusBarStateController,
+ mEntryManager,
+ mGutsManager,
+ true,
+ null,
+ mFalsingManager
+ ));
+
+ when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
+ .thenReturn(mNotificationRowComponentBuilder);
+ when(mNotificationRowComponentBuilder.build()).thenReturn(
+ () -> mActivatableNotificationViewController);
+
+ mRowBinder = new NotificationRowBinderImpl(
+ mContext,
+ new NotificationMessagingUtil(mContext),
+ mRemoteInputManager,
+ mLockscreenUserManager,
+ pipeline,
+ stage,
+ true, /* allowLongPress */
+ mock(KeyguardBypassController.class),
+ mock(StatusBarStateController.class),
+ mGroupManager,
+ mGutsManager,
+ mNotificationInterruptionStateProvider,
+ RowInflaterTask::new,
+ mExpandableNotificationRowComponentBuilder);
+
+ mEntryManager.setUpWithPresenter(mPresenter);
+ mEntryManager.addNotificationEntryListener(mEntryListener);
+
+ mRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
+ mRowBinder.setInflationCallback(mEntryManager);
+ mRowBinder.setNotificationClicker(mock(NotificationClicker.class));
+
+ Ranking ranking = new Ranking();
+ ranking.populate(
+ mSbn.getKey(),
+ 0,
+ false,
+ 0,
+ 0,
+ IMPORTANCE_DEFAULT,
+ null,
+ null,
+ null,
+ null,
+ null,
+ true,
+ Ranking.USER_SENTIMENT_NEUTRAL,
+ false,
+ -1,
+ false,
+ null,
+ null,
+ false,
+ false,
+ false);
+ mRankingMap = new NotificationListenerService.RankingMap(new Ranking[] {ranking});
+
+ TestableLooper.get(this).processAllMessages();
+ }
+
+ @After
+ public void cleanUp() {
+ // Don't leave anything on main thread
+ TestableLooper.get(this).processAllMessages();
+ }
+
+ @Test
+ public void testAddNotification() {
+ // WHEN a notification is added
+ mEntryManager.addNotification(mSbn, mRankingMap);
+ ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
+ NotificationEntry.class);
+ verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
+ NotificationEntry entry = entryCaptor.getValue();
+
+ // Wait for inflation
+ // row inflation, system notification, remote views, contracted view
+ waitForMessages(4);
+
+ // THEN the notification has its row inflated
+ assertNotNull(entry.getRow());
+ assertNotNull(entry.getRow().getPrivateLayout().getContractedChild());
+
+ // THEN inflation callbacks are called
+ verify(mBindCallback).onBindRow(eq(entry), any(), eq(mSbn), any());
+ verify(mEntryListener, never()).onInflationError(any(), any());
+ verify(mEntryListener).onEntryInflated(entry);
+ verify(mEntryListener).onNotificationAdded(entry);
+
+ // THEN the notification is active
+ assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
+
+ // THEN we update the presenter
+ verify(mPresenter).updateNotificationViews();
+ }
+
+ @Test
+ public void testUpdateNotification() {
+ // GIVEN a notification already added
+ mEntryManager.addNotification(mSbn, mRankingMap);
+ ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
+ NotificationEntry.class);
+ verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
+ NotificationEntry entry = entryCaptor.getValue();
+ waitForMessages(4);
+
+ Mockito.reset(mEntryListener);
+ Mockito.reset(mPresenter);
+
+ // WHEN the notification is updated
+ mEntryManager.updateNotification(mSbn, mRankingMap);
+
+ // Wait for inflation
+ // remote views, contracted view
+ waitForMessages(2);
+
+ // THEN the notification has its row and inflated
+ assertNotNull(entry.getRow());
+
+ // THEN inflation callbacks are called
+ verify(mEntryListener, never()).onInflationError(any(), any());
+ verify(mEntryListener).onEntryReinflated(entry);
+
+ // THEN we update the presenter
+ verify(mPresenter).updateNotificationViews();
+ }
+
+ /**
+ * Wait for a certain number of messages to finish before continuing, timing out if they never
+ * occur.
+ *
+ * As part of the inflation pipeline, the main thread is forced to deal with several callbacks
+ * due to the nature of the API used (generally because they're {@link android.os.AsyncTask}
+ * callbacks). In order, these are
+ *
+ * 1) Callback after row inflation. See {@link RowInflaterTask}.
+ * 2) Callback checking if row is system notification. See
+ * {@link ExpandableNotificationRow#setEntry}
+ * 3) Callback after remote views are created. See
+ * {@link NotificationContentInflater.AsyncInflationTask}.
+ * 4-6) Callback after each content view is inflated/rebound from remote view. See
+ * {@link NotificationContentInflater#applyRemoteView} and {@link InflationFlag}.
+ *
+ * Depending on the test, only some of these will be necessary. For example, generally, not
+ * every content view is inflated or the row may not be inflated if one already exists.
+ *
+ * Currently, the burden is on the developer to figure these out until we have a much more
+ * test-friendly way of executing inflation logic (i.e. pass in an executor).
+ */
+ private void waitForMessages(int numMessages) {
+ mHandler.postDelayed(TIMEOUT_RUNNABLE, TIMEOUT_TIME);
+ TestableLooper.get(this).processMessages(numMessages);
+ mHandler.removeCallbacks(TIMEOUT_RUNNABLE);
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
index 7d52df7..2782f3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
@@ -32,6 +32,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -58,6 +59,7 @@
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
+ @Mock private DumpController mDumpController;
private NotificationShadeWindowController mNotificationShadeWindowController;
@@ -69,7 +71,8 @@
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mDumpController);
mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
mNotificationShadeWindowController.attach();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 3b0a1a3..d86b223 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2120,8 +2120,6 @@
private void unmount(VolumeInfo vol) {
try {
- mVold.unmount(vol.id);
- mStorageSessionController.onVolumeUnmount(vol);
try {
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
@@ -2129,6 +2127,8 @@
} catch (Installer.InstallerException e) {
Slog.e(TAG, "Failed unmount mirror data", e);
}
+ mVold.unmount(vol.id);
+ mStorageSessionController.onVolumeUnmount(vol);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -4346,6 +4346,42 @@
mPolicies.add(policy);
}
+ /**
+ * Check if fuse is running in target user, if it's running then setup its obb directories.
+ * TODO: System server should store a list of active pids that obb is not mounted and use it.
+ */
+ @Override
+ public void prepareObbDirs(int userId, Set<String> packageList, String processName) {
+ String fuseRunningUsersList = SystemProperties.get("vold.fuse_running_users", "");
+ String[] fuseRunningUsers = fuseRunningUsersList.split(",");
+ boolean fuseReady = false;
+ String targetUserId = String.valueOf(userId);
+ for (String user : fuseRunningUsers) {
+ if (targetUserId.equals(user)) {
+ fuseReady = true;
+ }
+ }
+ if (fuseReady) {
+ try {
+ final IVold vold = IVold.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("vold"));
+ for (String pkg : packageList) {
+ final String obbDir =
+ String.format("/storage/emulated/%d/Android/obb", userId);
+ final String packageObbDir = String.format("%s/%s/", obbDir, pkg);
+
+ // Create package obb dir if it doesn't exist.
+ File file = new File(packageObbDir);
+ if (!file.exists()) {
+ vold.setupAppDir(packageObbDir, mPmInternal.getPackage(pkg).getUid());
+ }
+ }
+ } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
+ Slog.e(TAG, "Unable to create obb directories for " + processName, e);
+ }
+ }
+ }
+
@Override
public void onExternalStoragePolicyChanged(int uid, String packageName) {
final int mountMode = getExternalStorageMountMode(uid, packageName);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index ffa7d92..0dc44f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -80,11 +80,13 @@
import android.os.DropBoxManager;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IVold;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -142,10 +144,14 @@
public final class ProcessList {
static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
- // A device config to control the minimum target SDK to enable app data isolation
+ // A system property to control if app data isolation is enabled.
static final String ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.zygote.app_data_isolation";
+ // A system property to control if obb app data isolation is enabled in vold.
+ static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.sys.vold_app_data_isolation_enabled";
+
// A device config to control the minimum target SDK to enable app data isolation
static final String ANDROID_APP_DATA_ISOLATION_MIN_SDK = "android_app_data_isolation_min_sdk";
@@ -379,6 +385,8 @@
private boolean mAppDataIsolationEnabled = false;
+ private boolean mVoldAppDataIsolationEnabled = false;
+
private ArrayList<String> mAppDataIsolationWhitelistedApps;
/**
@@ -691,6 +699,8 @@
// want some apps enabled while some apps disabled
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mAppDataIsolationWhitelistedApps = new ArrayList<>(
SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
@@ -2113,6 +2123,13 @@
app.info.packageName, app.userId);
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages, uid);
+
+ if (mVoldAppDataIsolationEnabled) {
+ StorageManagerInternal storageManagerInternal = LocalServices.getService(
+ StorageManagerInternal.class);
+ storageManagerInternal.prepareObbDirs(UserHandle.getUserId(uid),
+ pkgDataInfoMap.keySet(), app.processName);
+ }
} else {
pkgDataInfoMap = null;
}
diff --git a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
index 09af655..bc50ebc 100644
--- a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
@@ -20,7 +20,6 @@
import android.location.GnssAntennaInfo;
import android.location.IGnssAntennaInfoListener;
import android.os.Handler;
-import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -100,41 +99,10 @@
@Override
protected ListenerOperation<IGnssAntennaInfoListener> getHandlerOperation(int result) {
- int status;
- switch (result) {
- case RESULT_SUCCESS:
- status = GnssAntennaInfo.Callback.STATUS_READY;
- break;
- case RESULT_NOT_AVAILABLE:
- case RESULT_NOT_SUPPORTED:
- case RESULT_INTERNAL_ERROR:
- status = GnssAntennaInfo.Callback.STATUS_NOT_SUPPORTED;
- break;
- case RESULT_GPS_LOCATION_DISABLED:
- status = GnssAntennaInfo.Callback.STATUS_LOCATION_DISABLED;
- break;
- case RESULT_UNKNOWN:
- return null;
- default:
- Log.v(TAG, "Unhandled addListener result: " + result);
- return null;
- }
- return new StatusChangedOperation(status);
- }
-
- private static class StatusChangedOperation
- implements ListenerOperation<IGnssAntennaInfoListener> {
- private final int mStatus;
-
- StatusChangedOperation(int status) {
- mStatus = status;
- }
-
- @Override
- public void execute(IGnssAntennaInfoListener listener,
- CallerIdentity callerIdentity) throws RemoteException {
- listener.onStatusChanged(mStatus);
- }
+ return (IGnssAntennaInfoListener listener,
+ CallerIdentity callerIdentity) -> {
+ // Do nothing, as GnssAntennaInfo.Callback does not have an onStatusChanged method.
+ };
}
/** Handle Gnss Antenna Info report. */
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 36136f4..5f44e04 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2244,6 +2244,7 @@
if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
s.append("MEASUREMENT_CORRECTIONS ");
}
+ if (hasCapability(GPS_CAPABILITY_ANTENNA_INFO)) s.append("ANTENNA_INFO ");
s.append(")\n");
if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
s.append("SubHal=MEASUREMENT_CORRECTIONS[");
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 1039cf6..b57c261 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -216,9 +216,6 @@
* {@link android.location.GnssCapabilities}.
*/
public long getGnssCapabilities(String packageName) {
- mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
- mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
if (!checkLocationAppOp(packageName)) {
return GnssCapabilities.INVALID_CAPABILITIES;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 3a16217..09e3feb 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
-import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -307,8 +306,8 @@
final int callingUserId = injectCallingUserId();
if (targetUserId == callingUserId) return true;
- if (mContext.checkCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL)
- == PackageManager.PERMISSION_GRANTED) {
+ if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(),
+ injectBinderCallingUid())) {
return true;
}
@@ -684,6 +683,15 @@
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
}
+ /**
+ * Returns true if the caller has the "INTERACT_ACROSS_USERS_FULL" permission.
+ */
+ @VisibleForTesting
+ boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
+ return mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
String packageName, List shortcutIds, List<LocusId> locusIds,
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e6eaf21..9c945d5 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -150,6 +150,12 @@
ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
+ private static final Set<String> FOREGROUND_LOCATION_PERMISSIONS = new ArraySet<>();
+ static {
+ ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
+ ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
+ }
+
private static final Set<String> COARSE_BACKGROUND_LOCATION_PERMISSIONS = new ArraySet<>();
static {
COARSE_BACKGROUND_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
@@ -587,11 +593,6 @@
DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
userId, CONTACTS_PERMISSIONS);
- // Maps
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
- userId, ALWAYS_LOCATION_PERMISSIONS);
-
// Email
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackageForCategory(
@@ -609,7 +610,7 @@
}
}
grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */,
- true /*whitelistRestrictedPermissions*/, ALWAYS_LOCATION_PERMISSIONS);
+ true /*whitelistRestrictedPermissions*/, FOREGROUND_LOCATION_PERMISSIONS);
// Voice interaction
if (voiceInteractPackageNames != null) {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e1615af..36ed9a5 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -55,10 +55,9 @@
static jclass class_gnssNavigationMessage;
static jclass class_gnssClock;
static jclass class_gnssConfiguration_halInterfaceVersion;
-static jclass class_gnssAntennaInfo;
-static jclass class_phaseCenterOffsetCoordinates;
-static jclass class_phaseCenterVariationCorrections;
-static jclass class_signalGainCorrections;
+static jclass class_gnssAntennaInfoBuilder;
+static jclass class_phaseCenterOffset;
+static jclass class_sphericalCorrections;
static jclass class_arrayList;
static jclass class_doubleArray;
@@ -122,12 +121,16 @@
static jmethodID method_gnssClockCtor;
static jmethodID method_gnssMeasurementCtor;
static jmethodID method_halInterfaceVersionCtor;
-static jmethodID method_gnssAntennaInfoCtor;
-static jmethodID method_phaseCenterOffsetCoordinatesCtor;
-static jmethodID method_phaseCenterVariationCorrectionsCtor;
-static jmethodID method_signalGainCorrectionsCtor;
+static jmethodID method_gnssAntennaInfoBuilderCtor;
+static jmethodID method_phaseCenterOffsetCtor;
+static jmethodID method_sphericalCorrectionsCtor;
static jmethodID method_arrayListCtor;
static jmethodID method_arrayListAdd;
+static jmethodID method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz;
+static jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterOffset;
+static jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections;
+static jmethodID method_gnssAntennaInfoBuilderSetSignalGainCorrections;
+static jmethodID method_gnssAntennaInfoBuilderBuild;
/*
* Save a pointer to JavaVm to attach/detach threads executing
@@ -1088,7 +1091,7 @@
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
jobject translateSingleGnssAntennaInfo(
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
- jobject translatePhaseCenterOffsetCoordinates(
+ jobject translatePhaseCenterOffset(
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
jobject translatePhaseCenterVariationCorrections(
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
@@ -1150,11 +1153,10 @@
return arrayList;
}
-jobject GnssAntennaInfoCallback::translatePhaseCenterOffsetCoordinates(
+jobject GnssAntennaInfoCallback::translatePhaseCenterOffset(
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
- jobject phaseCenterOffsetCoordinates =
- env->NewObject(class_phaseCenterOffsetCoordinates,
- method_phaseCenterOffsetCoordinatesCtor,
+ jobject phaseCenterOffset =
+ env->NewObject(class_phaseCenterOffset, method_phaseCenterOffsetCtor,
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x,
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty,
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y,
@@ -1162,7 +1164,7 @@
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z,
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty);
- return phaseCenterOffsetCoordinates;
+ return phaseCenterOffset;
}
jobject GnssAntennaInfoCallback::translatePhaseCenterVariationCorrections(
@@ -1185,8 +1187,7 @@
}
jobject phaseCenterVariationCorrections =
- env->NewObject(class_phaseCenterVariationCorrections,
- method_phaseCenterVariationCorrectionsCtor,
+ env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
phaseCenterVariationCorrectionsArray,
phaseCenterVariationCorrectionsUncertaintiesArray);
@@ -1212,7 +1213,7 @@
}
jobject signalGainCorrections =
- env->NewObject(class_signalGainCorrections, method_signalGainCorrectionsCtor,
+ env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
signalGainCorrectionsArray, signalGainCorrectionsUncertaintiesArray);
env->DeleteLocalRef(signalGainCorrectionsArray);
@@ -1223,8 +1224,7 @@
jobject GnssAntennaInfoCallback::translateSingleGnssAntennaInfo(
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
- jobject phaseCenterOffsetCoordinates =
- translatePhaseCenterOffsetCoordinates(env, gnssAntennaInfo);
+ jobject phaseCenterOffset = translatePhaseCenterOffset(env, gnssAntennaInfo);
// Nullable
jobject phaseCenterVariationCorrections =
@@ -1233,13 +1233,29 @@
// Nullable
jobject signalGainCorrections = translateSignalGainCorrections(env, gnssAntennaInfo);
+ // Get builder
+ jobject gnssAntennaInfoBuilderObject =
+ env->NewObject(class_gnssAntennaInfoBuilder, method_gnssAntennaInfoBuilderCtor);
+
+ // Set fields
+ env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz,
+ gnssAntennaInfo.carrierFrequencyMHz);
+ env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetPhaseCenterOffset, phaseCenterOffset);
+ env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections,
+ phaseCenterVariationCorrections);
+ env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetSignalGainCorrections,
+ signalGainCorrections);
+
+ // build
jobject gnssAntennaInfoObject =
- env->NewObject(class_gnssAntennaInfo, method_gnssAntennaInfoCtor,
- gnssAntennaInfo.carrierFrequencyMHz, phaseCenterOffsetCoordinates,
- phaseCenterVariationCorrections, signalGainCorrections);
+ env->CallObjectMethod(gnssAntennaInfoBuilderObject, method_gnssAntennaInfoBuilderBuild);
// Delete Local Refs
- env->DeleteLocalRef(phaseCenterOffsetCoordinates);
+ env->DeleteLocalRef(phaseCenterOffset);
env->DeleteLocalRef(phaseCenterVariationCorrections);
env->DeleteLocalRef(signalGainCorrections);
@@ -2004,35 +2020,38 @@
class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
- jclass gnssAntennaInfoClass = env->FindClass("android/location/GnssAntennaInfo");
- class_gnssAntennaInfo = (jclass)env->NewGlobalRef(gnssAntennaInfoClass);
- method_gnssAntennaInfoCtor =
- env->GetMethodID(class_gnssAntennaInfo, "<init>",
- "(D"
- "Landroid/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates;"
- "Landroid/location/GnssAntennaInfo$PhaseCenterVariationCorrections;"
- "Landroid/location/GnssAntennaInfo$SignalGainCorrections;"
- ")V");
+ jclass gnssAntennaInfoBuilder = env->FindClass("android/location/GnssAntennaInfo$Builder");
+ class_gnssAntennaInfoBuilder = (jclass)env->NewGlobalRef(gnssAntennaInfoBuilder);
+ method_gnssAntennaInfoBuilderCtor =
+ env->GetMethodID(class_gnssAntennaInfoBuilder, "<init>", "()V");
+ method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz =
+ env->GetMethodID(class_gnssAntennaInfoBuilder, "setCarrierFrequencyMHz",
+ "(D)Landroid/location/GnssAntennaInfo$Builder;");
+ method_gnssAntennaInfoBuilderSetPhaseCenterOffset =
+ env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterOffset",
+ "(Landroid/location/GnssAntennaInfo$PhaseCenterOffset;)"
+ "Landroid/location/GnssAntennaInfo$Builder;");
+ method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections =
+ env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterVariationCorrections",
+ "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
+ "Landroid/location/GnssAntennaInfo$Builder;");
+ method_gnssAntennaInfoBuilderSetSignalGainCorrections =
+ env->GetMethodID(class_gnssAntennaInfoBuilder, "setSignalGainCorrections",
+ "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
+ "Landroid/location/GnssAntennaInfo$Builder;");
+ method_gnssAntennaInfoBuilderBuild = env->GetMethodID(class_gnssAntennaInfoBuilder, "build",
+ "()Landroid/location/GnssAntennaInfo;");
- jclass phaseCenterOffsetCoordinatesClass =
- env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates");
- class_phaseCenterOffsetCoordinates =
- (jclass)env->NewGlobalRef(phaseCenterOffsetCoordinatesClass);
- method_phaseCenterOffsetCoordinatesCtor =
- env->GetMethodID(class_phaseCenterOffsetCoordinates, "<init>", "(DDDDDD)V");
+ jclass phaseCenterOffsetClass =
+ env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffset");
+ class_phaseCenterOffset = (jclass)env->NewGlobalRef(phaseCenterOffsetClass);
+ method_phaseCenterOffsetCtor = env->GetMethodID(class_phaseCenterOffset, "<init>", "(DDDDDD)V");
- jclass phaseCenterVariationCorrectionsClass =
- env->FindClass("android/location/GnssAntennaInfo$PhaseCenterVariationCorrections");
- class_phaseCenterVariationCorrections =
- (jclass)env->NewGlobalRef(phaseCenterVariationCorrectionsClass);
- method_phaseCenterVariationCorrectionsCtor =
- env->GetMethodID(class_phaseCenterVariationCorrections, "<init>", "([[D[[D)V");
-
- jclass signalGainCorrectionsClass =
- env->FindClass("android/location/GnssAntennaInfo$SignalGainCorrections");
- class_signalGainCorrections = (jclass)env->NewGlobalRef(signalGainCorrectionsClass);
- method_signalGainCorrectionsCtor =
- env->GetMethodID(class_signalGainCorrections, "<init>", "([[D[[D)V");
+ jclass sphericalCorrectionsClass =
+ env->FindClass("android/location/GnssAntennaInfo$SphericalCorrections");
+ class_sphericalCorrections = (jclass)env->NewGlobalRef(sphericalCorrectionsClass);
+ method_sphericalCorrectionsCtor =
+ env->GetMethodID(class_sphericalCorrections, "<init>", "([[D[[D)V");
jclass locationClass = env->FindClass("android/location/Location");
class_location = (jclass) env->NewGlobalRef(locationClass);
diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index 19cbb0e..a99c982 100644
--- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -38,6 +38,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.GnssAntennaInfo;
+import android.location.GnssAntennaInfo.SphericalCorrections;
import android.location.GnssClock;
import android.location.GnssMeasurementCorrections;
import android.location.GnssMeasurementsEvent;
@@ -245,8 +246,8 @@
private static List<GnssAntennaInfo> createDummyGnssAntennaInfos() {
double carrierFrequencyMHz = 13758.0;
- GnssAntennaInfo.PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates = new
- GnssAntennaInfo.PhaseCenterOffsetCoordinates(
+ GnssAntennaInfo.PhaseCenterOffset phaseCenterOffset = new
+ GnssAntennaInfo.PhaseCenterOffset(
4.3d,
1.4d,
2.10d,
@@ -256,22 +257,26 @@
double[][] phaseCenterVariationCorrectionsMillimeters = new double[10][10];
double[][] phaseCenterVariationCorrectionsUncertaintyMillimeters = new double[10][10];
- GnssAntennaInfo.PhaseCenterVariationCorrections
+ SphericalCorrections
phaseCenterVariationCorrections =
- new GnssAntennaInfo.PhaseCenterVariationCorrections(
+ new SphericalCorrections(
phaseCenterVariationCorrectionsMillimeters,
phaseCenterVariationCorrectionsUncertaintyMillimeters);
double[][] signalGainCorrectionsDbi = new double[10][10];
double[][] signalGainCorrectionsUncertaintyDbi = new double[10][10];
- GnssAntennaInfo.SignalGainCorrections signalGainCorrections = new
- GnssAntennaInfo.SignalGainCorrections(
+ SphericalCorrections signalGainCorrections = new
+ SphericalCorrections(
signalGainCorrectionsDbi,
signalGainCorrectionsUncertaintyDbi);
List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList();
- gnssAntennaInfos.add(new GnssAntennaInfo(carrierFrequencyMHz, phaseCenterOffsetCoordinates,
- phaseCenterVariationCorrections, signalGainCorrections));
+ gnssAntennaInfos.add(new GnssAntennaInfo.Builder()
+ .setCarrierFrequencyMHz(carrierFrequencyMHz)
+ .setPhaseCenterOffset(phaseCenterOffset)
+ .setPhaseCenterVariationCorrections(phaseCenterVariationCorrections)
+ .setSignalGainCorrections(signalGainCorrections)
+ .build());
return gnssAntennaInfos;
}
@@ -388,14 +393,6 @@
}
@Test
- public void getGnssCapabilitiesWithoutPermissionsTest() {
- disableLocationPermissions();
-
- assertThrows(SecurityException.class,
- () -> mGnssManagerService.getGnssCapabilities("com.android.server"));
- }
-
- @Test
public void getGnssCapabilitiesWithPermissionsTest() {
final long mGnssCapabilities = 23132L;
when(mMockGnssCapabilitiesProvider.getGnssCapabilities()).thenReturn(mGnssCapabilities);
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 df2b3ef..6c769485 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -562,6 +562,11 @@
boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
return true;
}
+
+ @Override
+ boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
+ return false;
+ }
}
protected class LauncherAppsTestable extends LauncherApps {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index df5b311..0d1b352 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -86,6 +86,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
@@ -104,6 +105,7 @@
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
@@ -1121,7 +1123,7 @@
boolean checkin = false;
boolean compact = false;
- String pkg = null;
+ final ArrayList<String> pkgs = new ArrayList<>();
if (args != null) {
for (int i = 0; i < args.length; i++) {
@@ -1214,8 +1216,7 @@
return;
} else if (arg != null && !arg.startsWith("-")) {
// Anything else that doesn't start with '-' is a pkg to filter
- pkg = arg;
- break;
+ pkgs.add(arg);
}
}
}
@@ -1230,15 +1231,15 @@
if (checkin) {
mUserState.valueAt(i).checkin(idpw);
} else {
- mUserState.valueAt(i).dump(idpw, pkg, compact);
+ mUserState.valueAt(i).dump(idpw, pkgs, compact);
idpw.println();
}
}
- mAppStandby.dumpUser(idpw, userId, pkg);
+ mAppStandby.dumpUser(idpw, userId, pkgs);
idpw.decreaseIndent();
}
- if (pkg == null) {
+ if (CollectionUtils.isEmpty(pkgs)) {
pw.println();
mAppStandby.dumpState(args, pw);
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index db26d88..b7779fd 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -48,6 +48,7 @@
import android.util.SparseIntArray;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.usage.UsageStatsDatabase.StatCombiner;
@@ -753,18 +754,21 @@
});
}
- void dump(IndentingPrintWriter pw, String pkg) {
- dump(pw, pkg, false);
+ void dump(IndentingPrintWriter pw, List<String> pkgs) {
+ dump(pw, pkgs, false);
}
- void dump(IndentingPrintWriter pw, String pkg, boolean compact) {
- printLast24HrEvents(pw, !compact, pkg);
+
+ void dump(IndentingPrintWriter pw, List<String> pkgs, boolean compact) {
+ printLast24HrEvents(pw, !compact, pkgs);
for (int interval = 0; interval < mCurrentStats.length; interval++) {
pw.print("In-memory ");
pw.print(intervalToString(interval));
pw.println(" stats");
- printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkg);
+ printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkgs);
}
- mDatabase.dump(pw, compact);
+ if (CollectionUtils.isEmpty(pkgs)) {
+ mDatabase.dump(pw, compact);
+ }
}
void dumpDatabaseInfo(IndentingPrintWriter ipw) {
@@ -894,7 +898,8 @@
pw.println();
}
- void printLast24HrEvents(IndentingPrintWriter pw, boolean prettyDates, final String pkg) {
+ void printLast24HrEvents(IndentingPrintWriter pw, boolean prettyDates,
+ final List<String> pkgs) {
final long endTime = System.currentTimeMillis();
UnixCalendar yesterday = new UnixCalendar(endTime);
yesterday.addDays(-1);
@@ -914,7 +919,7 @@
}
Event event = stats.events.get(i);
- if (pkg != null && !pkg.equals(event.mPackage)) {
+ if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(event.mPackage)) {
continue;
}
accumulatedResult.add(event);
@@ -958,7 +963,7 @@
}
void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
- boolean prettyDates, boolean skipEvents, String pkg) {
+ boolean prettyDates, boolean skipEvents, List<String> pkgs) {
if (prettyDates) {
pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
@@ -974,7 +979,7 @@
final int pkgCount = pkgStats.size();
for (int i = 0; i < pkgCount; i++) {
final UsageStats usageStats = pkgStats.valueAt(i);
- if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
+ if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(usageStats.mPackageName)) {
continue;
}
pw.printPair("package", usageStats.mPackageName);
@@ -998,7 +1003,7 @@
pw.println("ChooserCounts");
pw.increaseIndent();
for (UsageStats usageStats : pkgStats.values()) {
- if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
+ if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(usageStats.mPackageName)) {
continue;
}
pw.printPair("package", usageStats.mPackageName);
@@ -1023,7 +1028,7 @@
}
pw.decreaseIndent();
- if (pkg == null) {
+ if (CollectionUtils.isEmpty(pkgs)) {
pw.println("configurations");
pw.increaseIndent();
final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations;
@@ -1060,7 +1065,7 @@
final int eventCount = events != null ? events.size() : 0;
for (int i = 0; i < eventCount; i++) {
final Event event = events.get(i);
- if (pkg != null && !pkg.equals(event.mPackage)) {
+ if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(event.mPackage)) {
continue;
}
printEvent(pw, event, prettyDates);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 795de57..9924839c 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -17,7 +17,6 @@
package android.telephony;
import android.Manifest;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -28,7 +27,6 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
-import android.net.ipsec.ike.SaProposal;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.service.carrier.CarrierService;
@@ -3499,369 +3497,6 @@
public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL =
"show_forwarded_number_bool";
- /**
- * Configs used for epdg tunnel bring up.
- *
- * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange
- * Protocol Version 2 (IKEv2)</a>
- */
- public static final class Iwlan {
- /** Prefix of all Epdg.KEY_* constants. */
- public static final String KEY_PREFIX = "iwlan.";
-
- /**
- * Time in seconds after which the child security association session is terminated if
- * rekey procedure is not successful. If not set or set to <= 0, the default value is
- * 3600 seconds.
- */
- public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT =
- KEY_PREFIX + "child_sa_rekey_hard_timer_sec_int";
-
- /**
- * Time in seconds after which the child session rekey procedure is started. If not set or
- * set to <= 0, default value is 3000 seconds.
- */
- public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT =
- KEY_PREFIX + "child_sa_rekey_soft_timer_sec_int";
-
- /** Supported DH groups for IKE negotiation.
- * Possible values are {@link #DH_GROUP_NONE}, {@link #DH_GROUP_1024_BIT_MODP},
- * {@link #DH_GROUP_2048_BIT_MODP}
- */
- public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
- KEY_PREFIX + "diffie_hellman_groups_int_array";
-
- /**
- * Time in seconds after which a dead peer detection (DPD) request is sent.
- * If not set or set to <= 0, default value is 120 seconds.
- */
- public static final String KEY_DPD_TIMER_SEC_INT = KEY_PREFIX + "dpd_timer_sec_int";
-
- /**
- * Method used to authenticate epdg server.
- * Possible values are {@link #AUTHENTICATION_METHOD_EAP_ONLY},
- * {@link #AUTHENTICATION_METHOD_CERT}
- */
- public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT =
- KEY_PREFIX + "epdg_authentication_method_int";
-
- /**
- * A priority list of ePDG addresses to be used.
- * Possible values are {@link #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN},
- * {@link #EPDG_ADDRESS_PCO}
- */
- public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
- KEY_PREFIX + "epdg_address_priority_int_array";
-
- /** Epdg static IP address or FQDN */
- public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
- KEY_PREFIX + "epdg_static_address_string";
-
- /** Epdg static IP address or FQDN for roaming */
- public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING =
- KEY_PREFIX + "epdg_static_address_roaming_string";
-
- /**
- * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of child
- * session.
- * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
- * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
- */
- public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
- KEY_PREFIX + "child_session_aes_cbc_key_size_int_array";
-
- /**
- * List of supported key sizes for AES counter (CTR) encryption mode of child session.
- * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
- * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
- */
- public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
- KEY_PREFIX + "child_encryption_aes_ctr_key_size_int_array";
-
- /**
- * List of supported encryption algorithms for child session.
- * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
- * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
- * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
- */
- public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
- KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";
-
- /** Controls if IKE message fragmentation is enabled. */
- public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL =
- KEY_PREFIX + "ike_fragmentation_enabled_bool";
-
- /**
- * Time in seconds after which the IKE session is terminated if rekey procedure is not
- * successful. If not set or set to <= 0, default value is 3600 seconds.
- */
- public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT =
- KEY_PREFIX + "ike_rekey_hard_timer_in_sec";
-
- /**
- * Time in seconds after which the IKE session rekey procedure is started. If not set or
- * set to <= 0, default value is 3000 seconds.
- */
- public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT =
- KEY_PREFIX + "ike_rekey_soft_timer_sec_int";
-
- /**
- * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of IKE
- * session.
- * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
- * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
- */
- public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
- KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
-
- /**
- * List of supported key sizes for AES counter (CTR) encryption mode of IKE session.
- * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
- * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
- */
- public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
- KEY_PREFIX + "ike_session_aes_ctr_key_size_int_array";
-
- /**
- * List of supported encryption algorithms for IKE session.
- * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
- * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
- * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
- */
- public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
- KEY_PREFIX + "supported_ike_session_encryption_algorithms_int_array";
-
- /**
- * List of supported integrity algorithms for IKE session
- * Possible values are {@link #INTEGRITY_ALGORITHM_NONE},
- * {@link #INTEGRITY_ALGORITHM_HMAC_SHA1_96}, {@link #INTEGRITY_ALGORITHM_AES_XCBC_96},
- * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_256_128},
- * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_384_192},
- * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_512_256}
- */
- public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY =
- KEY_PREFIX + "supported_integrity_algorithms_int_array";
-
- /** Maximum number of retries for tunnel establishment. */
- public static final String KEY_MAX_RETRIES_INT = KEY_PREFIX + "max_retries_int";
-
- /** Controls if nat traversal should be enabled. */
- public static final String KEY_NATT_ENABLED_BOOL = KEY_PREFIX + "natt_enabled_bool";
-
- /**
- * Time in seconds after which a NATT keep alive message is sent. If not set or set to <= 0,
- * default value is 20 seconds.
- */
- public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT =
- KEY_PREFIX + "natt_keep_alive_timer_sec_int";
-
- /** List of comma separated MCC/MNCs used to create ePDG FQDN as per 3GPP TS 23.003 */
- public static final String KEY_MCC_MNCS_STRING_ARRAY = KEY_PREFIX + "mcc_mncs_string_array";
-
- /**
- * List of supported pseudo random function algorithms for IKE session
- * Possible values are {@link #PSEUDORANDOM_FUNCTION_HMAC_SHA1},
- * {@link #PSEUDORANDOM_FUNCTION_AES128_XCBC}
- */
- public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = KEY_PREFIX +
- "supported_prf_algorithms_int_array";
-
- /**
- * Time in seconds after which IKE message is retransmitted. If not set or set to <= 0,
- * default value is 2 seconds.
- */
- public static final String KEY_RETRANSMIT_TIMER_SEC_INT =
- KEY_PREFIX + "retransmit_timer_sec_int";
-
- /** @hide */
- @IntDef({
- AUTHENTICATION_METHOD_EAP_ONLY,
- AUTHENTICATION_METHOD_CERT
- })
- public @interface AuthenticationMethodType {}
-
- /**
- * Certificate sent from the server is ignored. Only Extensible Authentication Protocol
- * (EAP) is used to authenticate the server.
- * EAP_ONLY_AUTH payload is added to IKE_AUTH request if supported.
- * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998</a>
- */
- public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0;
- /** Server is authenticated using its certificate. */
- public static final int AUTHENTICATION_METHOD_CERT = 1;
-
- /** @hide */
- @IntDef({
- EPDG_ADDRESS_STATIC,
- EPDG_ADDRESS_PLMN,
- EPDG_ADDRESS_PCO
- })
- public @interface EpdgAddressType {}
-
- /** Use static epdg address. */
- public static final int EPDG_ADDRESS_STATIC = 0;
- /** Construct the epdg address using plmn. */
- public static final int EPDG_ADDRESS_PLMN = 1;
- /**
- * Use the epdg address received in protocol configuration options (PCO) from the
- * network.
- */
- public static final int EPDG_ADDRESS_PCO = 2;
-
- /** @hide */
- @IntDef({
- KEY_LEN_UNUSED,
- KEY_LEN_AES_128,
- KEY_LEN_AES_192,
- KEY_LEN_AES_256
- })
- public @interface EncrpytionKeyLengthType {}
-
- public static final int KEY_LEN_UNUSED = SaProposal.KEY_LEN_UNUSED;
- /** AES Encryption/Ciphering Algorithm key length 128 bits. */
- public static final int KEY_LEN_AES_128 = SaProposal.KEY_LEN_AES_128;
- /** AES Encryption/Ciphering Algorithm key length 192 bits. */
- public static final int KEY_LEN_AES_192 = SaProposal.KEY_LEN_AES_192;
- /** AES Encryption/Ciphering Algorithm key length 256 bits. */
- public static final int KEY_LEN_AES_256 = SaProposal.KEY_LEN_AES_256;
-
- /** @hide */
- @IntDef({
- DH_GROUP_NONE,
- DH_GROUP_1024_BIT_MODP,
- DH_GROUP_2048_BIT_MODP
- })
- public @interface DhGroup {}
-
- /** None Diffie-Hellman Group. */
- public static final int DH_GROUP_NONE = SaProposal.DH_GROUP_NONE;
- /** 1024-bit MODP Diffie-Hellman Group. */
- public static final int DH_GROUP_1024_BIT_MODP = SaProposal.DH_GROUP_1024_BIT_MODP;
- /** 2048-bit MODP Diffie-Hellman Group. */
- public static final int DH_GROUP_2048_BIT_MODP = SaProposal.DH_GROUP_2048_BIT_MODP;
-
- /** @hide */
- @IntDef({
- ENCRYPTION_ALGORITHM_3DES,
- ENCRYPTION_ALGORITHM_AES_CBC,
- ENCRYPTION_ALGORITHM_AES_GCM_8,
- ENCRYPTION_ALGORITHM_AES_GCM_12,
- ENCRYPTION_ALGORITHM_AES_GCM_16
- })
- public @interface EncryptionAlgorithm {}
-
- /** 3DES Encryption/Ciphering Algorithm. */
- public static final int ENCRYPTION_ALGORITHM_3DES = SaProposal.ENCRYPTION_ALGORITHM_3DES;
- /** AES-CBC Encryption/Ciphering Algorithm. */
- public static final int ENCRYPTION_ALGORITHM_AES_CBC =
- SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
-
- /**
- * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 8-octet ICV
- * (truncation).
- */
- public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 =
- SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
- /**
- * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 12-octet ICV
- * (truncation).
- */
- public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 =
- SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
- /**
- * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 16-octet ICV
- * (truncation).
- */
- public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 =
- SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
-
- /** @hide */
- @IntDef({
- INTEGRITY_ALGORITHM_NONE,
- INTEGRITY_ALGORITHM_HMAC_SHA1_96,
- INTEGRITY_ALGORITHM_AES_XCBC_96,
- INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
- INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
- INTEGRITY_ALGORITHM_HMAC_SHA2_512_256
- })
- public @interface IntegrityAlgorithm {}
-
- /** None Authentication/Integrity Algorithm. */
- public static final int INTEGRITY_ALGORITHM_NONE = SaProposal.INTEGRITY_ALGORITHM_NONE;
- /** HMAC-SHA1 Authentication/Integrity Algorithm. */
- public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 =
- SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
- /** AES-XCBC-96 Authentication/Integrity Algorithm. */
- public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 =
- SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
- /** HMAC-SHA256 Authentication/Integrity Algorithm with 128-bit truncation. */
- public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 =
- SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
- /** HMAC-SHA384 Authentication/Integrity Algorithm with 192-bit truncation. */
- public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 =
- SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
- /** HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation. */
- public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 =
- SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
-
- /** @hide */
- @IntDef({
- PSEUDORANDOM_FUNCTION_HMAC_SHA1,
- PSEUDORANDOM_FUNCTION_AES128_XCBC
- })
- public @interface PseudorandomFunction {}
-
- /** HMAC-SHA1 Pseudorandom Function. */
- public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 =
- SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
- /** AES128-XCBC Pseudorandom Function. */
- public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC =
- SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
-
- private Iwlan() {}
-
- private static PersistableBundle getDefaults() {
- PersistableBundle defaults = new PersistableBundle();
- defaults.putInt(KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, 3000);
- defaults.putInt(KEY_IKE_REKEY_HARD_TIMER_SEC_INT, 3600);
- defaults.putInt(KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, 3000);
- defaults.putInt(KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, 3600);
- defaults.putInt(KEY_RETRANSMIT_TIMER_SEC_INT, 2);
- defaults.putInt(KEY_DPD_TIMER_SEC_INT, 120);
- defaults.putInt(KEY_MAX_RETRIES_INT, 3);
- defaults.putIntArray(KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY,
- new int[]{DH_GROUP_1024_BIT_MODP, DH_GROUP_2048_BIT_MODP});
- defaults.putIntArray(KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
- new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
- defaults.putIntArray(KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
- new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
- defaults.putIntArray(KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
- new int[]{INTEGRITY_ALGORITHM_AES_XCBC_96, INTEGRITY_ALGORITHM_HMAC_SHA1_96,
- INTEGRITY_ALGORITHM_HMAC_SHA2_256_128});
- defaults.putIntArray(KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY,
- new int[]{PSEUDORANDOM_FUNCTION_HMAC_SHA1, PSEUDORANDOM_FUNCTION_AES128_XCBC});
- defaults.putBoolean(KEY_NATT_ENABLED_BOOL, true);
- defaults.putInt(KEY_EPDG_AUTHENTICATION_METHOD_INT, AUTHENTICATION_METHOD_CERT);
- defaults.putString(KEY_EPDG_STATIC_ADDRESS_STRING, "");
- defaults.putString(KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, "");
- defaults.putInt(KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, 20);
- defaults.putIntArray(KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
- new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
- defaults.putIntArray(KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
- new int[]{KEY_LEN_AES_128});
- defaults.putIntArray(KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
- new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
- defaults.putIntArray(KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
- new int[]{KEY_LEN_AES_128});
- defaults.putBoolean(KEY_IKE_FRAGMENTATION_ENABLED_BOOL, false);
- defaults.putIntArray(KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, new int[]{EPDG_ADDRESS_PLMN,
- EPDG_ADDRESS_STATIC});
- defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[]{});
-
- return defaults;
- }
- }
-
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -4359,7 +3994,6 @@
sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_FORWARDED_NUMBER_BOOL, false);
sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, 0);
- sDefaults.putAll(Iwlan.getDefaults());
}
/**
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 9f26203..5c9fb4e 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -86,7 +86,6 @@
// TODO(b/146757305): should be unnecessary once
// sdk_version="module_lib_current"
"android_system_stubs_current",
- "framework_mediaprovider_annotation", // for android.annotation.CurrentTimeMillisLong
],
srcs: [
":framework-wifi-updatable-sources",
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 7d9bdba..4507cc2 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -900,12 +900,15 @@
}
/**
- * Get a unique identifier for a PasspointConfiguration object.
+ * Get a unique identifier for a PasspointConfiguration object. The identifier depends on the
+ * configuration that identify the service provider under the HomeSp subtree, and on the
+ * credential configuration under the Credential subtree.
+ * The method throws an {@link IllegalStateException} if the configuration under HomeSp subtree
+ * or the configuration under Credential subtree are not initialized.
*
* @return A unique identifier
- * @throws IllegalStateException if Credential or HomeSP nodes are not initialized
*/
- public @NonNull String getUniqueId() throws IllegalStateException {
+ public @NonNull String getUniqueId() {
if (mCredential == null || mHomeSp == null || TextUtils.isEmpty(mHomeSp.getFqdn())) {
throw new IllegalStateException("Credential or HomeSP are not initialized");
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 8f6beb1..638efb9 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -426,17 +426,11 @@
*
* @throws Exception
*/
- @Test
+ @Test (expected = IllegalStateException.class)
public void validateUniqueIdExceptionWithEmptyHomeSp() throws Exception {
PasspointConfiguration config = PasspointTestUtils.createConfig();
config.setHomeSp(null);
- boolean exceptionCaught = false;
- try {
- String uniqueId = config.getUniqueId();
- } catch (IllegalStateException e) {
- exceptionCaught = true;
- }
- assertTrue(exceptionCaught);
+ String uniqueId = config.getUniqueId();
}
/**
@@ -445,16 +439,10 @@
*
* @throws Exception
*/
- @Test
+ @Test (expected = IllegalStateException.class)
public void validateUniqueIdExceptionWithEmptyCredential() throws Exception {
PasspointConfiguration config = PasspointTestUtils.createConfig();
config.setCredential(null);
- boolean exceptionCaught = false;
- try {
- String uniqueId = config.getUniqueId();
- } catch (IllegalStateException e) {
- exceptionCaught = true;
- }
- assertTrue(exceptionCaught);
+ String uniqueId = config.getUniqueId();
}
}