Merge "Surface "neverForLocation" through public API." into sc-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index cb20f4b..9775e08 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6944,6 +6944,7 @@
method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
+ method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
}
public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -7021,6 +7022,7 @@
field public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ field public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE";
field public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; // 0x0
field public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; // 0x1
field public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
@@ -7316,6 +7318,7 @@
field public static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
field public static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
field public static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
+ field public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -41805,7 +41808,7 @@
method @NonNull public android.os.Bundle getCarrierConfigValues();
method @Deprecated public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSmsCapacityOnIcc();
+ method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public int getSmsCapacityOnIcc();
method @Deprecated public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c812e8e..f7a3514 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -450,6 +450,21 @@
public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType);
/**
+ * Returns {@code true} if the given notification channel currently has a
+ * notification associated with a foreground service. This is an AMS check
+ * because that is the source of truth for the FGS state.
+ */
+ public abstract boolean hasForegroundServiceNotification(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
+ * If the given app has any FGSs whose notifications are in the given channel,
+ * stop them.
+ */
+ public abstract void stopForegroundServicesForChannel(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
* Registers the specified {@code processObserver} to be notified of future changes to
* process state.
*/
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 60506b5..f4e214c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -12423,10 +12423,6 @@
*/
public static final int DECORATION_FULL_CONSTRAINED = 4;
- private static final boolean DEFAULT_BACKPORT_S_NOTIF_RULES = false;
- private static final int DEFAULT_FULLY_CUSTOM_DECORATION = DECORATION_MINIMAL;
- private static final int DEFAULT_DECORATED_DECORATION = DECORATION_PARTIAL;
-
/**
* Used by unit tests to force that this class returns its default values, which is required
* in cases where the ContentResolver instance is a mock.
@@ -12439,11 +12435,7 @@
* @hide
*/
public static boolean shouldBackportSNotifRules(@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_BACKPORT_S_NOTIF_RULES;
- }
- return Settings.Global.getInt(contentResolver, Settings.Global.BACKPORT_S_NOTIF_RULES,
- DEFAULT_BACKPORT_S_NOTIF_RULES ? 1 : 0) == 1;
+ return false;
}
/**
@@ -12452,14 +12444,7 @@
*/
public static int getFullyCustomViewNotifDecoration(
@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_FULLY_CUSTOM_DECORATION;
- }
- final int decoration = Settings.Global.getInt(contentResolver,
- Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
- DEFAULT_FULLY_CUSTOM_DECORATION);
- // clamp to a valid decoration value
- return Math.max(DECORATION_NONE, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+ return DECORATION_MINIMAL;
}
/**
@@ -12468,14 +12453,7 @@
*/
public static int getDecoratedCustomViewNotifDecoration(
@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_DECORATED_DECORATION;
- }
- final int decoration = Settings.Global.getInt(contentResolver,
- Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
- DEFAULT_DECORATED_DECORATION);
- // clamp to a valid decoration value (and don't allow decoration to be NONE or MINIMAL)
- return Math.max(DECORATION_PARTIAL, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+ return DECORATION_PARTIAL;
}
}
}
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 25b8eab..36097c9 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -18,6 +18,7 @@
import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
+import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
@@ -115,6 +116,29 @@
}
/**
+ * Called each time a new batch of security logs can be retrieved. This callback method will
+ * only ever be called when security logging is enabled. The logs can only be retrieved while
+ * security logging is enabled.
+ *
+ * <p>If a secondary user or profile is created, this callback won't be received until all users
+ * become affiliated again (even if security logging is enabled). It will also no longer be
+ * possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
+ *
+ * <p> This callback is only applicable if the delegated app has
+ * {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
+ * declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
+ * the receiver's manifest in order to receive this callback. The default implementation
+ * simply throws {@link UnsupportedOperationException}.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @see DevicePolicyManager#retrieveSecurityLogs
+ */
+ public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
+ throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
+ }
+
+ /**
* Intercept delegated device administrator broadcasts. Implementations should not override
* this method; implement the convenience callbacks for each action instead.
*/
@@ -132,6 +156,8 @@
long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
+ } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
+ onSecurityLogsAvailable(context, intent);
} else {
Log.w(TAG, "Unhandled broadcast: " + action);
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index cccc929..747a2de 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -290,7 +290,6 @@
/**
* Broadcast action: notify that a new batch of security logs is ready to be collected.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(explicitOnly = true)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 594b005..426159f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1905,6 +1905,20 @@
public static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
/**
+ * Grants access to {@link #setSecurityLoggingEnabled}, {@link #isSecurityLoggingEnabled},
+ * {@link #retrieveSecurityLogs}, and {@link #retrievePreRebootSecurityLogs}. Once granted the
+ * delegated app will start receiving {@link DelegatedAdminReceiver#onSecurityLogsAvailable}
+ * callback, and Device owner or Profile Owner will no longer receive the
+ * {@link DeviceAdminReceiver#onSecurityLogsAvailable} callback. There can be at most one app
+ * that has this delegation. If another app already had delegated security logging access, it
+ * will lose the delegation when a new app is delegated.
+ *
+ * <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and
+ * managed profile.
+ */
+ public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
+
+ /**
* No management for current user in-effect. This is the default.
* @hide
*/
@@ -11241,7 +11255,7 @@
public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setSecurityLoggingEnabled");
try {
- mService.setSecurityLoggingEnabled(admin, enabled);
+ mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11260,7 +11274,7 @@
public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isSecurityLoggingEnabled");
try {
- return mService.isSecurityLoggingEnabled(admin);
+ return mService.isSecurityLoggingEnabled(admin, mContext.getPackageName());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11285,10 +11299,12 @@
* @see #isAffiliatedUser
* @see DeviceAdminReceiver#onSecurityLogsAvailable
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
throwIfParentInstance("retrieveSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
@@ -11438,11 +11454,13 @@
* @see #isAffiliatedUser
* @see #retrieveSecurityLogs
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
@NonNull ComponentName admin) {
throwIfParentInstance("retrievePreRebootSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e98720c..7901791 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -386,10 +386,10 @@
List<String> getAffiliationIds(in ComponentName admin);
boolean isAffiliatedUser();
- void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
- boolean isSecurityLoggingEnabled(in ComponentName admin);
- ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
- ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
+ void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
+ boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
+ ParceledListSlice retrieveSecurityLogs(in ComponentName admin, String packageName);
+ ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin, String packageName);
long forceNetworkLogs();
long forceSecurityLogs();
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8fd0de7..a6b4b47 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -520,9 +520,7 @@
return;
}
int layoutId = rvToApply.getLayoutId();
- // If our stale view has been prepared to match active, and the new
- // layout matches, try recycling it
- if (content == null && layoutId == mLayoutId) {
+ if (rvToApply.canRecycleView(mView)) {
try {
rvToApply.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
mColorResources);
diff --git a/core/java/android/hardware/biometrics/ComponentInfoInternal.java b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
index fa34e0b..3b61a56 100644
--- a/core/java/android/hardware/biometrics/ComponentInfoInternal.java
+++ b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
@@ -27,11 +27,11 @@
*/
public class ComponentInfoInternal implements Parcelable {
- public final String componentId;
- public final String hardwareVersion;
- public final String firmwareVersion;
- public final String serialNumber;
- public final String softwareVersion;
+ @NonNull public final String componentId;
+ @NonNull public final String hardwareVersion;
+ @NonNull public final String firmwareVersion;
+ @NonNull public final String serialNumber;
+ @NonNull public final String softwareVersion;
/**
* Constructs a {@link ComponentInfoInternal} from another instance.
@@ -45,8 +45,9 @@
/**
* @hide
*/
- public ComponentInfoInternal(String componentId, String hardwareVersion,
- String firmwareVersion, String serialNumber, String softwareVersion) {
+ public ComponentInfoInternal(@NonNull String componentId, @NonNull String hardwareVersion,
+ @NonNull String firmwareVersion, @NonNull String serialNumber,
+ @NonNull String softwareVersion) {
this.componentId = componentId;
this.hardwareVersion = hardwareVersion;
this.firmwareVersion = firmwareVersion;
diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
index eda0ded..17b2abf 100644
--- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
@@ -34,7 +34,7 @@
public final int sensorId;
@SensorProperties.Strength public final int sensorStrength;
public final int maxEnrollmentsPerUser;
- public final List<ComponentInfoInternal> componentInfo;
+ @NonNull public final List<ComponentInfoInternal> componentInfo;
public final boolean resetLockoutRequiresHardwareAuthToken;
public final boolean resetLockoutRequiresChallenge;
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a3c6f2f..b7b1a14 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2030,7 +2030,9 @@
// Tell listeners that the cameras and torch modes are unavailable and schedule a
// reconnection to camera service. When camera service is reconnected, the camera
// and torch statuses will be updated.
- for (int i = 0; i < mDeviceStatus.size(); i++) {
+ // Iterate from the end to the beginning befcause onStatusChangedLocked removes
+ // entries from the ArrayMap.
+ for (int i = mDeviceStatus.size() - 1; i >= 0; i--) {
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
}
diff --git a/core/java/android/hardware/face/FaceSensorProperties.java b/core/java/android/hardware/face/FaceSensorProperties.java
index 6ddea50..f613127 100644
--- a/core/java/android/hardware/face/FaceSensorProperties.java
+++ b/core/java/android/hardware/face/FaceSensorProperties.java
@@ -17,6 +17,7 @@
package android.hardware.face;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
@@ -74,7 +75,8 @@
* @hide
*/
public FaceSensorProperties(int sensorId, int sensorStrength,
- List<ComponentInfo> componentInfo, @FaceSensorProperties.SensorType int sensorType) {
+ @NonNull List<ComponentInfo> componentInfo,
+ @FaceSensorProperties.SensorType int sensorType) {
super(sensorId, sensorStrength, componentInfo);
mSensorType = sensorType;
}
diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
index 50ea60a2..44dffb2 100644
--- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
+++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
@@ -16,6 +16,7 @@
package android.hardware.face;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
import android.hardware.biometrics.SensorPropertiesInternal;
@@ -48,7 +49,7 @@
* Initializes SensorProperties with specified values
*/
public FaceSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength,
- int maxEnrollmentsPerUser, List<ComponentInfoInternal> componentInfo,
+ int maxEnrollmentsPerUser, @NonNull List<ComponentInfoInternal> componentInfo,
@FaceSensorProperties.SensorType int sensorType, boolean supportsFaceDetection,
boolean supportsSelfIllumination, boolean resetLockoutRequiresChallenge) {
// resetLockout is managed by the HAL and requires a HardwareAuthToken for all face
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
index a338575..71b705f 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
@@ -17,6 +17,7 @@
package android.hardware.fingerprint;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
@@ -94,7 +95,7 @@
* @hide
*/
public FingerprintSensorProperties(int sensorId, int sensorStrength,
- List<ComponentInfo> componentInfo, @SensorType int sensorType) {
+ @NonNull List<ComponentInfo> componentInfo, @SensorType int sensorType) {
super(sensorId, sensorStrength, componentInfo);
mSensorType = sensorType;
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index 1b13370..58f6e62 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -62,7 +62,7 @@
public FingerprintSensorPropertiesInternal(int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY,
int sensorRadius) {
@@ -83,7 +83,7 @@
*/
public FingerprintSensorPropertiesInternal(int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken) {
// TODO(b/179175438): Value should be provided from the HAL
@@ -99,7 +99,7 @@
// TODO(b/179175438): Remove this constructor once all HALs move to AIDL.
public FingerprintSensorPropertiesInternal(@NonNull Context context, int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken) {
super(sensorId, strength, maxEnrollmentsPerUser, componentInfo,
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index eaa8bd4..f69a7d7 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -60,8 +60,8 @@
private static final String TAG = "ContextHubManager";
/**
- * An extra containing an int from {@link AuthorizationState} describing the client's
- * authorization state.
+ * An extra containing one of the {@code AUTHORIZATION_*} constants such as
+ * {@link #AUTHORIZATION_GRANTED} describing the client's authorization state.
*/
public static final String EXTRA_CLIENT_AUTHORIZATION_STATE =
"android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f1c80af..71ffa92 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15795,48 +15795,6 @@
public static final String SHOW_NEW_NOTIF_DISMISS = "show_new_notif_dismiss";
/**
- * Whether to enforce the new notification rules (aka rules that are only applied to
- * notifications from apps targeting S) on all notifications.
- * - Collapsed custom view notifications will get the new 76dp height instead of 106dp.
- * - Custom view notifications will be partially decorated.
- * - Large icons will be given an aspect ratio of up to 16:9.
- *
- * Values are:
- * 0: Disabled (Only apps targeting S will receive the new rules)
- * 1: Enabled (All apps will receive the new rules)
- * @hide
- */
- public static final String BACKPORT_S_NOTIF_RULES = "backport_s_notif_rules";
-
- /**
- * The decoration to put on fully custom views that target S.
- *
- * <p>Values are:
- * <br>0: DECORATION_NONE: no decorations.
- * <br>1: DECORATION_MINIMAL: most minimal template; just the icon and the expander.
- * <br>2: DECORATION_PARTIAL: basic template without the top line.
- * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
- * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line; 28dp of height.
- * <p>See {@link android.app.Notification.DevFlags} for more details.
- * @hide
- */
- public static final String FULLY_CUSTOM_VIEW_NOTIF_DECORATION =
- "fully_custom_view_notif_decoration";
-
- /**
- * The decoration to put on decorated custom views that target S.
- *
- * <p>Values are:
- * <br>2: DECORATION_PARTIAL: basic template without the top line.
- * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
- * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line; 28dp of height.
- * <p>See {@link android.app.Notification.DevFlags} for more details.
- * @hide
- */
- public static final String DECORATED_CUSTOM_VIEW_NOTIF_DECORATION =
- "decorated_custom_view_notif_decoration";
-
- /**
* Block untrusted touches mode.
*
* Can be one of:
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index f61ab29..d3eaeae 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -30,11 +30,11 @@
*/
public final class Slog {
- @GuardedBy("sMessageBuilder")
- private static final StringBuilder sMessageBuilder = new StringBuilder();
+ @GuardedBy("Slog.class")
+ private static StringBuilder sMessageBuilder;
- @GuardedBy("sMessageBuilder")
- private static final Formatter sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+ @GuardedBy("Slog.class")
+ private static Formatter sFormatter;
private Slog() {
}
@@ -226,7 +226,12 @@
}
private static String getMessage(String format, @Nullable Object... args) {
- synchronized (sMessageBuilder) {
+ synchronized (Slog.class) {
+ if (sMessageBuilder == null) {
+ // Lazy load so they're not created if not used by the process
+ sMessageBuilder = new StringBuilder();
+ sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+ }
sFormatter.format(format, args);
String message = sMessageBuilder.toString();
sMessageBuilder.setLength(0);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 35d5d8e..7455b8b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,7 @@
package android.view;
import static android.content.res.Resources.ID_NULL;
+import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
@@ -26747,6 +26748,21 @@
* {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
* in DragEvent. The method uses these to determine what is happening in the drag and drop
* operation.
+ * </p>
+ * <p>
+ * The default implementation returns false, except if an {@link OnReceiveContentListener}
+ * is {@link #setOnReceiveContentListener set} for this view. If an
+ * {@link OnReceiveContentListener} is set, the default implementation...
+ * <ul>
+ * <li>returns true for an
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
+ * <li>calls {@link #performReceiveContent} for an
+ * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
+ * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
+ * the listener consumed some or all of the content
+ * </ul>
+ * </p>
+ *
* @param event The {@link android.view.DragEvent} sent by the system.
* The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
* in DragEvent, indicating the type of drag event represented by this object.
@@ -26766,6 +26782,24 @@
* </p>
*/
public boolean onDragEvent(DragEvent event) {
+ if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
+ return false;
+ }
+ // Accept drag events by default if there's an OnReceiveContentListener set.
+ if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
+ return true;
+ }
+ if (event.getAction() == DragEvent.ACTION_DROP) {
+ final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
+ if (permissions != null) {
+ permissions.takeTransient();
+ }
+ final ContentInfo payload = new ContentInfo.Builder(
+ event.getClipData(), SOURCE_DRAG_AND_DROP).build();
+ ContentInfo remainingPayload = performReceiveContent(payload);
+ // Return true unless none of the payload was consumed.
+ return remainingPayload != payload;
+ }
return false;
}
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 5f55887..58dfc0d 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -117,12 +117,12 @@
/**
* The natural frequency of the stretch spring.
*/
- private static final double NATURAL_FREQUENCY = 14.4222;
+ private static final double NATURAL_FREQUENCY = 17.55;
/**
* The damping ratio of the stretch spring.
*/
- private static final double DAMPING_RATIO = 0.875;
+ private static final double DAMPING_RATIO = 0.92;
/** @hide */
@IntDef({TYPE_GLOW, TYPE_STRETCH})
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2b73923..319e788 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2196,7 +2196,7 @@
int recycledViewIndex = findViewIndexToRecycle(target, rvToApply);
if (recycledViewIndex >= 0) {
View child = target.getChildAt(recycledViewIndex);
- if (getViewLayoutId(child) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(child)) {
if (nextChild < recycledViewIndex) {
target.removeViews(nextChild, recycledViewIndex - nextChild);
}
@@ -2254,7 +2254,7 @@
// application are placed before.
ViewTree recycled = target.mChildren.get(recycledViewIndex);
// We can only recycle the view if the layout id is the same.
- if (getViewLayoutId(recycled.mRoot) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(recycled.mRoot)) {
if (recycledViewIndex > nextChild) {
target.removeChildren(nextChild, recycledViewIndex - nextChild);
}
@@ -3726,7 +3726,8 @@
*
* The {@code stableId} will be used to identify a potential view to recycled when the remote
* view is inflated. Views can be re-used if inserted in the same order, potentially with
- * some views appearing / disappearing.
+ * some views appearing / disappearing. To be recycled the view must not change the layout
+ * used to inflate it or its view id (see {@link RemoteViews#setViewId}).
*
* Note: if a view is re-used, all the actions will be re-applied on it. However, its properties
* are not reset, so what was applied in previous round will have an effect. As a view may be
@@ -5116,6 +5117,7 @@
View v = inflater.inflate(rv.getLayoutId(), parent, false);
if (mViewId != View.NO_ID) {
v.setId(mViewId);
+ v.setTagInternal(R.id.remote_views_override_id, mViewId);
}
v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
return v;
@@ -5335,6 +5337,24 @@
reapply(context, v, handler, size, colorResources, true);
}
+ /** @hide */
+ public boolean canRecycleView(@Nullable View v) {
+ if (v == null) {
+ return false;
+ }
+ Integer previousLayoutId = (Integer) v.getTag(R.id.widget_frame);
+ if (previousLayoutId == null) {
+ return false;
+ }
+ Integer overrideIdTag = (Integer) v.getTag(R.id.remote_views_override_id);
+ int overrideId = overrideIdTag == null ? View.NO_ID : overrideIdTag;
+ // If mViewId is View.NO_ID, we only recycle if overrideId is also View.NO_ID.
+ // Otherwise, it might be that, on a previous iteration, the view's ID was set to
+ // something else, and it should now be reset to the ID defined in the XML layout file,
+ // whatever it is.
+ return previousLayoutId == getLayoutId() && mViewId == overrideId;
+ }
+
// Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
// should set it to false.
private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
@@ -5347,7 +5367,7 @@
// (orientation or size), we throw an exception, since the layouts may be completely
// unrelated.
if (hasMultipleLayouts()) {
- if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+ if (!rvToApply.canRecycleView(v)) {
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
" that does not share the same root layout id.");
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index dba7fa9..940a3c9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13071,11 +13071,37 @@
return getLayout().getOffsetForHorizontal(line, x);
}
+ /**
+ * Handles drag events sent by the system following a call to
+ * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
+ * startDragAndDrop()}.
+ *
+ * <p>If this text view is not editable, delegates to the default {@link View#onDragEvent}
+ * implementation.
+ *
+ * <p>If this text view is editable, accepts all drag actions (returns true for an
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event and all
+ * subsequent drag events). While the drag is in progress, updates the cursor position
+ * to follow the touch location. Once a drop event is received, handles content insertion
+ * via {@link #performReceiveContent}.
+ *
+ * @param event The {@link android.view.DragEvent} sent by the system.
+ * The {@link android.view.DragEvent#getAction()} method returns an action type constant
+ * defined in DragEvent, indicating the type of drag event represented by this object.
+ * @return Returns true if this text view is editable and delegates to super otherwise.
+ * See {@link View#onDragEvent}.
+ */
@Override
public boolean onDragEvent(DragEvent event) {
+ if (mEditor == null || !mEditor.hasInsertionController()) {
+ // If this TextView is not editable, defer to the default View implementation. This
+ // will check for the presence of an OnReceiveContentListener and accept/reject
+ // drag events depending on whether the listener is/isn't set.
+ return super.onDragEvent(event);
+ }
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- return mEditor != null && mEditor.hasInsertionController();
+ return true;
case DragEvent.ACTION_DRAG_ENTERED:
TextView.this.requestFocus();
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 7ade05c..e6c911e 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -3,6 +3,9 @@
per-file *Chooser* = file:/packages/SystemUI/OWNERS
per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
-per-file IVoice* = file:/core/java/android/service/voice/OWNERS
-per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
+
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 6f377b9..93cde3d 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -353,8 +353,8 @@
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mLeftEdge = new EdgeEffect(context);
- mRightEdge = new EdgeEffect(context);
+ mLeftEdge = new EdgeEffect(context, attrs);
+ mRightEdge = new EdgeEffect(context, attrs);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
@@ -387,6 +387,28 @@
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ // Both left and right edge have the same edge effect type
+ return mLeftEdge.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mLeftEdge.setType(type);
+ mRightEdge.setType(type);
+ invalidate();
+ }
+
+ /**
* Set a PagerAdapter that will supply views for this pager as needed.
*
* @param adapter Adapter to use
@@ -1891,7 +1913,7 @@
}
if (mIsBeingDragged) {
// Scroll to follow the motion event
- if (performDrag(x)) {
+ if (performDrag(x, y)) {
postInvalidateOnAnimation();
}
}
@@ -1918,6 +1940,17 @@
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
setScrollState(SCROLL_STATE_DRAGGING);
+ } else if (mLeftEdge.getDistance() != 0
+ || mRightEdge.getDistance() != 0) {
+ // Caught the edge glow animation
+ mIsBeingDragged = true;
+ setScrollState(SCROLL_STATE_DRAGGING);
+ if (mLeftEdge.getDistance() != 0) {
+ mLeftEdge.onPullDistance(0f, 1 - mLastMotionY / getHeight());
+ }
+ if (mRightEdge.getDistance() != 0) {
+ mRightEdge.onPullDistance(0f, mLastMotionY / getHeight());
+ }
} else {
completeScroll(false);
mIsBeingDragged = false;
@@ -2009,7 +2042,7 @@
// Scroll to follow the motion event
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(activePointerIndex);
- needsInvalidate |= performDrag(x);
+ needsInvalidate |= performDrag(x, ev.getY(activePointerIndex));
}
break;
case MotionEvent.ACTION_UP:
@@ -2080,12 +2113,43 @@
}
}
- private boolean performDrag(float x) {
+ /**
+ * If either of the horizontal edge glows are currently active, this consumes part or all of
+ * deltaX on the edge glow.
+ *
+ * @param deltaX The pointer motion, in pixels, in the horizontal direction, positive
+ * for moving down and negative for moving up.
+ * @param y The vertical position of the pointer.
+ * @return The amount of <code>deltaX</code> that has been consumed by the
+ * edge glow.
+ */
+ private float releaseHorizontalGlow(float deltaX, float y) {
+ // First allow releasing existing overscroll effect:
+ float consumed = 0;
+ float displacement = y / getHeight();
+ float pullDistance = (float) deltaX / getWidth();
+ if (mLeftEdge.getDistance() != 0) {
+ consumed = -mLeftEdge.onPullDistance(-pullDistance, 1 - displacement);
+ } else if (mRightEdge.getDistance() != 0) {
+ consumed = mRightEdge.onPullDistance(pullDistance, displacement);
+ }
+ return consumed * getWidth();
+ }
+
+ private boolean performDrag(float x, float y) {
boolean needsInvalidate = false;
+ final float dX = mLastMotionX - x;
final int width = getPaddedWidth();
- final float deltaX = mLastMotionX - x;
mLastMotionX = x;
+ final float releaseConsumed = releaseHorizontalGlow(dX, y);
+ final float deltaX = dX - releaseConsumed;
+ if (releaseConsumed != 0) {
+ needsInvalidate = true;
+ }
+ if (Math.abs(deltaX) < 0.0001f) { // ignore rounding errors from releaseHorizontalGlow()
+ return needsInvalidate;
+ }
final EdgeEffect startEdge;
final EdgeEffect endEdge;
@@ -2128,14 +2192,14 @@
if (scrollStart < startBound) {
if (startAbsolute) {
final float over = startBound - scrollStart;
- startEdge.onPull(Math.abs(over) / width);
+ startEdge.onPullDistance(over / width, 1 - y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = startBound;
} else if (scrollStart > endBound) {
if (endAbsolute) {
final float over = scrollStart - endBound;
- endEdge.onPull(Math.abs(over) / width);
+ endEdge.onPullDistance(over / width, y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = endBound;
@@ -2228,7 +2292,9 @@
*/
private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) {
int targetPage;
- if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
+ if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity
+ && mLeftEdge.getDistance() == 0 // don't fling while stretched
+ && mRightEdge.getDistance() == 0) {
targetPage = currentPage - (velocity < 0 ? mLeftIncr : 0);
} else {
final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d88f259..45fd96a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4824,7 +4824,7 @@
TODO(159952358): STOPSHIP: This must be updated to the new "internal" protectionLevel
-->
<permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="internal|privileged" />
<!-- @SystemApi @hide Must be required by the domain verification agent's intent
BroadcastReceiver, to ensure that only the system can interact with it.
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 7bc4663..c3b35c8 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -252,5 +252,8 @@
<item type="id" name="remote_views_next_child" />
<!-- View tag associating a view with its stable id for potential recycling. -->
- <item type="id" name = "remote_views_stable_id" />
+ <item type="id" name="remote_views_stable_id" />
+
+ <!-- View tag associating a view with its overridden id, to ensure valid recycling only. -->
+ <item type="id" name="remote_views_override_id" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 541c18c..cdeb71c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4324,8 +4324,11 @@
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed" />
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default" />
+ <!-- Ids for RemoteViews -->
<java-symbol type="id" name="remote_views_next_child" />
<java-symbol type="id" name="remote_views_stable_id" />
+ <java-symbol type="id" name="remote_views_override_id" />
+
<!-- View and control prompt -->
<java-symbol type="drawable" name="ic_accessibility_24dp" />
<java-symbol type="string" name="view_and_control_notification_title" />
diff --git a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
index 1e6bdc6..fcb1e71 100644
--- a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
+++ b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="25"/>
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26"/>
<application>
<activity android:name=".TestActivity"
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 4fe7d70..13d529c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -124,6 +124,7 @@
sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0);
+ executeCmd("cmd deviceidle whitelist +" + TEST_PKG);
final ArrayMap<String, String> desiredConstants = new ArrayMap<>();
desiredConstants.put(KEY_TRACK_CPU_TIMES_BY_PROC_STATE, Boolean.toString(true));
@@ -134,6 +135,7 @@
@AfterClass
public static void tearDownOnce() throws Exception {
+ executeCmd("cmd deviceidle whitelist -" + TEST_PKG);
if (sBatteryStatsConstsUpdated) {
Settings.Global.putString(sContext.getContentResolver(),
Settings.Global.BATTERY_STATS_CONSTANTS, sOriginalBatteryStatsConsts);
@@ -382,7 +384,7 @@
}
@Test
- @SkipPresubmit("b/180015146 flakey")
+ @SkipPresubmit("b/183225190 flaky")
public void testCpuFreqTimes_stateFgService() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -515,7 +517,6 @@
}
@Test
- @SkipPresubmit("b/180015146")
public void testCpuFreqTimes_trackingDisabled() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -625,7 +626,7 @@
splitter.setString(settingsDump);
String next;
while (splitter.hasNext()) {
- next = splitter.next();
+ next = splitter.next().trim();
if (next.startsWith(key)) {
return next.split("=")[1];
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9b124ce..1924e5f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -493,6 +493,8 @@
<!-- Permission required for hotword detection service CTS tests -->
<permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
<permission name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index b57f7af..94d5c22 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -26,8 +26,8 @@
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
import android.graphics.animation.RenderNodeAnimator;
-import android.util.ArraySet;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
@@ -41,8 +41,8 @@
private static final int ENTER_ANIM_DURATION = 450;
private static final int EXIT_ANIM_DURATION = 300;
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
- private static final TimeInterpolator PATH_INTERPOLATOR =
- new PathInterpolator(.2f, 0, 0, 1f);
+ private static final Interpolator FAST_OUT_LINEAR_IN =
+ new PathInterpolator(0.4f, 0f, 1f, 1f);
private Consumer<RippleAnimationSession> mOnSessionEnd;
private final AnimationProperties<Float, Paint> mProperties;
private AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>> mCanvasProperties;
@@ -59,7 +59,7 @@
mSparkle.addUpdateListener(anim -> {
final long now = AnimationUtils.currentAnimationTimeMillis();
final long elapsed = now - mStartTime - ENTER_ANIM_DURATION;
- final float phase = (float) elapsed / 30000f;
+ final float phase = (float) elapsed / 800;
mProperties.getShader().setNoisePhase(phase);
notifyUpdate();
});
@@ -174,7 +174,7 @@
private void startAnimation(Animator expand) {
expand.setDuration(ENTER_ANIM_DURATION);
expand.addListener(new AnimatorListener(this));
- expand.setInterpolator(LINEAR_INTERPOLATOR);
+ expand.setInterpolator(FAST_OUT_LINEAR_IN);
expand.start();
if (!mSparkle.isRunning()) {
mSparkle.start();
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fb2b9b3..d5711c8 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -914,7 +914,7 @@
shader.setColor(color);
shader.setOrigin(w / 2, y / 2);
shader.setTouch(x, y);
- shader.setResolution(w, h);
+ shader.setResolution(w, h, mState.mDensity);
shader.setNoisePhase(0);
shader.setRadius(radius);
shader.setProgress(.0f);
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index ea9ba32..5dd250c 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -20,13 +20,15 @@
import android.graphics.Color;
import android.graphics.RuntimeShader;
import android.graphics.Shader;
+import android.util.DisplayMetrics;
final class RippleShader extends RuntimeShader {
private static final String SHADER_UNIFORMS = "uniform vec2 in_origin;\n"
+ "uniform vec2 in_touch;\n"
+ "uniform float in_progress;\n"
+ "uniform float in_maxRadius;\n"
- + "uniform vec2 in_resolution;\n"
+ + "uniform vec2 in_resolutionScale;\n"
+ + "uniform vec2 in_noiseScale;\n"
+ "uniform float in_hasMask;\n"
+ "uniform float in_noisePhase;\n"
+ "uniform vec4 in_color;\n"
@@ -40,18 +42,15 @@
+ "}"
+ "const float PI = 3.1415926535897932384626;\n"
+ "\n"
- + "float threshold(float v, float l, float h) {\n"
- + " return step(l, v) * (1.0 - step(h, v));\n"
- + "}\n"
- + "\n"
+ "float sparkles(vec2 uv, float t) {\n"
+ " float n = triangleNoise(uv);\n"
+ " float s = 0.0;\n"
+ " for (float i = 0; i < 4; i += 1) {\n"
- + " float l = i * 0.25;\n"
- + " float h = l + 0.005;\n"
- + " float o = abs(sin(0.1 * PI * (t + i)));\n"
- + " s += threshold(n + o, l, h);\n"
+ + " float l = i * 0.01;\n"
+ + " float h = l + 0.1;\n"
+ + " float o = smoothstep(n - l, h, n);\n"
+ + " o *= abs(sin(PI * o * (t + 0.55 * i)));\n"
+ + " s += o;\n"
+ " }\n"
+ " return saturate(s);\n"
+ "}\n"
@@ -83,7 +82,9 @@
+ " vec2 center = mix(in_touch, in_origin, fadeIn);\n"
+ " float ring = getRingMask(p, center, in_maxRadius, fadeIn);\n"
+ " float alpha = min(fadeIn, 1. - fadeOutNoise);\n"
- + " float sparkle = sparkles(p, in_noisePhase) * ring * alpha;\n"
+ + " vec2 uv = p * in_resolutionScale;\n"
+ + " vec2 densityUv = uv - mod(uv, in_noiseScale);\n"
+ + " float sparkle = sparkles(densityUv, in_noisePhase) * ring * alpha;\n"
+ " float fade = min(fadeIn, 1. - fadeOutRipple);\n"
+ " vec4 circle = in_color * (softCircle(p, center, in_maxRadius "
+ " * fadeIn, 0.2) * fade);\n"
@@ -135,7 +136,10 @@
color.green(), color.blue(), color.alpha()});
}
- public void setResolution(float w, float h) {
- setUniform("in_resolution", w, h);
+ public void setResolution(float w, float h, int density) {
+ float noiseScale = 0.8f;
+ float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 0.5f * noiseScale;
+ setUniform("in_resolutionScale", new float[] {1f / w, 1f / h});
+ setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h});
}
}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index d7112d6..0d61399 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -612,7 +612,9 @@
}
/**
- * Sets the context the record belongs to.
+ * Sets the context the record belongs to. This context will be used to pull information,
+ * such as attribution tags, which will be associated with the AudioRecord. However, the
+ * context itself will not be retained by the AudioRecord.
* @param context a non-null {@link Context} instance
* @return the same Builder instance.
*/
diff --git a/packages/SettingsLib/TwoTargetPreference/Android.bp b/packages/SettingsLib/TwoTargetPreference/Android.bp
index f2e79b9..078e8c3 100644
--- a/packages/SettingsLib/TwoTargetPreference/Android.bp
+++ b/packages/SettingsLib/TwoTargetPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibTwoTargetPreference",
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c520568..068efac 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -139,7 +139,6 @@
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
- Settings.Global.BACKPORT_S_NOTIF_RULES,
Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
Settings.Global.BROADCAST_BG_CONSTANTS,
@@ -217,7 +216,6 @@
Settings.Global.DEBUG_APP,
Settings.Global.DEBUG_VIEW_ATTRIBUTES,
Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
- Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
Settings.Global.DEFAULT_DNS_SERVER,
Settings.Global.DEFAULT_INSTALL_LOCATION,
Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
@@ -289,7 +287,6 @@
Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
Settings.Global.FSTRIM_MANDATORY_INTERVAL,
Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED,
- Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Settings.Global.GLOBAL_HTTP_PROXY_HOST,
Settings.Global.GLOBAL_HTTP_PROXY_PAC,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8d8e442..b86ae6d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -435,6 +435,9 @@
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 338aa3a..3904201 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -336,7 +336,7 @@
</receiver>
<activity android:name=".screenshot.LongScreenshotActivity"
- android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:theme="@style/LongScreenshotActivity"
android:process=":screenshot"
android:exported="false"
android:finishOnTaskLaunch="true" />
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 7ba28a8..19bcf95 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -24,51 +24,27 @@
<Button
android:id="@+id/save"
+ style="@android:style/Widget.DeviceDefault.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save"
- app:layout_constraintEnd_toStartOf="@id/cancel"
- app:layout_constraintHorizontal_chainStyle="packed"
+ android:layout_marginLeft="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
+ app:layout_constraintBottom_toTopOf="@id/preview" />
- <Button
- android:id="@+id/cancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/cancel"
- app:layout_constraintEnd_toStartOf="@id/edit"
- app:layout_constraintStart_toEndOf="@id/save"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <Button
- android:id="@+id/edit"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/screenshot_edit_label"
- app:layout_constraintEnd_toStartOf="@id/share"
- app:layout_constraintStart_toEndOf="@id/cancel"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <Button
+ <ImageButton
android:id="@+id/share"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@*android:string/share"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:tint="?android:textColorPrimary"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="6dp"
+ android:src="@drawable/ic_screenshot_share"
+ android:layout_marginRight="8dp"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toEndOf="@+id/edit"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- app:layout_constraintGuide_percent="0.1" />
+ app:layout_constraintBottom_toTopOf="@id/preview" />
<ImageView
android:id="@+id/preview"
@@ -78,7 +54,7 @@
android:layout_marginHorizontal="48dp"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toBottomOf="@id/save"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -93,7 +69,7 @@
android:layout_marginBottom="42dp"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toTopOf="@id/preview"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -110,7 +86,7 @@
android:layout_width="200dp"
android:layout_height="200dp"
android:elevation="2dp"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toTopOf="@id/preview"
app:layout_constraintLeft_toLeftOf="parent"
app:handleThickness="@dimen/screenshot_crop_handle_thickness"
app:handleColor="@*android:color/accent_device_default"
@@ -119,5 +95,24 @@
app:borderColor="#fff"
/>
+ <Button
+ android:id="@+id/edit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ style="@android:style/Widget.DeviceDefault.Button.Colored"
+ android:backgroundTint="?android:colorBackground"
+ android:drawableStart="@drawable/ic_screenshot_edit"
+ android:drawableTint="?android:textColorPrimary"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
+ android:paddingVertical="8dp"
+ android:textColor="?android:textColorPrimary"
+ android:text="@string/screenshot_edit_label"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ />
+
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff9ea01..4a661dc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -610,6 +610,11 @@
<item name="android:windowCloseOnTouchOutside">true</item>
</style>
+ <!-- Screenshots -->
+ <style name="LongScreenshotActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
<!-- Privacy dialog -->
<style name="PrivacyDialog" parent="ScreenRecord">
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b9f9b1bc..98b3fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -321,6 +321,7 @@
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
checkArgument(mSensorProps != null);
+ mStatusBar.setSensorRect(getSensorLocation());
mCoreLayoutParams = new WindowManager.LayoutParams(
// TODO(b/152419866): Use the UDFPS window type when it becomes available.
@@ -367,7 +368,8 @@
*/
public RectF getSensorLocation() {
// This is currently used to calculate the amount of space available for notifications
- // on lockscreen. Keyguard is only shown in portrait mode for now, so this will need to
+ // on lockscreen and for the udfps light reveal animation on keyguard.
+ // Keyguard is only shown in portrait mode for now, so this will need to
// be updated if that ever changes.
return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 31cdada..6a004c2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -76,7 +76,6 @@
private ImageView mPreview;
private View mSave;
- private View mCancel;
private View mEdit;
private View mShare;
private CropView mCropView;
@@ -117,7 +116,6 @@
mPreview = requireViewById(R.id.preview);
mSave = requireViewById(R.id.save);
- mCancel = requireViewById(R.id.cancel);
mEdit = requireViewById(R.id.edit);
mShare = requireViewById(R.id.share);
mCropView = requireViewById(R.id.crop_view);
@@ -125,7 +123,6 @@
mCropView.setCropInteractionListener(mMagnifierView);
mSave.setOnClickListener(this::onClicked);
- mCancel.setOnClickListener(this::onClicked);
mEdit.setOnClickListener(this::onClicked);
mShare.setOnClickListener(this::onClicked);
@@ -313,7 +310,6 @@
private void setButtonsEnabled(boolean enabled) {
mSave.setEnabled(enabled);
- mCancel.setEnabled(enabled);
mEdit.setEnabled(enabled);
mShare.setEnabled(enabled);
}
@@ -350,8 +346,6 @@
setButtonsEnabled(false);
if (id == R.id.save) {
startExport(PendingAction.SAVE);
- } else if (id == R.id.cancel) {
- finishAndRemoveTask();
} else if (id == R.id.edit) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
startExport(PendingAction.EDIT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index c1feaca..563470d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -82,6 +82,31 @@
}
}
+class CircleReveal(
+ /** X-value of the circle center of the reveal. */
+ val centerX: Float,
+ /** Y-value of the circle center of the reveal. */
+ val centerY: Float,
+ /** Radius of initial state of circle reveal */
+ val startRadius: Float,
+ /** Radius of end state of circle reveal */
+ val endRadius: Float
+) : LightRevealEffect {
+ override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
+ val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(amount)
+ val fadeAmount =
+ LightRevealEffect.getPercentPastThreshold(interpolatedAmount, 0.75f)
+ val radius = startRadius + ((endRadius - startRadius) * interpolatedAmount)
+ scrim.revealGradientEndColorAlpha = 1f - fadeAmount
+ scrim.setRevealGradientBounds(
+ centerX - radius /* left */,
+ centerY - radius /* top */,
+ centerX + radius /* right */,
+ centerY + radius /* bottom */
+ )
+ }
+}
+
class PowerButtonReveal(
/** Approximate Y-value of the center of the power button on the physical device. */
val powerButtonY: Float
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e119907..3daa2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -132,6 +132,7 @@
mHiddenShelfIconSize = res.getDimensionPixelOffset(R.dimen.hidden_shelf_icon_size);
mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
+ mShelfIcons.setInNotificationIconShelf(true);
if (!mShowNotificationShelf) {
setVisibility(GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 6b144c6..25de551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -152,6 +152,7 @@
private boolean mDozing;
private boolean mOnLockScreen;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+ private boolean mInNotificationIconShelf;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1;
@@ -702,6 +703,10 @@
mLockScreenMode = lockScreenMode;
}
+ public void setInNotificationIconShelf(boolean inShelf) {
+ mInNotificationIconShelf = inShelf;
+ }
+
public class IconState extends ViewState {
public static final int NO_VALUE = NotificationIconContainer.NO_VALUE;
public float iconAppearAmount = 1.0f;
@@ -813,7 +818,7 @@
}
}
icon.setVisibleState(visibleState, animationsAllowed);
- icon.setIconColor(mThemedTextColorPrimary,
+ icon.setIconColor(mInNotificationIconShelf ? mThemedTextColorPrimary : iconColor,
needsCannedAnimation && animationsAllowed);
if (animate) {
animateTo(icon, animationProperties);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 427df5e..0e1fe22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,6 +22,7 @@
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -46,6 +47,7 @@
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -74,6 +76,7 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RectF;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -179,6 +182,7 @@
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
+import com.android.systemui.statusbar.CircleReveal;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.FeatureFlags;
@@ -382,6 +386,8 @@
private ChargingRippleView mChargingRipple;
private WiredChargingRippleController mChargingRippleAnimationController;
private PowerButtonReveal mPowerButtonReveal;
+ private CircleReveal mCircleReveal;
+ private ValueAnimator mCircleRevealAnimator = ValueAnimator.ofFloat(0f, 1f);
private final Object mQueueLock = new Object();
@@ -1206,7 +1212,9 @@
mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
mChargingRippleAnimationController.setViewHost(mNotificationShadeWindowView);
- if (mFeatureFlags.useNewLockscreenAnimations() && mDozeParameters.getAlwaysOn()) {
+
+ if (mFeatureFlags.useNewLockscreenAnimations()
+ && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
mLightRevealScrim.setVisibility(View.VISIBLE);
mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
} else {
@@ -3353,6 +3361,9 @@
mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
()-> {
hideKeyguard();
+ if (shouldShowCircleReveal()) {
+ startCircleReveal();
+ }
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}).start();
}
@@ -3666,15 +3677,16 @@
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- final boolean usePowerButtonEffect =
- (isDozing && mWakefulnessLifecycle.getLastSleepReason()
- == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
- || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
- == PowerManager.WAKE_REASON_POWER_BUTTON);
-
- mLightRevealScrim.setRevealEffect(usePowerButtonEffect
- ? mPowerButtonReveal
- : LiftReveal.INSTANCE);
+ if (!isDozing && shouldShowCircleReveal()) {
+ startCircleReveal();
+ } else if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
+ == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
+ || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
+ == PowerManager.WAKE_REASON_POWER_BUTTON)) {
+ mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
+ } else if (!mCircleRevealAnimator.isRunning()) {
+ mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
+ }
mNotificationsController.requestNotificationUpdate("onDozingChanged");
updateDozingState();
@@ -3684,6 +3696,22 @@
Trace.endSection();
}
+ private void startCircleReveal() {
+ mLightRevealScrim.setRevealEffect(mCircleReveal);
+ mCircleRevealAnimator.cancel();
+ mCircleRevealAnimator.addUpdateListener(animation ->
+ mLightRevealScrim.setRevealAmount(
+ (float) mCircleRevealAnimator.getAnimatedValue()));
+ mCircleRevealAnimator.setDuration(900);
+ mCircleRevealAnimator.start();
+ }
+
+ private boolean shouldShowCircleReveal() {
+ return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
+ && mKeyguardUpdateMonitor.isUdfpsEnrolled()
+ && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
+ }
+
private void updateKeyguardState() {
mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mStatusBarKeyguardViewManager.isOccluded());
@@ -4170,6 +4198,15 @@
mBiometricUnlockController.getBiometricType());
}
+ /**
+ * Set the location of the sensor on UDFPS if existent.
+ */
+ public void setSensorRect(RectF rect) {
+ final float startRadius = (rect.right - rect.left) / 2f;
+ mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
+ startRadius, rect.centerY() - startRadius);
+ }
+
@VisibleForTesting
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
diff --git a/services/api/Android.bp b/services/api/Android.bp
index b8ca548..bbc8c72 100644
--- a/services/api/Android.bp
+++ b/services/api/Android.bp
@@ -14,6 +14,12 @@
package {
default_visibility: ["//visibility:private"],
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
}
filegroup {
@@ -26,4 +32,4 @@
name: "non-updatable-system-server-removed.txt",
srcs: ["non-updatable-removed.txt"],
visibility: ["//frameworks/base/api"],
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3c445ae..1b352c7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -160,6 +160,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
@@ -559,6 +560,45 @@
return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false;
}
+ boolean hasForegroundServiceNotificationLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Channel u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " has fg service notification");
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ void stopForegroundServicesForChannelLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Stopping FGS u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " for conversation channel clear");
+ }
+ stopServiceLocked(sr, false);
+ }
+ }
+ }
+ }
+ }
+
private ServiceMap getServiceMapLocked(int callingUser) {
ServiceMap smap = mServiceMap.get(callingUser);
if (smap == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0e8644a..c4548a3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15911,6 +15911,22 @@
}
@Override
+ public boolean hasForegroundServiceNotification(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ return mServices.hasForegroundServiceNotificationLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
+ public void stopForegroundServicesForChannel(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ mServices.stopForegroundServicesForChannelLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
public void registerProcessObserver(IProcessObserver processObserver) {
ActivityManagerService.this.registerProcessObserver(processObserver);
}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 9e79b02..273b9c3 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -30,6 +30,10 @@
michaelwr@google.com
narayan@google.com
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 5083c5e..6017e92 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -597,7 +597,8 @@
mPreAuthInfo.confirmationRequested,
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
latency,
- mDebugEnabled);
+ mDebugEnabled,
+ -1 /* sensorId */);
} else {
final long latency = System.currentTimeMillis() - mStartTimeMs;
@@ -625,7 +626,8 @@
error,
0 /* vendorCode */,
mDebugEnabled,
- latency);
+ latency,
+ -1 /* sensorId */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index de57186..282261e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -127,7 +127,8 @@
getContext().getPackageName(), mBiometricUtils, getSensorId(), mAuthenticatorIds);
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
mStatsModality,
- BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL,
+ -1 /* sensorId */);
mCurrentTask.start(mRemoveCallback);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index e3feb74..7f6903a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -118,7 +118,8 @@
getTargetUserId(), identifier.getBiometricId());
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
mStatsModality,
- BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK,
+ -1 /* sensorId */);
}
mEnrolledList.clear();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index edde3d4..4da644d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -126,7 +126,8 @@
mStatsClient,
acquiredInfo,
vendorCode,
- Utils.isDebugEnabled(context, targetUserId));
+ Utils.isDebugEnabled(context, targetUserId),
+ -1 /* sensorId */);
}
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
@@ -164,7 +165,8 @@
error,
vendorCode,
Utils.isDebugEnabled(context, targetUserId),
- sanitizeLatency(latency));
+ sanitizeLatency(latency),
+ -1 /* sensorId */);
}
protected final void logOnAuthenticated(Context context, boolean authenticated,
@@ -214,7 +216,8 @@
requireConfirmation,
authState,
sanitizeLatency(latency),
- Utils.isDebugEnabled(context, targetUserId));
+ Utils.isDebugEnabled(context, targetUserId),
+ -1 /* sensorId */);
}
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -240,7 +243,8 @@
mStatsModality,
targetUserId,
sanitizeLatency(latency),
- enrollSuccessful);
+ enrollSuccessful,
+ -1 /* sensorId */);
}
private long sanitizeLatency(long latency) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index b6c5048..ca29057 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -27,6 +27,7 @@
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
@@ -137,8 +138,7 @@
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
if (prop.commonProps.componentInfo != null) {
- for (android.hardware.biometrics.common.ComponentInfo info
- : prop.commonProps.componentInfo) {
+ for (ComponentInfo info : prop.commonProps.componentInfo) {
componentInfo.add(new ComponentInfoInternal(info.componentId,
info.hardwareVersion, info.firmwareVersion, info.serialNumber,
info.softwareVersion));
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index c7d2f0f..c6f39aa 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -546,7 +546,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index d8aaa22..50756c8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -387,7 +387,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index f8af650..1b5def6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -29,6 +29,7 @@
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.SensorProps;
import android.hardware.fingerprint.Fingerprint;
@@ -141,8 +142,7 @@
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
if (prop.commonProps.componentInfo != null) {
- for (android.hardware.biometrics.common.ComponentInfo info
- : prop.commonProps.componentInfo) {
+ for (ComponentInfo info : prop.commonProps.componentInfo) {
componentInfo.add(new ComponentInfoInternal(info.componentId,
info.hardwareVersion, info.firmwareVersion, info.serialNumber,
info.softwareVersion));
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index b9dee7d..5631647 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -526,7 +526,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 136caeb..f2992cc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -390,7 +390,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f8a913a..c010906 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1134,8 +1134,13 @@
recordStableDisplayStatsIfNeededLocked(display);
recordTopInsetLocked(display);
}
- addDisplayPowerControllerLocked(display);
- mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+ final int groupId = mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(displayId);
+ if (groupId != Display.INVALID_DISPLAY_GROUP) {
+ addDisplayPowerControllerLocked(display);
+ mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+ } else {
+ mDisplayStates.append(displayId, Display.STATE_ON);
+ }
mDisplayBrightnesses.append(displayId, display.getDisplayInfoLocked().brightnessDefault);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1214,8 +1219,7 @@
final int displayId = display.getDisplayIdLocked();
final int state = mDisplayStates.get(displayId);
- // Only send a request for display state if the display state has already been
- // initialized by DisplayPowercontroller.
+ // Only send a request for display state if display state has already been initialized.
if (state != Display.STATE_UNKNOWN) {
final float brightness = mDisplayBrightnesses.get(displayId);
return device.requestDisplayStateLocked(state, brightness);
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index fcfa674..6c2e6eb 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -433,31 +433,37 @@
final int displayId = display.getDisplayIdLocked();
// Get current display group data
- int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
+ final int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
final DisplayGroup oldGroup = getDisplayGroupLocked(groupId);
// Get the new display group if a change is needed
final DisplayInfo info = display.getDisplayInfoLocked();
final boolean needsOwnDisplayGroup = (info.flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0;
final boolean hasOwnDisplayGroup = groupId != Display.DEFAULT_DISPLAY_GROUP;
- if (groupId == Display.INVALID_DISPLAY_GROUP
- || hasOwnDisplayGroup != needsOwnDisplayGroup) {
- groupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
- }
-
- // Create a new group if needed
- DisplayGroup newGroup = getDisplayGroupLocked(groupId);
- if (newGroup == null) {
- newGroup = new DisplayGroup(groupId);
- mDisplayGroups.append(groupId, newGroup);
- }
- if (oldGroup != newGroup) {
+ final boolean needsDisplayGroup = needsOwnDisplayGroup || info.type == Display.TYPE_INTERNAL
+ || info.type == Display.TYPE_EXTERNAL;
+ if (!needsDisplayGroup) {
if (oldGroup != null) {
oldGroup.removeDisplayLocked(display);
}
+ return;
+ }
+ if (groupId == Display.INVALID_DISPLAY_GROUP
+ || hasOwnDisplayGroup != needsOwnDisplayGroup) {
+ if (oldGroup != null) {
+ oldGroup.removeDisplayLocked(display);
+ }
+
+ final int newGroupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
+ // Create a new group if needed
+ DisplayGroup newGroup = getDisplayGroupLocked(newGroupId);
+ if (newGroup == null) {
+ newGroup = new DisplayGroup(newGroupId);
+ mDisplayGroups.append(newGroupId, newGroup);
+ }
newGroup.addDisplayLocked(display);
- display.updateDisplayGroupIdLocked(groupId);
- Slog.i(TAG, "Setting new display group " + groupId + " for display "
+ display.updateDisplayGroupIdLocked(newGroupId);
+ Slog.i(TAG, "Setting new display group " + newGroupId + " for display "
+ displayId + ", from previous group: "
+ (oldGroup != null ? oldGroup.getGroupId() : "null"));
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e588366..eb4f9d3 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3576,15 +3576,30 @@
pkg, uid, channelId, conversationId, true, includeDeleted);
}
+ // Returns 'true' if the given channel has a notification associated
+ // with an active foreground service.
+ private void enforceDeletingChannelHasNoFgService(String pkg, int userId,
+ String channelId) {
+ if (mAmi.hasForegroundServiceNotification(pkg, userId, channelId)) {
+ Slog.w(TAG, "Package u" + userId + "/" + pkg
+ + " may not delete notification channel '"
+ + channelId + "' with fg service");
+ throw new SecurityException("Not allowed to delete channel " + channelId
+ + " with a foreground service");
+ }
+ }
+
@Override
public void deleteNotificationChannel(String pkg, String channelId) {
checkCallerIsSystemOrSameApp(pkg);
final int callingUid = Binder.getCallingUid();
+ final int callingUser = UserHandle.getUserId(callingUid);
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
throw new IllegalArgumentException("Cannot delete default channel");
}
+ enforceDeletingChannelHasNoFgService(pkg, callingUser, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
+ callingUser, REASON_CHANNEL_BANNED, null);
mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
@@ -3597,19 +3612,23 @@
public void deleteConversationNotificationChannels(String pkg, int uid,
String conversationId) {
checkCallerIsSystem();
- final int callingUid = Binder.getCallingUid();
List<NotificationChannel> channels =
mPreferencesHelper.getNotificationChannelsByConversationId(
pkg, uid, conversationId);
if (!channels.isEmpty()) {
+ // Preflight for fg service notifications in these channels: do nothing
+ // unless they're all eligible
+ final int appUserId = UserHandle.getUserId(uid);
for (NotificationChannel nc : channels) {
+ final String channelId = nc.getId();
+ mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
- mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, nc.getId());
+ appUserId, REASON_CHANNEL_BANNED, null);
+ mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
- UserHandle.getUserHandleForUid(callingUid),
+ UserHandle.getUserHandleForUid(uid),
mPreferencesHelper.getNotificationChannel(
- pkg, callingUid, nc.getId(), true),
+ pkg, uid, channelId, true),
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
}
handleSavePolicyFile();
@@ -3640,13 +3659,20 @@
NotificationChannelGroup groupToDelete =
mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
if (groupToDelete != null) {
+ // Preflight for allowability
+ final int userId = UserHandle.getUserId(callingUid);
+ List<NotificationChannel> groupChannels = groupToDelete.getChannels();
+ for (int i = 0; i < groupChannels.size(); i++) {
+ enforceDeletingChannelHasNoFgService(pkg, userId,
+ groupChannels.get(i).getId());
+ }
List<NotificationChannel> deletedChannels =
mPreferencesHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
for (int i = 0; i < deletedChannels.size(); i++) {
final NotificationChannel deletedChannel = deletedChannels.get(i);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+ userId, REASON_CHANNEL_BANNED,
null);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index dbd1211..27b1648 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -103,7 +103,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
/**
@@ -312,7 +311,7 @@
// Initialize any users that can't be switched to, as their state would
// never be setup in onSwitchUser(). We will switch to the system user right
// after this, and its state will be setup there.
- updatePackageManager(mImpl.updateOverlaysForUser(users.get(i).id));
+ updatePackageManagerLocked(mImpl.updateOverlaysForUser(users.get(i).id));
}
}
}
@@ -329,9 +328,8 @@
// ensure overlays in the settings are up-to-date, and propagate
// any asset changes to the rest of the system
synchronized (mLock) {
- updateActivityManager(updatePackageManager(mImpl.updateOverlaysForUser(newUserId)));
+ updateTargetPackagesLocked(mImpl.updateOverlaysForUser(newUserId));
}
- persistSettings();
} finally {
traceEnd(TRACE_TAG_RRO);
}
@@ -415,7 +413,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageAdded(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageAdded(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageAdded internal error", e);
}
@@ -437,7 +436,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageChanged(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageChanged(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageChanged internal error", e);
}
@@ -459,7 +459,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageReplacing(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageReplacing(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplacing internal error", e);
}
@@ -481,7 +482,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageReplaced(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageReplaced(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplaced internal error", e);
}
@@ -500,7 +502,7 @@
for (int userId : userIds) {
synchronized (mLock) {
mPackageManager.onPackageRemoved(packageName, userId);
- updateTargetPackages(mImpl.onPackageRemoved(packageName, userId));
+ updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
}
}
} finally {
@@ -519,7 +521,7 @@
try {
traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
synchronized (mLock) {
- updatePackageManager(mImpl.updateOverlaysForUser(userId));
+ updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId));
}
} finally {
traceEnd(TRACE_TAG_RRO);
@@ -624,7 +626,8 @@
try {
synchronized (mLock) {
try {
- updateTargetPackages(mImpl.setEnabled(overlay, enable, realUserId));
+ updateTargetPackagesLocked(
+ mImpl.setEnabled(overlay, enable, realUserId));
return true;
} catch (OperationFailedException e) {
return false;
@@ -656,9 +659,10 @@
try {
synchronized (mLock) {
try {
- mImpl.setEnabledExclusive(overlay,
- false /* withinCategory */, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ mImpl.setEnabledExclusive(
+ overlay, false /* withinCategory */, realUserId)
+ .ifPresent(
+ OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -693,7 +697,7 @@
try {
mImpl.setEnabledExclusive(overlay,
true /* withinCategory */, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -728,7 +732,7 @@
synchronized (mLock) {
try {
mImpl.setPriority(overlay, parentOverlay, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -759,7 +763,8 @@
try {
synchronized (mLock) {
try {
- updateTargetPackages(mImpl.setHighestPriority(overlay, realUserId));
+ updateTargetPackagesLocked(
+ mImpl.setHighestPriority(overlay, realUserId));
return true;
} catch (OperationFailedException e) {
return false;
@@ -791,7 +796,7 @@
synchronized (mLock) {
try {
mImpl.setLowestPriority(overlay, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -945,27 +950,12 @@
throw new IllegalArgumentException("null transaction");
}
- // map: userId -> set<package-name>: target packages of overlays in
- // this transaction
- final SparseArray<Set<String>> transactionTargets = new SparseArray<>();
-
- // map: userId -> set<package-name>: packages that need to reload
- // their resources due to changes to the overlays in this
- // transaction
- final SparseArray<List<String>> affectedPackagesToUpdate = new SparseArray<>();
-
synchronized (mLock) {
// execute the requests (as calling user)
+ Set<PackageAndUser> affectedPackagesToUpdate = null;
for (final OverlayManagerTransaction.Request request : transaction) {
- executeRequest(request).forEach(
- target -> {
- Set<String> userTargets = transactionTargets.get(target.userId);
- if (userTargets == null) {
- userTargets = new ArraySet<>();
- transactionTargets.put(target.userId, userTargets);
- }
- userTargets.add(target.packageName);
- });
+ affectedPackagesToUpdate = CollectionUtils.addAll(affectedPackagesToUpdate,
+ executeRequest(request));
}
// past the point of no return: the entire transaction has been
@@ -973,37 +963,11 @@
// system_server
final long ident = Binder.clearCallingIdentity();
try {
- persistSettings();
-
- // inform the package manager about the new paths
- for (int index = 0; index < transactionTargets.size(); index++) {
- final int userId = transactionTargets.keyAt(index);
- final List<String> affectedTargets =
- updatePackageManager(transactionTargets.valueAt(index), userId);
- affectedPackagesToUpdate.put(userId, affectedTargets);
- }
+ updateTargetPackagesLocked(affectedPackagesToUpdate);
} finally {
Binder.restoreCallingIdentity(ident);
}
- } // synchronized (mLock)
-
- FgThread.getHandler().post(() -> {
- final long ident = Binder.clearCallingIdentity();
- try {
- // schedule apps to refresh
- updateActivityManager(affectedPackagesToUpdate);
-
- // broadcast the ACTION_OVERLAY_CHANGED intents
- for (int index = 0; index < transactionTargets.size(); index++) {
- final int userId = transactionTargets.keyAt(index);
- for (String pkg: transactionTargets.valueAt(index)) {
- broadcastActionOverlayChanged(pkg, userId);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- });
+ }
}
@Override
@@ -1382,32 +1346,37 @@
}
}
- private void updateTargetPackages(@Nullable PackageAndUser updatedTarget) {
+ private void updateTargetPackagesLocked(@Nullable PackageAndUser updatedTarget) {
if (updatedTarget != null) {
- updateTargetPackages(Set.of(updatedTarget));
+ updateTargetPackagesLocked(Set.of(updatedTarget));
}
}
- private void updateTargetPackages(@Nullable Set<PackageAndUser> updatedTargets) {
+ private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) {
if (CollectionUtils.isEmpty(updatedTargets)) {
return;
}
- persistSettings();
+ persistSettingsLocked();
final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets);
- FgThread.getHandler().post(() -> {
- for (int i = 0, n = userTargets.size(); i < n; i++) {
- final ArraySet<String> targets = userTargets.valueAt(i);
- final int userId = userTargets.keyAt(i);
+ for (int i = 0, n = userTargets.size(); i < n; i++) {
+ final ArraySet<String> targets = userTargets.valueAt(i);
+ final int userId = userTargets.keyAt(i);
+ final List<String> affectedPackages = updatePackageManagerLocked(targets, userId);
+ if (affectedPackages.isEmpty()) {
+ // The package manager paths are already up-to-date.
+ continue;
+ }
- // Update the overlay paths in package manager.
- final List<String> affectedPackages = updatePackageManager(targets, userId);
+ FgThread.getHandler().post(() -> {
+ // Send configuration changed events for all target packages that have been affected
+ // by overlay state changes.
updateActivityManager(affectedPackages, userId);
- // Overlays targeting shared libraries may cause more packages to need to be
- // refreshed.
+ // Do not send broadcasts for all affected targets. Overlays targeting the framework
+ // or shared libraries may cause too many broadcasts to be sent at once.
broadcastActionOverlayChanged(targets, userId);
- }
- });
+ });
+ }
}
@Nullable
@@ -1430,20 +1399,17 @@
private static void broadcastActionOverlayChanged(@NonNull final Set<String> targetPackages,
final int userId) {
- CollectionUtils.forEach(targetPackages,
- target -> broadcastActionOverlayChanged(target, userId));
- }
-
- private static void broadcastActionOverlayChanged(String targetPackage, final int userId) {
- final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
- Uri.fromParts("package", targetPackage, null));
- intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- try {
- ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null, null,
- null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
- } catch (RemoteException e) {
- // Intentionally left empty.
- }
+ CollectionUtils.forEach(targetPackages, target -> {
+ final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
+ Uri.fromParts("package", target, null));
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ try {
+ ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null,
+ null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "broadcastActionOverlayChanged remote exception", e);
+ }
+ });
}
/**
@@ -1455,18 +1421,13 @@
try {
am.scheduleApplicationInfoChanged(targetPackageNames, userId);
} catch (RemoteException e) {
- // Intentionally left empty.
- }
- }
-
- private void updateActivityManager(@NonNull SparseArray<List<String>> targetPackageNames) {
- for (int i = 0, n = targetPackageNames.size(); i < n; i++) {
- updateActivityManager(targetPackageNames.valueAt(i), targetPackageNames.keyAt(i));
+ Slog.e(TAG, "updateActivityManager remote exception", e);
}
}
@NonNull
- private SparseArray<List<String>> updatePackageManager(@Nullable Set<PackageAndUser> targets) {
+ private SparseArray<List<String>> updatePackageManagerLocked(
+ @Nullable Set<PackageAndUser> targets) {
if (CollectionUtils.isEmpty(targets)) {
return new SparseArray<>();
}
@@ -1474,7 +1435,7 @@
final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(targets);
for (int i = 0, n = userTargets.size(); i < n; i++) {
final int userId = userTargets.keyAt(i);
- affectedTargets.put(userId, updatePackageManager(userTargets.valueAt(i), userId));
+ affectedTargets.put(userId, updatePackageManagerLocked(userTargets.valueAt(i), userId));
}
return affectedTargets;
}
@@ -1485,10 +1446,10 @@
* targetPackageNames: the target themselves and shared libraries)
*/
@NonNull
- private List<String> updatePackageManager(@NonNull Collection<String> targetPackageNames,
+ private List<String> updatePackageManagerLocked(@NonNull Collection<String> targetPackageNames,
final int userId) {
try {
- traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManager " + targetPackageNames);
+ traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManagerLocked " + targetPackageNames);
if (DEBUG) {
Slog.d(TAG, "Update package manager about changed overlays");
}
@@ -1535,20 +1496,18 @@
}
}
- private void persistSettings() {
+ private void persistSettingsLocked() {
if (DEBUG) {
Slog.d(TAG, "Writing overlay settings");
}
- synchronized (mLock) {
- FileOutputStream stream = null;
- try {
- stream = mSettingsFile.startWrite();
- mSettings.persist(stream);
- mSettingsFile.finishWrite(stream);
- } catch (IOException | XmlPullParserException e) {
- mSettingsFile.failWrite(stream);
- Slog.e(TAG, "failed to persist overlay state", e);
- }
+ FileOutputStream stream = null;
+ try {
+ stream = mSettingsFile.startWrite();
+ mSettings.persist(stream);
+ mSettingsFile.finishWrite(stream);
+ } catch (IOException | XmlPullParserException e) {
+ mSettingsFile.failWrite(stream);
+ Slog.e(TAG, "failed to persist overlay state", e);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8283ac6..fe19956 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2861,6 +2861,100 @@
}
}
+ @GuardedBy("mUsersLock")
+ @VisibleForTesting
+ void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
+ @NonNull ArrayMap<String, UserTypeDetails> userTypes,
+ final int formerUserTypeVersion,
+ @NonNull Set<Integer> userIdsToWrite) {
+ for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
+ if (DBG) {
+ Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
+ + userTypeUpgrade.getToType() + " maxVersion: "
+ + userTypeUpgrade.getUpToVersion());
+ }
+
+ // upgrade user type if version up to getUpToVersion()
+ if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserData userData = mUsers.valueAt(i);
+ if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
+ final UserTypeDetails newUserType = userTypes.get(
+ userTypeUpgrade.getToType());
+
+ if (newUserType == null) {
+ throw new IllegalStateException(
+ "Upgrade destination user type not defined: "
+ + userTypeUpgrade.getToType());
+ }
+
+ upgradeProfileToTypeLU(userData.info, newUserType);
+ userIdsToWrite.add(userData.info.id);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Changes the user type of a profile to a new user type.
+ * @param userInfo The user to be updated.
+ * @param newUserType The new user type.
+ */
+ @GuardedBy("mUsersLock")
+ @VisibleForTesting
+ void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
+ Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
+ + " from " + userInfo.userType
+ + " to " + newUserType.getName());
+
+ if (!userInfo.isProfile()) {
+ throw new IllegalStateException(
+ "Can only upgrade profile types. " + userInfo.userType
+ + " is not a profile type.");
+ }
+
+ // Exceeded maximum profiles for parent user: log error, but allow upgrade
+ if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
+ Slog.w(LOG_TAG,
+ "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
+ + userInfo.id + ". Maximum allowed= "
+ + newUserType.getMaxAllowedPerParent());
+ }
+
+ final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
+ final int oldFlags;
+ if (oldUserType != null) {
+ oldFlags = oldUserType.getDefaultUserInfoFlags();
+ } else {
+ // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
+ oldFlags = UserInfo.FLAG_PROFILE;
+ }
+
+ //convert userData to newUserType
+ userInfo.userType = newUserType.getName();
+ // remove old default flags and add newUserType's default flags
+ userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
+
+ // merge existing base restrictions with the new type's default restrictions
+ synchronized (mRestrictionsLock) {
+ if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
+ final Bundle newRestrictions = BundleUtils.clone(
+ mBaseUserRestrictions.getRestrictions(userInfo.id));
+ UserRestrictionsUtils.merge(newRestrictions,
+ newUserType.getDefaultRestrictions());
+ updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
+ if (DBG) {
+ Slog.i(LOG_TAG, "Updated user " + userInfo.id
+ + " restrictions to " + newRestrictions);
+ }
+ }
+ }
+
+ // re-compute badge index
+ userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
+ }
+
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
@@ -5759,98 +5853,4 @@
}
return mDevicePolicyManagerInternal;
}
-
- @GuardedBy("mUsersLock")
- @VisibleForTesting
- void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
- @NonNull ArrayMap<String, UserTypeDetails> userTypes,
- final int formerUserTypeVersion,
- @NonNull Set<Integer> userIdsToWrite) {
- for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
- if (DBG) {
- Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
- + userTypeUpgrade.getToType() + " maxVersion: "
- + userTypeUpgrade.getUpToVersion());
- }
-
- // upgrade user type if version up to getUpToVersion()
- if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
- for (int i = 0; i < mUsers.size(); i++) {
- UserData userData = mUsers.valueAt(i);
- if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
- final UserTypeDetails newUserType = userTypes.get(
- userTypeUpgrade.getToType());
-
- if (newUserType == null) {
- throw new IllegalStateException(
- "Upgrade destination user type not defined: "
- + userTypeUpgrade.getToType());
- }
-
- upgradeProfileToTypeLU(userData.info, newUserType);
- userIdsToWrite.add(userData.info.id);
- }
- }
- }
- }
- }
-
- /**
- * Changes the user type of a profile to a new user type.
- * @param userInfo The user to be updated.
- * @param newUserType The new user type.
- */
- @GuardedBy("mUsersLock")
- @VisibleForTesting
- void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
- Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
- + " from " + userInfo.userType
- + " to " + newUserType.getName());
-
- if (!userInfo.isProfile()) {
- throw new IllegalStateException(
- "Can only upgrade profile types. " + userInfo.userType
- + " is not a profile type.");
- }
-
- // Exceeded maximum profiles for parent user: log error, but allow upgrade
- if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
- Slog.w(LOG_TAG,
- "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
- + userInfo.id + ". Maximum allowed= "
- + newUserType.getMaxAllowedPerParent());
- }
-
- final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
- final int oldFlags;
- if (oldUserType != null) {
- oldFlags = oldUserType.getDefaultUserInfoFlags();
- } else {
- // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
- oldFlags = UserInfo.FLAG_PROFILE;
- }
-
- //convert userData to newUserType
- userInfo.userType = newUserType.getName();
- // remove old default flags and add newUserType's default flags
- userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
-
- // merge existing base restrictions with the new type's default restrictions
- synchronized (mRestrictionsLock) {
- if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
- final Bundle newRestrictions = BundleUtils.clone(
- mBaseUserRestrictions.getRestrictions(userInfo.id));
- UserRestrictionsUtils.merge(newRestrictions,
- newUserType.getDefaultRestrictions());
- updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
- if (DBG) {
- Slog.i(LOG_TAG, "Updated user " + userInfo.id
- + " restrictions to " + newRestrictions);
- }
- }
- }
-
- // re-compute badge index
- userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
- }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index a46a8d5..64a26ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.os.Build.IS_USER;
+import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
@@ -135,6 +136,8 @@
return runGetLetterboxBackgroundColor(pw);
case "reset":
return runReset(pw);
+ case "disable-blur":
+ return runSetBlurDisabled(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -214,6 +217,33 @@
return 0;
}
+ private int runSetBlurDisabled(PrintWriter pw) throws RemoteException {
+ String arg = getNextArg();
+ if (arg == null) {
+ pw.println("Blur supported on device: " + CROSS_WINDOW_BLUR_SUPPORTED);
+ pw.println("Blur enabled: " + mInternal.mBlurController.mBlurEnabled);
+ return 0;
+ }
+
+ final boolean disableBlur;
+ switch (arg) {
+ case "true":
+ case "1":
+ disableBlur = true;
+ break;
+ case "false":
+ case "0":
+ disableBlur = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
+ return -1;
+ }
+
+ mInterface.setForceCrossWindowBlurDisabled(disableBlur);
+ return 0;
+ }
+
private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
try {
final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
@@ -725,6 +755,7 @@
pw.println(" Set display scaling mode.");
pw.println(" dismiss-keyguard");
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
+ pw.println(" disable-blur [true|1|false|0]");
pw.println(" user-rotation [-d DISPLAY_ID] [free|lock] [rotation]");
pw.println(" Print or set user rotation mode and user rotation.");
pw.println(" dump-visible-window-views");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8131e4..283895b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
@@ -430,6 +431,7 @@
DELEGATION_INSTALL_EXISTING_PACKAGE,
DELEGATION_KEEP_UNINSTALLED_PACKAGES,
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
};
@@ -440,9 +442,18 @@
DELEGATION_NETWORK_LOGGING,
});
+ // Subset of delegations that can only be delegated by Device Owner or Profile Owner of an
+ // organization-owned and managed profile.
+ private static final List<String>
+ DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS =
+ Arrays.asList(new String[]{
+ DELEGATION_SECURITY_LOGGING,
+ });
+
// Subset of delegations that only one single package within a given user can hold
private static final List<String> EXCLUSIVE_DELEGATIONS = Arrays.asList(new String[] {
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
});
@@ -6024,6 +6035,10 @@
if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
+ } else if (!Collections.disjoint(
+ scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ || isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
@@ -7658,6 +7673,10 @@
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
deviceOwnerUserId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
+ deviceOwnerUserId);
+ }
if (receiverComponent == null) {
synchronized (getLockObject()) {
receiverComponent = mOwners.getDeviceOwnerComponent();
@@ -7674,6 +7693,10 @@
if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(
+ DELEGATION_SECURITY_LOGGING, action, userId);
+ }
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
}
@@ -13920,16 +13943,24 @@
}
@Override
- public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
+ public void setSecurityLoggingEnabled(ComponentName admin, String packageName,
+ boolean enabled) {
if (!mHasFeature) {
return;
}
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
synchronized (getLockObject()) {
- Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
return;
}
@@ -13949,17 +13980,23 @@
}
@Override
- public boolean isSecurityLoggingEnabled(ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(ComponentName admin, String packageName) {
if (!mHasFeature) {
return false;
}
synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(
- isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
}
return mInjector.securityLogGetLoggingEnabledProperty();
}
@@ -13977,15 +14014,23 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
@@ -14015,15 +14060,22 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 7e85f9d..3465499 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -255,7 +255,7 @@
static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
-class RealTimedQueueWrapper : public TimedQueueWrapper {
+class RealTimedQueueWrapper final : public TimedQueueWrapper {
public:
RealTimedQueueWrapper(JavaVM* jvm) {
mThread = std::thread([this, jvm]() {
@@ -268,11 +268,11 @@
CHECK(!mThread.joinable()) << "call stop first";
}
- void addJob(MountId id, Milliseconds after, Job what) final {
+ void addJob(MountId id, Milliseconds timeout, Job what) final {
const auto now = Clock::now();
{
std::unique_lock lock(mMutex);
- mJobs.insert(TimedJob{id, now + after, std::move(what)});
+ mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
}
mCondition.notify_all();
}
@@ -293,29 +293,28 @@
private:
void runTimers() {
static constexpr TimePoint kInfinityTs{Clock::duration::max()};
- TimePoint nextJobTs = kInfinityTs;
std::unique_lock lock(mMutex);
for (;;) {
- mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() {
+ const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
+ mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
const auto now = Clock::now();
- const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
- return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs;
+ const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
+ return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
});
if (!mRunning) {
return;
}
const auto now = Clock::now();
- auto it = mJobs.begin();
- // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
- for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
+ // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
+ for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
+ it = mJobs.begin()) {
auto jobNode = mJobs.extract(it);
lock.unlock();
jobNode.value().what();
lock.lock();
}
- nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
}
}
@@ -328,7 +327,7 @@
}
};
bool mRunning = true;
- std::set<TimedJob> mJobs;
+ std::multiset<TimedJob> mJobs;
std::condition_variable mCondition;
std::mutex mMutex;
std::thread mThread;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
index 5a4431e..5492dc8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
@@ -1,2 +1 @@
-calin@google.com
-ngeoffray@google.com
+include platform/art:/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index bcd853c..dcb2c15 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -186,11 +186,14 @@
LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0));
LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
+ // Physical displays should be automatically put into the default group.
assertEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1)));
assertEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2)));
- assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+
+ // Virtual displays should belong to no group by default.
+ assertEquals(Display.INVALID_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
}
@@ -212,13 +215,13 @@
assertNotEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
- // Now switch it back to the default group by removing the flag and issuing an update
+ // Now switch it to the invalid group by removing the flag and issuing an update
DisplayDeviceInfo info = device3.getSourceInfo();
info.flags = info.flags & ~DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
- // Verify the new group is correct.
- assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+ // Verify the virtual display has not been placed into a group.
+ assertEquals(Display.INVALID_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
}
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index f5357b1..011dc17 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -27,6 +27,8 @@
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
+
+import android.telephony.CallQuality;
import android.util.ArrayMap;
import com.android.internal.telecom.ICallDiagnosticService;
@@ -111,6 +113,12 @@
@NonNull DisconnectCause disconnectCause) throws RemoteException {
handleCallDisconnected(callId, disconnectCause);
}
+
+ @Override
+ public void callQualityChanged(String callId, CallQuality callQuality)
+ throws RemoteException {
+ handleCallQualityChanged(callId, callQuality);
+ }
}
/**
@@ -375,6 +383,21 @@
}
/**
+ * Handles a change reported by Telecom to the call quality for a call.
+ * @param callId the call ID the change applies to.
+ * @param callQuality The new call quality.
+ */
+ private void handleCallQualityChanged(@NonNull String callId,
+ @NonNull CallQuality callQuality) {
+ Log.i(this, "handleCallQualityChanged; call=%s, cq=%s", callId, callQuality);
+ CallDiagnostics callDiagnostics;
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ if (callDiagnostics != null) {
+ callDiagnostics.onCallQualityReceived(callQuality);
+ }
+ }
+
+ /**
* Handles a request from a {@link CallDiagnostics} to send a device to device message (received
* via {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}.
* @param callDiagnostics
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 6dab6df..2dc18e8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -44,6 +44,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.telephony.CallQuality;
import android.telephony.ims.ImsStreamMediaProfile;
import android.util.ArraySet;
import android.view.Surface;
@@ -978,6 +979,23 @@
public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE =
"android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_VALUE";
+ /**
+ * Connection event used to communicate a {@link android.telephony.CallQuality} report from
+ * telephony to Telecom for relaying to
+ * {@link DiagnosticCall#onCallQualityReceived(CallQuality)}.
+ * @hide
+ */
+ public static final String EVENT_CALL_QUALITY_REPORT =
+ "android.telecom.event.CALL_QUALITY_REPORT";
+
+ /**
+ * Extra sent with {@link #EVENT_CALL_QUALITY_REPORT} containing the
+ * {@link android.telephony.CallQuality} data.
+ * @hide
+ */
+ public static final String EXTRA_CALL_QUALITY_REPORT =
+ "android.telecom.extra.CALL_QUALITY_REPORT";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
diff --git a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
index fc9879a..4bd369f 100644
--- a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
@@ -20,6 +20,7 @@
import android.telecom.CallAudioState;
import android.telecom.DisconnectCause;
import android.telecom.ParcelableCall;
+import android.telephony.CallQuality;
import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
/**
@@ -34,6 +35,7 @@
void updateCallAudioState(in CallAudioState callAudioState);
void removeDiagnosticCall(in String callId);
void receiveDeviceToDeviceMessage(in String callId, int message, int value);
+ void callQualityChanged(in String callId, in CallQuality callQuality);
void receiveBluetoothCallQualityReport(in BluetoothCallQualityReport qualityReport);
void notifyCallDisconnected(in String callId, in DisconnectCause disconnectCause);
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 4926687..17af463 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -2207,7 +2208,9 @@
*
* @return the total number of SMS records which can be stored on the SIM card.
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+ @IntRange(from = 0)
public int getSmsCapacityOnIcc() {
int ret = 0;
try {