Merge "Do no use libandroidicu for host targets"
diff --git a/Android.bp b/Android.bp
index 727842e..490de6e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -842,6 +842,7 @@
java_library {
name: "framework-annotation-proc",
defaults: ["framework-defaults"],
+ installable: false,
// Use UsedByApps annotation processor
plugins: ["unsupportedappusage-annotation-processor"],
}
@@ -1880,3 +1881,13 @@
srcs: [":framework-defaults"],
output: "framework-aidl-mappings.txt",
}
+
+genrule {
+ name: "framework-annotation-proc-index",
+ srcs: [":framework-annotation-proc"],
+ cmd: "unzip -qp $(in) unsupportedappusage/unsupportedappusage_index.csv > $(out)",
+ out: ["unsupportedappusage_index.csv"],
+ dist: {
+ targets: ["droidcore"],
+ },
+}
diff --git a/api/test-current.txt b/api/test-current.txt
index bf2730a..14c70e3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -795,6 +795,7 @@
}
public final class RollbackManager {
+ method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
@@ -2301,6 +2302,7 @@
field public static final String NAMESPACE_PRIVACY = "privacy";
field public static final String NAMESPACE_ROLLBACK = "rollback";
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
+ field public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
}
public static interface DeviceConfig.OnPropertiesChangedListener {
@@ -2317,6 +2319,10 @@
method @Nullable public String getString(@NonNull String, @Nullable String);
}
+ public static interface DeviceConfig.WindowManager {
+ field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+ }
+
public final class MediaStore {
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 10f25ea..c30a6f4 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -581,6 +581,7 @@
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName;
Landroid/service/euicc/IEuiccService$Stub;-><init>()V
+Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
Landroid/service/notification/INotificationListener$Stub;-><init>()V
Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7a614ce..525bc44b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1050,6 +1050,7 @@
}
}
+ @UnsupportedAppUsage
@Override
public boolean setInstantAppCookie(@NonNull byte[] cookie) {
try {
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 60fb6fb..a812c32 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,6 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -83,6 +84,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
"android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
@@ -303,6 +305,7 @@
* @return false on immediate error, true otherwise
* @hide
*/
+ @UnsupportedAppUsage
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
final IBluetoothHearingAid service = getService();
@@ -331,6 +334,7 @@
* is not active, it will be null on that position. Returns empty list on error.
* @hide
*/
+ @UnsupportedAppUsage
@RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 1838bab..f39fc66 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.os.Parcel;
import android.os.Parcelable;
@@ -169,6 +170,7 @@
* The state of this OverlayInfo as defined by the STATE_* constants in this class.
* @hide
*/
+ @UnsupportedAppUsage
public final @State int state;
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a2994af..cf858f5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -8397,6 +8397,7 @@
PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
Collections.emptySet(), state);
pi.applicationInfo.sourceDir = apexFile.getPath();
+ pi.applicationInfo.publicSourceDir = apexFile.getPath();
if (apexInfo.isFactory) {
pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
} else {
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index 1b84f29..8c2a65f 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -24,7 +24,7 @@
interface IRollbackManager {
ParceledListSlice getAvailableRollbacks();
- ParceledListSlice getRecentlyExecutedRollbacks();
+ ParceledListSlice getRecentlyCommittedRollbacks();
void commitRollback(int rollbackId, in ParceledListSlice causePackages,
String callerPackageName, in IntentSender statusReceiver);
@@ -51,4 +51,7 @@
// Used by the staging manager to notify the RollbackManager of the apk
// session for a staged session.
void notifyStagedApkSession(int originalSessionId, int apkSessionId);
+
+ // For test purposes only.
+ void blockRollbackManager(long millis);
}
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index 9a10a0c..73b8a48 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -114,7 +114,7 @@
})
public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() {
try {
- return mBinder.getRecentlyExecutedRollbacks().getList();
+ return mBinder.getRecentlyCommittedRollbacks().getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -250,4 +250,25 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Block the RollbackManager for a specified amount of time.
+ * This API is meant to facilitate testing of race conditions in
+ * RollbackManager. Blocks RollbackManager from processing anything for
+ * the given number of milliseconds.
+ *
+ * @param millis number of milliseconds to block the RollbackManager for
+ * @throws SecurityException if the caller does not have appropriate permissions.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS)
+ @TestApi
+ public void blockRollbackManager(long millis) {
+ try {
+ mBinder.blockRollbackManager(millis);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 04e8cf4..5ac13d8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -925,14 +925,14 @@
* case, when the application configures a RAW stream, the camera device will make sure
* the active physical camera will remain active to ensure consistent RAW output
* behavior, and not switch to other physical cameras.</p>
- * <p>To maintain backward compatibility, the capture request and result metadata tags
- * required for basic camera functionalities will be solely based on the
- * logical camera capabiltity. Other request and result metadata tags, on the other
- * hand, will be based on current active physical camera. For example, the physical
- * cameras' sensor sensitivity and lens capability could be different from each other.
- * So when the application manually controls sensor exposure time/gain, or does manual
- * focus control, it must checks the current active physical camera's exposure, gain,
- * and focus distance range.</p>
+ * <p>The capture request and result metadata tags required for backward compatible camera
+ * functionalities will be solely based on the logical camera capabiltity. On the other
+ * hand, the use of manual capture controls (sensor or post-processing) with a
+ * logical camera may result in unexpected behavior when the HAL decides to switch
+ * between physical cameras with different characteristics under the hood. For example,
+ * when the application manually sets exposure time and sensitivity while zooming in,
+ * the brightness of the camera images may suddenly change because HAL switches from one
+ * physical camera to the other.</p>
*
* @see CameraCharacteristics#LENS_DISTORTION
* @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index c45b8ed..3e995b6 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -48,7 +48,8 @@
return pulseOnNotificationEnabled(user)
|| pulseOnLongPressEnabled(user)
|| alwaysOnEnabled(user)
- || wakeScreenGestureEnabled(user)
+ || wakeLockScreenGestureEnabled(user)
+ || wakeDisplayGestureEnabled(user)
|| pickupGestureEnabled(user)
|| tapGestureEnabled(user)
|| doubleTapGestureEnabled(user);
@@ -105,8 +106,14 @@
}
/** {@hide} */
- public boolean wakeScreenGestureEnabled(int user) {
- return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+ public boolean wakeLockScreenGestureEnabled(int user) {
+ return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
+ && wakeScreenGestureAvailable();
+ }
+
+ /** {@hide} */
+ public boolean wakeDisplayGestureEnabled(int user) {
+ return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, user)
&& wakeScreenGestureAvailable();
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 660cd848..43ea589 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -437,15 +437,23 @@
}
/**
- * Called by the bearer to indicate this network was manually selected by the user.
+ * Called by the bearer to indicate whether the network was manually selected by the user.
* This should be called before the NetworkInfo is marked CONNECTED so that this
- * Network can be given special treatment at that time. If {@code acceptUnvalidated} is
- * {@code true}, then the system will switch to this network. If it is {@code false} and the
- * network cannot be validated, the system will ask the user whether to switch to this network.
- * If the user confirms and selects "don't ask again", then the system will call
- * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
- * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
- * {@link #saveAcceptUnvalidated} to respect the user's choice.
+ * Network can be given special treatment at that time.
+ *
+ * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true},
+ * then the system will switch to this network. If {@code explicitlySelected} is {@code true}
+ * and {@code acceptUnvalidated} is {@code false}, and the network cannot be validated, the
+ * system will ask the user whether to switch to this network. If the user confirms and selects
+ * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the
+ * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected}
+ * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also
+ * implement {@link #saveAcceptUnvalidated} to respect the user's choice.
+ *
+ * If {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is
+ * {@code true}, the system will interpret this as the user having accepted partial connectivity
+ * on this network. Thus, the system will switch to the network and consider it validated even
+ * if it only provides partial connectivity, but the network is not otherwise treated specially.
*/
public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED,
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index b121234..d70ba99 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -68,6 +68,7 @@
public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
/** @hide An undefined user id */
+ @UnsupportedAppUsage
public static final @UserIdInt int USER_NULL = -10000;
/**
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 01b6758..48faf11 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -293,6 +293,15 @@
public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
/**
+ * Namespace for window manager related features. The names to access the properties in this
+ * namespace should be defined in {@link WindowManager}.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
+
+ /**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
*
* @hide
@@ -309,6 +318,23 @@
@TestApi
public static final String NAMESPACE_PRIVACY = "privacy";
+ /**
+ * Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
+ * @hide
+ */
+ @TestApi
+ public interface WindowManager {
+
+ /**
+ * Key for accessing the system gesture exclusion limit (an integer in dp).
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ @TestApi
+ String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+ }
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e5b7987..9e1bb94 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -88,6 +88,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.MemoryIntArray;
+import android.view.Display;
import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.annotations.GuardedBy;
@@ -4073,7 +4074,7 @@
* preference, this rotation value will be used. Must be one of the
* {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
*
- * @see android.view.Display#getRotation
+ * @see Display#getRotation
*/
public static final String USER_ROTATION = "user_rotation";
@@ -7733,12 +7734,21 @@
private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
- * Gesture that wakes up the display, showing the ambient version of the status bar.
+ * Gesture that wakes up the display, showing some version of the lock screen.
* @hide
*/
- public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+ public static final String DOZE_WAKE_LOCK_SCREEN_GESTURE = "doze_wake_screen_gesture";
- private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+ private static final Validator DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
+ * Gesture that wakes up the display, toggling between {@link Display.STATE_OFF} and
+ * {@link Display.STATE_DOZE}.
+ * @hide
+ */
+ public static final String DOZE_WAKE_DISPLAY_GESTURE = "doze_wake_display_gesture";
+
+ private static final Validator DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
* Gesture that skips media.
@@ -8266,6 +8276,16 @@
BOOLEAN_VALIDATOR;
/**
+ * Whether or not media is shown automatically when bypassing as a heads up.
+ * @hide
+ */
+ public static final String SHOW_MEDIA_WHEN_BYPASSING =
+ "show_media_when_bypassing";
+
+ private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not face unlock requires attention. This is a cached value, the source of
* truth is obtained through the HAL.
* @hide
@@ -8959,10 +8979,12 @@
DOZE_PICK_UP_GESTURE,
DOZE_DOUBLE_TAP_GESTURE,
DOZE_TAP_SCREEN_GESTURE,
- DOZE_WAKE_SCREEN_GESTURE,
+ DOZE_WAKE_LOCK_SCREEN_GESTURE,
+ DOZE_WAKE_DISPLAY_GESTURE,
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
+ SHOW_MEDIA_WHEN_BYPASSING,
FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
@@ -9131,13 +9153,15 @@
VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR);
- VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
+ VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR);
+ VALIDATORS.put(DOZE_WAKE_DISPLAY_GESTURE, DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR);
VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
+ VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index cb64ab1..17f07b5 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -21,6 +21,7 @@
import android.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.RecordingCanvas;
@@ -80,7 +81,8 @@
private static native long nativeGetNextFrameNumber(long nativeObject);
private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
private static native int nativeForceScopedDisconnect(long nativeObject);
- private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
+ private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject,
+ GraphicBuffer buffer, int colorSpaceId);
private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
@@ -699,18 +701,35 @@
}
/**
+ * Transfer ownership of buffer with a color space and present it on the Surface.
+ * The supported color spaces are SRGB and Display P3, other color spaces will be
+ * treated as SRGB.
+ * @hide
+ */
+ public void attachAndQueueBufferWithColorSpace(GraphicBuffer buffer, ColorSpace colorSpace) {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ if (colorSpace == null) {
+ colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+ }
+ int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer,
+ colorSpace.getId());
+ if (err != 0) {
+ throw new RuntimeException(
+ "Failed to attach and queue buffer to Surface (bad object?), "
+ + "native error: " + err);
+ }
+ }
+ }
+
+ /**
+ * Deprecated, use attachAndQueueBufferWithColorSpace instead.
* Transfer ownership of buffer and present it on the Surface.
+ * The color space of the buffer is treated as SRGB.
* @hide
*/
public void attachAndQueueBuffer(GraphicBuffer buffer) {
- synchronized (mLock) {
- checkNotReleasedLocked();
- int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
- if (err != 0) {
- throw new RuntimeException(
- "Failed to attach and queue buffer to Surface (bad object?)");
- }
- }
+ attachAndQueueBufferWithColorSpace(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
}
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d1ab7c99..522ad64 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1846,7 +1846,8 @@
final ScreenshotGraphicBuffer buffer = screenshotToBuffer(display, sourceCrop, width,
height, useIdentityTransform, rotation);
try {
- consumer.attachAndQueueBuffer(buffer.getGraphicBuffer());
+ consumer.attachAndQueueBufferWithColorSpace(buffer.getGraphicBuffer(),
+ buffer.getColorSpace());
} catch (RuntimeException e) {
Log.w(TAG, "Failed to take screenshot - " + e.getMessage());
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 882e6fd..2e9d881 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -184,7 +184,7 @@
boolean mIsTouchExplorationEnabled;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768939)
+ @UnsupportedAppUsage(trackingBug = 123768939L)
boolean mIsHighTextContrastEnabled;
AccessibilityPolicy mAccessibilityPolicy;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 564d972..86cec5e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -206,13 +206,13 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public ApplicationInfo mApplication;
/**
* The resource ID of the layout file. (Added to the parcel)
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private final int mLayoutId;
/**
@@ -224,13 +224,13 @@
* An array of actions to perform on the view tree once it has been
* inflated
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private ArrayList<Action> mActions;
/**
* Maps bitmaps to unique indicies to avoid Bitmap duplication.
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private BitmapCache mBitmapCache;
/**
@@ -252,7 +252,7 @@
* RemoteViews.
*/
private RemoteViews mLandscape = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private RemoteViews mPortrait = null;
@ApplyFlags
@@ -430,7 +430,7 @@
// Do nothing
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int mergeBehavior() {
return MERGE_REPLACE;
}
@@ -466,7 +466,7 @@
// Nothing to visit by default
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
int viewId;
}
@@ -499,7 +499,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void mergeRemoteViews(RemoteViews newRv) {
if (newRv == null) return;
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
@@ -690,7 +690,7 @@
return SET_PENDING_INTENT_TEMPLATE_TAG;
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
PendingIntent pendingIntentTemplate;
}
@@ -1138,7 +1138,7 @@
private static class BitmapCache {
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
ArrayList<Bitmap> mBitmaps;
int mBitmapMemory = -1;
@@ -1190,9 +1190,9 @@
private class BitmapReflectionAction extends Action {
int bitmapId;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
Bitmap bitmap;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
String methodName;
BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) {
@@ -1258,10 +1258,10 @@
static final int COLOR_STATE_LIST = 15;
static final int ICON = 16;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
String methodName;
int type;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
Object value;
ReflectionAction(int viewId, String methodName, int type, Object value) {
@@ -1554,7 +1554,7 @@
* ViewGroup methods that are related to adding Views.
*/
private class ViewGroupActionAdd extends Action {
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private RemoteViews mNestedViews;
private int mIndex;
@@ -2469,7 +2469,7 @@
* Returns an estimate of the bitmap heap memory usage for this RemoteViews.
*/
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int estimateMemoryUsage() {
return mBitmapCache.getBitmapMemory();
}
@@ -2517,7 +2517,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void addView(int viewId, RemoteViews nestedView, int index) {
addAction(new ViewGroupActionAdd(viewId, nestedView, index));
}
@@ -2994,7 +2994,8 @@
* @hide
* @deprecated this appears to have no users outside of UnsupportedAppUsage?
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
+ @Deprecated
public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) {
addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount));
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7cc8128..f905ea2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -29,7 +29,6 @@
import android.app.VoiceInteractor.PickOptionRequest;
import android.app.VoiceInteractor.PickOptionRequest.Option;
import android.app.VoiceInteractor.Prompt;
-import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -111,7 +110,6 @@
protected AbsListView mAdapterView;
private Button mAlwaysButton;
private Button mOnceButton;
- private Button mSettingsButton;
protected View mProfileView;
private int mIconDpi;
private int mLastSelected = AbsListView.INVALID_POSITION;
@@ -146,6 +144,10 @@
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
+ private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
+ private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+ private static final String OPEN_LINKS_COMPONENT_KEY = "app_link_state";
+
private final PackageMonitor mPackageMonitor = createPackageMonitor();
/**
@@ -196,9 +198,13 @@
// titles for layout that deals with http(s) intents
public static final int BROWSABLE_TITLE_RES =
- com.android.internal.R.string.whichGiveAccessToApplication;
- public static final int BROWSABLE_NAMED_TITLE_RES =
- com.android.internal.R.string.whichGiveAccessToApplicationNamed;
+ com.android.internal.R.string.whichOpenLinksWith;
+ public static final int BROWSABLE_HOST_TITLE_RES =
+ com.android.internal.R.string.whichOpenHostLinksWith;
+ public static final int BROWSABLE_HOST_APP_TITLE_RES =
+ com.android.internal.R.string.whichOpenHostLinksWithApp;
+ public static final int BROWSABLE_APP_TITLE_RES =
+ com.android.internal.R.string.whichOpenLinksWithApp;
public final String action;
public final int titleRes;
@@ -322,9 +328,7 @@
? false
: isHttpSchemeAndViewAction(getTargetIntent());
- // We don't want to support Always Use if browsable layout is being used,
- // as to mitigate Intent Capturing vulnerability
- mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;
+ mSupportsAlwaysUseOption = supportsAlwaysUseOption;
if (configureContentView(mIntents, initialIntents, rList)) {
return;
@@ -554,10 +558,21 @@
} else if (isHttpSchemeAndViewAction(intent)) {
// If the Intent's scheme is http(s) then we need to warn the user that
// they're giving access for the activity to open URLs from this specific host
- return named
- ? getString(ActionTitle.BROWSABLE_NAMED_TITLE_RES, intent.getData().getHost(),
- mAdapter.getFilteredItem().getDisplayLabel())
- : getString(ActionTitle.BROWSABLE_TITLE_RES, intent.getData().getHost());
+ String dialogTitle = null;
+ if (named && !mUseLayoutForBrowsables) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_APP_TITLE_RES,
+ mAdapter.getFilteredItem().getDisplayLabel());
+ } else if (named && mUseLayoutForBrowsables) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_HOST_APP_TITLE_RES,
+ intent.getData().getHost(),
+ mAdapter.getFilteredItem().getDisplayLabel());
+ } else if (mAdapter.areAllTargetsBrowsers()) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES);
+ } else {
+ dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES,
+ intent.getData().getHost());
+ }
+ return dialogTitle;
} else {
return named
? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
@@ -856,6 +871,13 @@
} else {
enabled = true;
}
+ if (mUseLayoutForBrowsables && !ri.handleAllWebDataURI) {
+ mAlwaysButton.setText(getResources()
+ .getString(R.string.activity_resolver_set_always));
+ } else {
+ mAlwaysButton.setText(getResources()
+ .getString(R.string.activity_resolver_use_always));
+ }
}
mAlwaysButton.setEnabled(enabled);
}
@@ -866,26 +888,29 @@
? mAdapter.getFilteredPosition()
: mAdapterView.getCheckedItemPosition();
boolean hasIndexBeenFiltered = !mAdapter.hasFilteredItem();
- if (id == R.id.button_app_settings) {
- showSettingsForSelected(which, hasIndexBeenFiltered);
+ ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+ if (!ri.handleAllWebDataURI && id == R.id.button_always) {
+ showSettingsForSelected(ri);
} else {
startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
}
}
- private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
- ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+ private void showSettingsForSelected(ResolveInfo ri) {
Intent intent = new Intent();
- // For browsers, we open the Default Browser page
+
+ final String packageName = ri.activityInfo.packageName;
+ Bundle showFragmentArgs = new Bundle();
+ showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY);
+ showFragmentArgs.putString("package", packageName);
+
// For regular apps, we open the Open by Default page
- if (ri.handleAllWebDataURI) {
- intent.setAction(Intent.ACTION_MANAGE_DEFAULT_APP)
- .putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_BROWSER);
- } else {
- intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
- .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- }
+ intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
+ .setData(Uri.fromParts("package", packageName, null))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+ .putExtra(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY)
+ .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
+
startActivity(intent);
}
@@ -1332,41 +1357,15 @@
R.dimen.resolver_button_bar_spacing) + inset);
mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
- mSettingsButton = (Button) buttonLayout.findViewById(R.id.button_app_settings);
mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
- if (mUseLayoutForBrowsables) {
- resetSettingsOrOnceButtonBar();
- } else {
- resetAlwaysOrOnceButtonBar();
- }
+ resetAlwaysOrOnceButtonBar();
} else {
Log.e(TAG, "Layout unexpectedly does not have a button bar");
}
}
- private void resetSettingsOrOnceButtonBar() {
- //unsetting always button
- mAlwaysButton.setVisibility(View.GONE);
-
- // When the items load in, if an item was already selected,
- // enable the buttons
- if (mAdapterView != null
- && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
- mSettingsButton.setEnabled(true);
- mOnceButton.setEnabled(true);
- }
- }
-
private void resetAlwaysOrOnceButtonBar() {
- // This check needs to be made because layout with default
- // doesn't have a settings button
- if (mSettingsButton != null) {
- //unsetting always button
- mSettingsButton.setVisibility(View.GONE);
- mSettingsButton = null;
- }
-
if (useLayoutWithDefault()
&& mAdapter.getFilteredPosition() != ListView.INVALID_POSITION) {
setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
@@ -1626,6 +1625,7 @@
private DisplayResolveInfo mOtherProfile;
private ResolverListController mResolverListController;
private int mPlaceholderCount;
+ private boolean mAllTargetsAreBrowsers = false;
protected final LayoutInflater mInflater;
@@ -1701,6 +1701,14 @@
}
/**
+ * @return true if all items in the display list are defined as browsers by
+ * ResolveInfo.handleAllWebDataURI
+ */
+ public boolean areAllTargetsBrowsers() {
+ return mAllTargetsAreBrowsers;
+ }
+
+ /**
* Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
* to complete.
*
@@ -1712,6 +1720,7 @@
mOtherProfile = null;
mLastChosen = null;
mLastChosenPosition = -1;
+ mAllTargetsAreBrowsers = false;
mDisplayList.clear();
if (mBaseResolveList != null) {
currentResolveList = mUnfilteredResolveList = new ArrayList<>();
@@ -1812,6 +1821,8 @@
private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
int N;
if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
+ mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
+
// First put the initial items at the top.
if (mInitialIntents != null) {
for (int i = 0; i < mInitialIntents.length; i++) {
@@ -1841,6 +1852,8 @@
ri.noResourceId = true;
ri.icon = 0;
}
+ mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(getPackageManager()), null, ii));
}
@@ -1850,6 +1863,8 @@
for (ResolvedComponentInfo rci : sortedComponents) {
final ResolveInfo ri = rci.getResolveInfoAt(0);
if (ri != null) {
+ mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
ResolveInfoPresentationGetter pg = makePresentationGetter(ri);
addResolveInfoWithAlternates(rci, pg.getSubLabel(), pg.getLabel());
}
@@ -2152,14 +2167,8 @@
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (!useLayoutWithDefault()
&& (!hasValidSelection || mLastSelected != checkedPos)
- && (mAlwaysButton != null || mSettingsButton != null)) {
- if (mSettingsButton != null) {
- // this implies that the layout for browsables is being used
- mSettingsButton.setEnabled(true);
- } else {
- // this implies that mAlwaysButton != null
- setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
- }
+ && mAlwaysButton != null) {
+ setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
mAdapterView.smoothScrollToPosition(checkedPos);
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 64291de..d00108e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -16,8 +16,6 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuPresenter.Callback;
-
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,14 +24,14 @@
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.Build;
-import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow.OnDismissListener;
+import com.android.internal.view.menu.MenuPresenter.Callback;
+
/**
* Presents a menu as a small, simple popup anchored to another view.
*/
@@ -114,7 +112,7 @@
* @param forceShowIcon {@code true} to force icons to be shown, or
* {@code false} for icons to be optionally shown
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void setForceShowIcon(boolean forceShowIcon) {
mForceShowIcon = forceShowIcon;
if (mPopup != null) {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5611cc4..dad4a28 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -899,20 +899,16 @@
addOption("-Ximage-compiler-option");
addOption("--compiler-filter=speed-profile");
} else {
- // Make sure there is a preloaded-classes file.
- if (!hasFile("/system/etc/preloaded-classes")) {
- ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
- strerror(errno));
- return -1;
- }
- addOption("-Ximage-compiler-option");
- addOption("--image-classes=/system/etc/preloaded-classes");
+ ALOGE("Missing boot-image.prof file, /system/etc/boot-image.prof not found: %s\n",
+ strerror(errno));
+ return -1;
+ }
- // If there is a dirty-image-objects file, push it.
- if (hasFile("/system/etc/dirty-image-objects")) {
- addOption("-Ximage-compiler-option");
- addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
- }
+
+ // If there is a dirty-image-objects file, push it.
+ if (hasFile("/system/etc/dirty-image-objects")) {
+ addOption("-Ximage-compiler-option");
+ addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
}
property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 7c42994..0d95f99 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -74,6 +74,24 @@
jfieldID bottom;
} gRectClassInfo;
+class JNamedColorSpace {
+public:
+ // ColorSpace.Named.SRGB.ordinal() = 0;
+ static constexpr jint SRGB = 0;
+
+ // ColorSpace.Named.DISPLAY_P3.ordinal() = 7;
+ static constexpr jint DISPLAY_P3 = 7;
+};
+
+constexpr ui::Dataspace fromNamedColorSpaceValueToDataspace(const jint colorSpace) {
+ switch (colorSpace) {
+ case JNamedColorSpace::DISPLAY_P3:
+ return ui::Dataspace::DISPLAY_P3;
+ default:
+ return ui::Dataspace::V0_SRGB;
+ }
+}
+
// ----------------------------------------------------------------------------
// this is just a pointer we use to pass to inc/decStrong
@@ -411,11 +429,12 @@
return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
}
-static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeObject,
- jobject graphicBuffer) {
+static jint nativeAttachAndQueueBufferWithColorSpace(JNIEnv *env, jclass clazz, jlong nativeObject,
+ jobject graphicBuffer, jint colorSpaceId) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
- int err = Surface::attachAndQueueBuffer(surface, bp);
+ int err = Surface::attachAndQueueBufferWithDataspace(surface, bp,
+ fromNamedColorSpaceValueToDataspace(colorSpaceId));
return err;
}
@@ -517,7 +536,8 @@
{"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
{"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
{"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
- {"nativeAttachAndQueueBuffer", "(JLandroid/graphics/GraphicBuffer;)I", (void*)nativeAttachAndQueueBuffer},
+ {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/graphics/GraphicBuffer;I)I",
+ (void*)nativeAttachAndQueueBufferWithColorSpace},
{"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
{"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index d06e1a6..7e26952 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -497,8 +497,7 @@
}
optional Telephony telephony = 38;
- optional string url_legal = 39;
- optional string url_legal_android_privacy = 40;
+ reserved 39, 40; // Removed url_legal* props
message Vendor {
optional string build_date = 1;
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index aeaccfd..1dd4207 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -129,18 +129,6 @@
android:enabled="false"
android:text="@string/activity_resolver_use_always"
android:onClick="onButtonClick" />
-
- <Button
- android:id="@+id/button_app_settings"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_app_settings"
- android:onClick="onButtonClick" />
</LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values-mcc313-mnc100/config.xml b/core/res/res/values-mcc313-mnc100/config.xml
new file mode 100644
index 0000000..ccd03f1
--- /dev/null
+++ b/core/res/res/values-mcc313-mnc100/config.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array translatable="false" name="config_twoDigitNumberPattern">
+ <item>"0"</item>
+ <item>"00"</item>
+ <item>"*0"</item>
+ <item>"*1"</item>
+ <item>"*2"</item>
+ <item>"*3"</item>
+ <item>"*4"</item>
+ <item>"*5"</item>
+ <item>"*6"</item>
+ <item>"*7"</item>
+ <item>"*8"</item>
+ <item>"*9"</item>
+ <item>"#0"</item>
+ <item>"#1"</item>
+ <item>"#2"</item>
+ <item>"#3"</item>
+ <item>"#4"</item>
+ <item>"#5"</item>
+ <item>"#6"</item>
+ <item>"#7"</item>
+ <item>"#8"</item>
+ <item>"#9"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 597f504..6fd855c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3077,12 +3077,20 @@
<string name="whichViewApplicationNamed">Open with %1$s</string>
<!-- Label for a link to a intent resolver dialog to view something -->
<string name="whichViewApplicationLabel">Open</string>
- <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
+ <!-- Title of intent resolver dialog when selecting a browser/application that opens specific URIs
[CHAR LIMIT=128]. -->
- <string name="whichGiveAccessToApplication">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+ <string name="whichOpenHostLinksWith">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+ <!-- Title of intent resolver dialog when selecting a browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenLinksWith">Open links with</string>
+ <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenLinksWithApp">Open links with <xliff:g id="application" example="Chrome">%1$s</xliff:g></string>
+ <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenHostLinksWithApp">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Chrome">%2$s</xliff:g></string>
<!-- Title of intent resolver dialog when selecting a viewer application that opens URI
and a previously used application is known [CHAR LIMIT=128]. -->
- <string name="whichGiveAccessToApplicationNamed">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Gmail">%2$s</xliff:g></string>
<!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=18] -->
<string name="whichGiveAccessToApplicationLabel">Give access</string>
<!-- Title of intent resolver dialog when selecting an editor application to run. -->
@@ -4215,6 +4223,10 @@
<string name="activity_resolver_use_always">Always</string>
<!-- Title for a button to choose the currently selected activity
+ as the default in the activity resolver. [CHAR LIMIT=50] -->
+ <string name="activity_resolver_set_always">Set to always open</string>
+
+ <!-- Title for a button to choose the currently selected activity
from the activity resolver to use just this once. [CHAR LIMIT=25] -->
<string name="activity_resolver_use_once">Just once</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 05c0114..5ca77f9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2242,7 +2242,6 @@
<java-symbol type="id" name="resolver_list" />
<java-symbol type="id" name="button_once" />
<java-symbol type="id" name="button_always" />
- <java-symbol type="id" name="button_app_settings" />
<java-symbol type="integer" name="config_globalActionsKeyTimeout" />
<java-symbol type="integer" name="config_screenshotChordKeyTimeout" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -2624,14 +2623,17 @@
<java-symbol type="bool" name="config_use_voip_mode_for_ims" />
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
- <java-symbol type="string" name="activity_resolver_app_settings" />
+ <java-symbol type="string" name="activity_resolver_set_always" />
+ <java-symbol type="string" name="activity_resolver_use_always" />
<java-symbol type="string" name="whichApplicationNamed" />
<java-symbol type="string" name="whichApplicationLabel" />
<java-symbol type="string" name="whichViewApplication" />
<java-symbol type="string" name="whichViewApplicationNamed" />
<java-symbol type="string" name="whichViewApplicationLabel" />
- <java-symbol type="string" name="whichGiveAccessToApplication" />
- <java-symbol type="string" name="whichGiveAccessToApplicationNamed" />
+ <java-symbol type="string" name="whichOpenHostLinksWith" />
+ <java-symbol type="string" name="whichOpenHostLinksWithApp" />
+ <java-symbol type="string" name="whichOpenLinksWith" />
+ <java-symbol type="string" name="whichOpenLinksWithApp" />
<java-symbol type="string" name="whichGiveAccessToApplicationLabel" />
<java-symbol type="string" name="whichEditApplication" />
<java-symbol type="string" name="whichEditApplicationNamed" />
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
new file mode 100644
index 0000000..f13885e
--- /dev/null
+++ b/core/tests/utiltests/Android.bp
@@ -0,0 +1,38 @@
+//########################################################################
+// Build FrameworksUtilTests package
+//########################################################################
+
+android_test {
+ name: "FrameworksUtilTests",
+
+ // We only want this apk build for tests.
+
+ // Include all test java files.
+ srcs: ["src/**/*.java"] + ["src/android/util/IRemoteMemoryIntArray.aidl"],
+
+ jni_libs: [
+ "libmemoryintarraytest",
+ "libcutils",
+ "libc++",
+ ],
+
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "mockito-target-minus-junit4",
+ "androidx.test.ext.junit",
+ ],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+
+ platform_apis: true,
+
+ certificate: "platform",
+
+ test_suites: ["device-tests"],
+
+}
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
deleted file mode 100644
index 9ef73e9..0000000
--- a/core/tests/utiltests/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#########################################################################
-# Build FrameworksUtilTests package
-#########################################################################
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += src/android/util/IRemoteMemoryIntArray.aidl
-
-LOCAL_JNI_SHARED_LIBRARIES := libmemoryintarraytest libcutils libc++
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- frameworks-base-testutils \
- mockito-target-minus-junit4 \
- androidx.test.ext.junit
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_PACKAGE_NAME := FrameworksUtilTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 4f64da7..bbffb35 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -27,15 +27,6 @@
namespace uirenderer {
namespace renderthread {
-static bool IsTransformSupported(int transform) {
- // For now, only support pure rotations, not flip or flip-and-rotate, until we have
- // more time to test them and build sample code. As far as I know we never actually
- // use anything besides pure rotations anyway.
- return transform == 0 || transform == NATIVE_WINDOW_TRANSFORM_ROT_90 ||
- transform == NATIVE_WINDOW_TRANSFORM_ROT_180 ||
- transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
-}
-
static int InvertTransform(int transform) {
switch (transform) {
case NATIVE_WINDOW_TRANSFORM_ROT_90:
@@ -68,28 +59,6 @@
return SkMatrix::I();
}
-void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
- const SkISize& maxSize) {
- SkISize& windowSize = windowInfo->size;
-
- // clamp width & height to handle currentExtent of -1 and protect us from broken hints
- if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width() ||
- windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
- int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
- int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
- ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]", windowSize.width(),
- windowSize.height(), width, height);
- windowSize.set(width, height);
- }
-
- windowInfo->actualSize = windowSize;
- if (windowInfo->transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- windowInfo->actualSize.set(windowSize.height(), windowSize.width());
- }
-
- windowInfo->preTransform = GetPreTransformMatrix(windowInfo->size, windowInfo->transform);
-}
-
static bool ConnectAndSetWindowDefaults(ANativeWindow* window) {
ATRACE_CALL();
@@ -125,6 +94,24 @@
return false;
}
+ // Let consumer drive the size of the buffers.
+ err = native_window_set_buffers_dimensions(window, 0, 0);
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_dimensions(0,0) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ // Enable auto prerotation, so when buffer size is driven by the consumer
+ // and the transform hint specifies a 90 or 270 degree rotation, the width
+ // and height used for buffer pre-allocation and dequeueBuffer will be
+ // additionally swapped.
+ err = native_window_set_auto_prerotation(window, true);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_auto_prerotation failed: %s (%d)",
+ strerror(-err), err);
+ return false;
+ }
+
return true;
}
@@ -132,10 +119,6 @@
SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
GrContext* grContext, const VulkanManager& vkManager,
uint32_t extraBuffers) {
- // TODO(http://b/134182502)
- const SkISize minSize = SkISize::Make(1, 1);
- const SkISize maxSize = SkISize::Make(4096, 4096);
-
// Connect and set native window to default configurations.
if (!ConnectAndSetWindowDefaults(window)) {
return nullptr;
@@ -144,7 +127,7 @@
// Initialize WindowInfo struct.
WindowInfo windowInfo;
if (!InitializeWindowInfoStruct(window, colorMode, colorType, colorSpace, vkManager,
- extraBuffers, minSize, maxSize, &windowInfo)) {
+ extraBuffers, &windowInfo)) {
return nullptr;
}
@@ -153,15 +136,14 @@
return nullptr;
}
- return new VulkanSurface(window, windowInfo, minSize, maxSize, grContext);
+ return new VulkanSurface(window, windowInfo, grContext);
}
bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const VulkanManager& vkManager,
- uint32_t extraBuffers, const SkISize& minSize,
- const SkISize& maxSize, WindowInfo* outWindowInfo) {
+ uint32_t extraBuffers, WindowInfo* outWindowInfo) {
ATRACE_CALL();
int width, height;
@@ -185,7 +167,13 @@
}
outWindowInfo->transform = query_value;
- ComputeWindowSizeAndTransform(outWindowInfo, minSize, maxSize);
+ outWindowInfo->actualSize = outWindowInfo->size;
+ if (outWindowInfo->transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ outWindowInfo->actualSize.set(outWindowInfo->size.height(), outWindowInfo->size.width());
+ }
+
+ outWindowInfo->preTransform =
+ GetPreTransformMatrix(outWindowInfo->size, outWindowInfo->transform);
err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
if (err != 0 || query_value < 0) {
@@ -290,15 +278,6 @@
return false;
}
- const SkISize& size = windowInfo.actualSize;
- err = native_window_set_buffers_dimensions(window, size.width(), size.height());
- if (err != 0) {
- ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
- "failed: %s (%d)",
- size.width(), size.height(), strerror(-err), err);
- return false;
- }
-
// native_window_set_buffers_transform() expects the transform the app is requesting that
// the compositor perform during composition. With native windows, pre-transform works by
// rendering with the same transform the compositor is applying (as in Vulkan), but
@@ -331,12 +310,8 @@
}
VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
- SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
- : mNativeWindow(window)
- , mWindowInfo(windowInfo)
- , mGrContext(grContext)
- , mMinWindowSize(minWindowSize)
- , mMaxWindowSize(maxWindowSize) {}
+ GrContext* grContext)
+ : mNativeWindow(window), mWindowInfo(windowInfo), mGrContext(grContext) {}
VulkanSurface::~VulkanSurface() {
releaseBuffers();
@@ -379,58 +354,51 @@
// value at the end of the function if everything dequeued correctly.
mCurrentBufferInfo = nullptr;
- // check if the native window has been resized or rotated and update accordingly
- SkISize newSize = SkISize::MakeEmpty();
+ // Query the transform hint synced from the initial Surface connect or last queueBuffer. The
+ // auto prerotation on the buffer is based on the same transform hint in use by the producer.
int transformHint = 0;
- mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
- mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &newSize.fHeight);
- mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
- if (newSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
- WindowInfo newWindowInfo = mWindowInfo;
- newWindowInfo.size = newSize;
- newWindowInfo.transform = IsTransformSupported(transformHint) ? transformHint : 0;
- ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+ int err =
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
- int err = 0;
- if (newWindowInfo.actualSize != mWindowInfo.actualSize) {
- // reset the native buffers and update the window
- err = native_window_set_buffers_dimensions(mNativeWindow.get(),
- newWindowInfo.actualSize.width(),
- newWindowInfo.actualSize.height());
- if (err != 0) {
- ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
- newWindowInfo.actualSize.width(), newWindowInfo.actualSize.height(),
- strerror(-err), err);
- return nullptr;
- }
- // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
- // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
- releaseBuffers();
- // TODO should we ask the nativewindow to allocate buffers?
- }
-
- if (newWindowInfo.transform != mWindowInfo.transform) {
- err = native_window_set_buffers_transform(mNativeWindow.get(),
- InvertTransform(newWindowInfo.transform));
- if (err != 0) {
- ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
- newWindowInfo.transform, strerror(-err), err);
- newWindowInfo.transform = mWindowInfo.transform;
- ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
- }
- }
-
- mWindowInfo = newWindowInfo;
- }
-
+ // Since auto pre-rotation is enabled, dequeueBuffer to get the consumer driven buffer size
+ // from ANativeWindowBuffer.
ANativeWindowBuffer* buffer;
int fence_fd;
- int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
+ err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
if (err != 0) {
ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
return nullptr;
}
+ SkISize actualSize = SkISize::Make(buffer->width, buffer->height);
+ if (actualSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
+ if (actualSize != mWindowInfo.actualSize) {
+ // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
+ // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
+ mWindowInfo.actualSize = actualSize;
+ releaseBuffers();
+ }
+
+ if (transformHint != mWindowInfo.transform) {
+ err = native_window_set_buffers_transform(mNativeWindow.get(),
+ InvertTransform(transformHint));
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", transformHint,
+ strerror(-err), err);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ return nullptr;
+ }
+ mWindowInfo.transform = transformHint;
+ }
+
+ mWindowInfo.size = actualSize;
+ if (mWindowInfo.transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ mWindowInfo.size.set(actualSize.height(), actualSize.width());
+ }
+
+ mWindowInfo.preTransform = GetPreTransformMatrix(mWindowInfo.size, mWindowInfo.transform);
+ }
+
uint32_t idx;
for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
if (mNativeBuffers[idx].buffer.get() == buffer) {
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 54007e7..5fa860a 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -101,16 +101,12 @@
SkMatrix preTransform;
};
- VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, SkISize minWindowSize,
- SkISize maxWindowSize, GrContext* grContext);
+ VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrContext* grContext);
static bool InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
const VulkanManager& vkManager, uint32_t extraBuffers,
- const SkISize& minSize, const SkISize& maxSize,
WindowInfo* outWindowInfo);
static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
- static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
- const SkISize& maxSize);
void releaseBuffers();
// TODO: Just use a vector?
@@ -122,11 +118,8 @@
uint32_t mPresentCount = 0;
NativeBufferInfo* mCurrentBufferInfo = nullptr;
-
- const SkISize mMinWindowSize;
- const SkISize mMaxWindowSize;
};
} /* namespace renderthread */
} /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 8238b8c..7e3f2f8 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -19,7 +19,9 @@
* the playback of the media app.
* @param extra Extras returned by the media service.
*/
+ @UnsupportedAppUsage
void onConnect(String root, in MediaSession.Token session, in Bundle extras);
+ @UnsupportedAppUsage
void onConnectFailed();
void onLoadChildren(String mediaId, in ParceledListSlice list);
void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list,
diff --git a/packages/SystemUI/res/anim/lock_in.xml b/packages/SystemUI/res/anim/lock_in.xml
deleted file mode 100644
index c7014e8..0000000
--- a/packages/SystemUI/res/anim/lock_in.xml
+++ /dev/null
@@ -1,227 +0,0 @@
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="42dp" android:width="32dp" android:viewportHeight="42"
- android:viewportWidth="32">
- <group android:name="_R_G">
- <group android:name="_R_G_L_2_G" android:translateX="1.6669999999999998"
- android:translateY="11.992999999999999" android:pivotX="14.333"
- android:pivotY="13" android:scaleX="0" android:scaleY="0">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#ffffff"
- android:strokeLineCap="round" android:strokeLineJoin="round"
- android:strokeWidth="2" android:strokeAlpha="1"
- android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "/>
- </group>
- <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="1.6669999999999998"
- android:translateY="11.992999999999999" android:pivotX="14.333"
- android:pivotY="13" android:scaleX="0" android:scaleY="0">
- <group android:name="_R_G_L_1_G" android:translateX="11.583"
- android:translateY="10.257">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c "/>
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="1.6669999999999998"
- android:translateY="11.992999999999999" android:pivotX="14.333"
- android:pivotY="13" android:scaleX="0" android:scaleY="0">
- <group android:name="_R_G_L_0_G_T_1" android:translateX="14.333"
- android:translateY="3.172">
- <group android:name="_R_G_L_0_G" android:translateX="-9.667"
- android:translateY="-9.667">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff"
- android:strokeLineCap="round" android:strokeLineJoin="round"
- android:strokeWidth="2" android:strokeAlpha="1"
- android:trimPathStart="0.14" android:trimPathEnd="0.89"
- android:trimPathOffset="0"
- android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "/>
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G_N_4_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="trimPathStart" android:duration="50"
- android:startOffset="0" android:valueFrom="0.14"
- android:valueTo="0.14" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="trimPathStart" android:duration="67"
- android:startOffset="50" android:valueFrom="0.14"
- android:valueTo="0" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="trimPathEnd" android:duration="50"
- android:startOffset="0" android:valueFrom="0.89"
- android:valueTo="0.89" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="trimPathEnd" android:duration="67"
- android:startOffset="50" android:valueFrom="0.89"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_T_1">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="translateY" android:duration="150"
- android:startOffset="0" android:valueFrom="3.172"
- android:valueTo="0.34" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.23,-0.46 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_4_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.02"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="translateX" android:duration="717"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1"
- android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_circular.xml b/packages/SystemUI/res/anim/lock_in_circular.xml
deleted file mode 100644
index d1e98db..0000000
--- a/packages/SystemUI/res/anim/lock_in_circular.xml
+++ /dev/null
@@ -1,327 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
- xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <aapt:attr name="android:drawable" >
- <vector
- android:height="32dp"
- android:viewportHeight="32"
- android:viewportWidth="32"
- android:width="32dp" >
- <group android:name="_R_G" >
- <group
- android:name="_R_G_L_2_G"
- android:pivotX="9.583"
- android:pivotY="8.916"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="6.416"
- android:translateY="10.416999999999998" >
- <path
- android:name="_R_G_L_2_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="#ffffff"
- android:fillType="nonZero"
- android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
- </group>
- <group
- android:name="_R_G_L_1_G_N_3_T_0"
- android:pivotX="9.583"
- android:pivotY="8.916"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="6.416"
- android:translateY="10.416999999999998" >
- <group
- android:name="_R_G_L_1_G"
- android:translateX="7.334"
- android:translateY="5.333" >
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="#ffffff"
- android:fillType="nonZero"
- android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
- <path
- android:name="_R_G_L_1_G_D_1_P_0"
- android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="1.5" />
- </group>
- </group>
- <group
- android:name="_R_G_L_0_G_N_3_T_0"
- android:pivotX="9.583"
- android:pivotY="8.916"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="6.416"
- android:translateY="10.416999999999998" >
- <group
- android:name="_R_G_L_0_G_T_1"
- android:translateX="9.583"
- android:translateY="-0.861" >
- <group
- android:name="_R_G_L_0_G"
- android:translateX="-8.083"
- android:translateY="-8.173" >
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="1.5"
- android:trimPathEnd="0.9"
- android:trimPathOffset="0"
- android:trimPathStart="0.15" />
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
-
- <target android:name="_R_G_L_2_G" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G_N_3_T_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathStart"
- android:startOffset="0"
- android:valueFrom="0.15"
- android:valueTo="0.15"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathStart"
- android:startOffset="50"
- android:valueFrom="0.15"
- android:valueTo="0"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0.9"
- android:valueTo="0.9"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathEnd"
- android:startOffset="50"
- android:valueFrom="0.9"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_T_1" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="150"
- android:pathData="M 9.583,-0.861C 9.583,-1.32784640645981 9.583,-3.19515359354019 9.583,-3.662"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_3_T_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="717"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_filled.xml b/packages/SystemUI/res/anim/lock_in_filled.xml
deleted file mode 100644
index 4cde38d..0000000
--- a/packages/SystemUI/res/anim/lock_in_filled.xml
+++ /dev/null
@@ -1,190 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
- xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <aapt:attr name="android:drawable" >
- <vector
- android:height="32dp"
- android:viewportHeight="32"
- android:viewportWidth="32"
- android:width="32dp" >
- <group android:name="_R_G" >
- <group
- android:name="_R_G_L_1_G"
- android:pivotX="10.917"
- android:pivotY="9.583"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="5.083"
- android:translateY="10.417" >
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="#ffffff"
- android:fillType="nonZero"
- android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
- </group>
- <group
- android:name="_R_G_L_0_G_N_2_T_0"
- android:pivotX="10.917"
- android:pivotY="9.583"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="5.083"
- android:translateY="10.417" >
- <group
- android:name="_R_G_L_0_G_T_1"
- android:translateX="10.917"
- android:translateY="0.579" >
- <group
- android:name="_R_G_L_0_G"
- android:translateX="-9"
- android:translateY="-9" >
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M13 13 C13,13 13,9 13,9 C13,6.79 11.21,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2" />
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
-
- <target android:name="_R_G_L_1_G" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_T_1" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="150"
- android:pathData="M 10.917,0.579C 10.917,-0.14248990631104008 10.917,-3.02851009368896 10.917,-3.75"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_2_T_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="717"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_rounded.xml b/packages/SystemUI/res/anim/lock_in_rounded.xml
deleted file mode 100644
index 7c8cf9d..0000000
--- a/packages/SystemUI/res/anim/lock_in_rounded.xml
+++ /dev/null
@@ -1,336 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
- xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <aapt:attr name="android:drawable" >
- <vector
- android:height="38dp"
- android:viewportHeight="38"
- android:viewportWidth="32"
- android:width="32dp" >
- <group android:name="_R_G" >
- <group
- android:name="_R_G_L_2_G"
- android:pivotX="14.667"
- android:pivotY="12.667"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="1.3330000000000002"
- android:translateY="10.333" >
- <path
- android:name="_R_G_L_2_G_D_0_P_0"
- android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="1.5" />
- </group>
- <group
- android:name="_R_G_L_1_G_N_3_T_0"
- android:pivotX="14.667"
- android:pivotY="12.667"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="1.3330000000000002"
- android:translateY="10.333" >
- <group
- android:name="_R_G_L_1_G"
- android:translateX="12.416"
- android:translateY="10.417" >
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="#ffffff"
- android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_3_T_0_M" >
- <group
- android:name="_R_G_L_0_G_N_3_T_0"
- android:pivotX="14.667"
- android:pivotY="12.667"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="1.3330000000000002"
- android:translateY="10.333" >
- <group
- android:name="_R_G_L_0_G_T_1"
- android:translateX="14.666"
- android:translateY="3.769" >
- <group
- android:name="_R_G_L_0_G"
- android:translateX="-9.333"
- android:translateY="-9.713" >
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="1.5"
- android:trimPathEnd="0.9"
- android:trimPathOffset="0"
- android:trimPathStart="0.14" />
- </group>
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
-
- <target android:name="_R_G_L_2_G" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G_N_3_T_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathStart"
- android:startOffset="0"
- android:valueFrom="0.14"
- android:valueTo="0.14"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathStart"
- android:startOffset="50"
- android:valueFrom="0.14"
- android:valueTo="0"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0.9"
- android:valueTo="0.9"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathEnd"
- android:startOffset="50"
- android:valueFrom="0.9"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_T_1" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="150"
- android:pathData="M 14.666,3.769C 14.666,3.18868762874603 14.666,0.8673123712539699 14.666,0.287"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_3_T_0" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType" >
- <aapt:attr name="android:interpolator" >
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_3_T_0_M" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="0"
- android:propertyName="scaleX"
- android:startOffset="50"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group" >
- <aapt:attr name="android:animation" >
- <set android:ordering="together" >
- <objectAnimator
- android:duration="717"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 0481310..ee0bd14 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -19,46 +19,47 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <!-- Menu layout -->
- <FrameLayout
- android:id="@+id/menu_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:forceHasOverlappingRendering="false">
+ <!-- Menu layout -->
+ <FrameLayout
+ android:id="@+id/menu_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:forceHasOverlappingRendering="false"
+ android:accessibilityTraversalAfter="@id/dismiss">
- <!-- The margins for this container is calculated in the code depending on whether the
- actions_container is visible. -->
- <FrameLayout
- android:id="@+id/expand_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageButton
- android:id="@+id/expand_button"
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:layout_gravity="center"
- android:contentDescription="@string/pip_phone_expand"
- android:padding="10dp"
- android:src="@drawable/pip_expand"
- android:background="?android:selectableItemBackgroundBorderless" />
- </FrameLayout>
+ <!-- The margins for this container is calculated in the code depending on whether the
+ actions_container is visible. -->
+ <FrameLayout
+ android:id="@+id/expand_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <ImageButton
+ android:id="@+id/expand_button"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/pip_phone_expand"
+ android:padding="10dp"
+ android:src="@drawable/pip_expand"
+ android:background="?android:selectableItemBackgroundBorderless" />
+ </FrameLayout>
- <FrameLayout
- android:id="@+id/actions_container"
- android:layout_width="match_parent"
- android:layout_height="@dimen/pip_action_size"
- android:layout_gravity="bottom"
- android:visibility="invisible">
- <LinearLayout
- android:id="@+id/actions_group"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal"
- android:orientation="horizontal"
- android:divider="@android:color/transparent"
- android:showDividers="middle" />
- </FrameLayout>
- </FrameLayout>
+ <FrameLayout
+ android:id="@+id/actions_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/pip_action_size"
+ android:layout_gravity="bottom"
+ android:visibility="invisible">
+ <LinearLayout
+ android:id="@+id/actions_group"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal"
+ android:divider="@android:color/transparent"
+ android:showDividers="middle" />
+ </FrameLayout>
+ </FrameLayout>
<ImageButton
android:id="@+id/settings"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index bb7614a..a549870 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -141,6 +141,9 @@
<!-- The number of milliseconds before the heads up notification auto-dismisses. -->
<integer name="heads_up_notification_decay">5000</integer>
+ <!-- The number of milliseconds before the heads up notification sent automatically by the system auto-dismisses. -->
+ <integer name="auto_heads_up_notification_decay">3000</integer>
+
<!-- The number of milliseconds after a heads up notification is pushed back
before the app can interrupt again. -->
<integer name="heads_up_default_snooze_length_ms">60000</integer>
@@ -197,25 +200,9 @@
<!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
<integer name="doze_pickup_vibration_threshold">2000</integer>
- <!-- Doze: can we assume the pickup sensor includes a proximity check?
- This is ignored if doze_pickup_subtype_performs_proximity_check is not empty.
- @deprecated: use doze_pickup_subtype_performs_proximity_check instead.-->
+ <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
<bool name="doze_pickup_performs_proximity_check">false</bool>
- <!-- Doze: a list of pickup sensor subtypes that perform a proximity check before they trigger.
- If not empty, either * or !* must appear to specify the default.
- If empty, falls back to doze_pickup_performs_proximity_check.
-
- Examples: 1,2,3,!* -> subtypes 1,2 and 3 perform the check, all others don't.
- !1,!2,* -> subtypes 1 and 2 don't perform the check, all others do.
- !8,* -> subtype 8 does not perform the check, all others do
- 1,1,* -> illegal, every item may only appear once
- 1,!1,* -> illegal, no contradictions allowed
- 1,2 -> illegal, need either * or !*
- 1,,4a3 -> illegal, no empty or non-numeric terms allowed
- -->
- <string name="doze_pickup_subtype_performs_proximity_check"></string>
-
<!-- Type of a sensor that provides a low-power estimate of the desired display
brightness, suitable to listen to while the device is asleep (e.g. during
always-on display) -->
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 2090748..11d093f 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -303,6 +303,11 @@
}
} else {
subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+ if (subs == null) {
+ subs = new ArrayList<>();
+ } else {
+ filterMobileSubscriptionInSameGroup(subs);
+ }
}
return subs;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f465003..45f69d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -28,6 +28,7 @@
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
import android.annotation.AnyThread;
import android.annotation.MainThread;
@@ -70,6 +71,7 @@
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -382,6 +384,13 @@
}
};
+ private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
+ }
+ };
+
private OnSubscriptionsChangedListener mSubscriptionListener =
new OnSubscriptionsChangedListener() {
@Override
@@ -431,7 +440,7 @@
private void handleSimSubscriptionInfoChanged() {
if (DEBUG_SIM_STATES) {
Log.v(TAG, "onSubscriptionInfoChanged()");
- List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+ List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(false);
if (sil != null) {
for (SubscriptionInfo subInfo : sil) {
Log.v(TAG, "SubInfo:" + subInfo);
@@ -483,7 +492,7 @@
public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
List<SubscriptionInfo> sil = mSubscriptionInfo;
if (sil == null || forceReload) {
- sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+ sil = mSubscriptionManager.getActiveSubscriptionInfoList(false);
}
if (sil == null) {
// getActiveSubscriptionInfoList was null callers expect an empty list.
@@ -1080,6 +1089,8 @@
}
mHandler.sendMessage(
mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
+ } else if (TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
+ mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
} else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
action)) {
mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -1490,6 +1501,7 @@
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+ filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -1563,6 +1575,12 @@
mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
updateAirplaneModeState();
+
+ TelephonyManager telephony =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephony != null) {
+ telephony.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+ }
}
private void updateAirplaneModeState() {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 67ff0e7..4d42e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -56,6 +57,7 @@
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -66,6 +68,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeDialogComponent;
@@ -224,6 +227,18 @@
@Singleton
@Provides
+ @Nullable
+ public KeyguardLiftController provideKeyguardLiftController(Context context,
+ StatusBarStateController statusBarStateController,
+ AsyncSensorManager asyncSensorManager) {
+ if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ return null;
+ }
+ return new KeyguardLiftController(context, statusBarStateController, asyncSensorManager);
+ }
+
+ @Singleton
+ @Provides
public NotificationListener provideNotificationListener(Context context) {
return new NotificationListener(context);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index cdcf660..cf04b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -76,6 +76,8 @@
private final ProxSensor mProxSensor;
private long mDebounceFrom;
private boolean mSettingRegistered;
+ private boolean mListening;
+ private boolean mPaused;
public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
@@ -100,9 +102,12 @@
mPickupSensor = new TriggerSensor(
mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Settings.Secure.DOZE_PICK_UP_GESTURE,
+ true /* settingDef */,
config.dozePickupSensorAvailable(),
DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
- false /* touchscreen */),
+ false /* touchscreen */,
+ false /* ignoresSetting */,
+ mDozeParameters.getPickupPerformsProxCheck()),
new TriggerSensor(
findSensorWithType(config.doubleTapSensorType()),
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
@@ -127,15 +132,15 @@
true /* touchscreen */),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
- Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
+ Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
mConfig.wakeScreenGestureAvailable() && alwaysOn,
DozeLog.REASON_SENSOR_WAKE_UP,
false /* reports touch coordinates */,
false /* touchscreen */),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
- Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
- mConfig.wakeScreenGestureAvailable() && alwaysOn,
+ Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
+ mConfig.wakeScreenGestureAvailable(),
DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
false /* reports touch coordinates */,
false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
@@ -170,11 +175,49 @@
return null;
}
+ /**
+ * If sensors should be registered and sending signals.
+ */
public void setListening(boolean listen) {
- for (TriggerSensor s : mSensors) {
- s.setListening(listen);
+ if (mListening == listen) {
+ return;
}
- registerSettingsObserverIfNeeded(listen);
+ mListening = listen;
+ updateListening();
+ }
+
+ /**
+ * Unregister sensors, when listening, unless they are prox gated.
+ * @see #setListening(boolean)
+ */
+ public void setPaused(boolean paused) {
+ if (mPaused == paused) {
+ return;
+ }
+ mPaused = paused;
+ updateListening();
+ }
+
+ private void updateListening() {
+ boolean anyListening = false;
+ for (TriggerSensor s : mSensors) {
+ // We don't want to be listening while we're PAUSED (prox sensor is covered)
+ // except when the sensor is already gated by prox.
+ boolean listen = mListening && (!mPaused || s.performsProxCheck());
+ s.setListening(listen);
+ if (listen) {
+ anyListening = true;
+ }
+ }
+
+ if (!anyListening) {
+ mResolver.unregisterContentObserver(mSettingsObserver);
+ } else if (!mSettingRegistered) {
+ for (TriggerSensor s : mSensors) {
+ s.registerSettingsObserver(mSettingsObserver);
+ }
+ }
+ mSettingRegistered = anyListening;
}
/** Set the listening state of only the sensors that require the touchscreen. */
@@ -236,17 +279,6 @@
return mProxSensor.mCurrentlyFar;
}
- private void registerSettingsObserverIfNeeded(boolean register) {
- if (!register) {
- mResolver.unregisterContentObserver(mSettingsObserver);
- } else if (!mSettingRegistered) {
- for (TriggerSensor s : mSensors) {
- s.registerSettingsObserver(mSettingsObserver);
- }
- }
- mSettingRegistered = register;
- }
-
private class ProxSensor implements SensorEventListener {
boolean mRequested;
@@ -334,10 +366,11 @@
final Sensor mSensor;
final boolean mConfigured;
final int mPulseReason;
- final String mSetting;
- final boolean mReportsTouchCoordinates;
- final boolean mSettingDefault;
- final boolean mRequiresTouchscreen;
+ private final String mSetting;
+ private final boolean mReportsTouchCoordinates;
+ private final boolean mSettingDefault;
+ private final boolean mRequiresTouchscreen;
+ private final boolean mSensorPerformsProxCheck;
protected boolean mRequested;
protected boolean mRegistered;
@@ -354,12 +387,14 @@
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
boolean requiresTouchscreen) {
this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen, false /* ignoresSetting */);
+ requiresTouchscreen, false /* ignoresSetting */,
+ false /* sensorPerformsProxCheck */);
}
private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
- boolean requiresTouchscreen, boolean ignoresSetting) {
+ boolean requiresTouchscreen, boolean ignoresSetting,
+ boolean sensorPerformsProxCheck) {
mSensor = sensor;
mSetting = setting;
mSettingDefault = settingDef;
@@ -368,6 +403,7 @@
mReportsTouchCoordinates = reportsTouchCoordinates;
mRequiresTouchscreen = requiresTouchscreen;
mIgnoresSetting = ignoresSetting;
+ mSensorPerformsProxCheck = sensorPerformsProxCheck;
}
public void setListening(boolean listen) {
@@ -427,14 +463,11 @@
DozeLog.traceSensor(mContext, mPulseReason);
mHandler.post(mWakeLock.wrap(() -> {
if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
- boolean sensorPerformsProxCheck = false;
if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
int subType = (int) event.values[0];
MetricsLogger.action(
mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
subType);
- sensorPerformsProxCheck =
- mDozeParameters.getPickupSubtypePerformsProxCheck(subType);
}
mRegistered = false;
@@ -444,7 +477,7 @@
screenX = event.values[0];
screenY = event.values[1];
}
- mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY,
+ mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
event.values);
if (!mRegistered) {
updateListener(); // reregister, this sensor only fires once
@@ -452,6 +485,15 @@
}));
}
+ /**
+ * If the sensor itself performs proximity checks, to avoid pocket dialing.
+ * Gated sensors don't need to be stopped when the {@link DozeMachine} is
+ * {@link DozeMachine.State#DOZE_AOD_PAUSED}.
+ */
+ public boolean performsProxCheck() {
+ return mSensorPerformsProxCheck;
+ }
+
public void registerSettingsObserver(ContentObserver settingsObserver) {
if (mConfigured && !TextUtils.isEmpty(mSetting)) {
mResolver.registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index a381e7b..97b08d5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -107,9 +107,17 @@
}
private void onNotification() {
- if (DozeMachine.DEBUG) Log.d(TAG, "requestNotificationPulse");
+ if (DozeMachine.DEBUG) {
+ Log.d(TAG, "requestNotificationPulse");
+ }
+ if (!sWakeDisplaySensorState) {
+ Log.d(TAG, "Wake display false. Pulse denied.");
+ return;
+ }
mNotificationPulseTime = SystemClock.elapsedRealtime();
- if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
+ if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
+ return;
+ }
requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
DozeLog.traceNotificationPulse(mContext);
}
@@ -216,15 +224,21 @@
if (state == DozeMachine.State.DOZE_PULSING
|| state == DozeMachine.State.DOZE_PULSING_BRIGHT) {
boolean ignoreTouch = near;
- if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
+ if (DEBUG) {
+ Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
+ }
mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
}
if (far && (paused || pausing)) {
- if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
+ if (DEBUG) {
+ Log.i(TAG, "Prox FAR, unpausing AOD");
+ }
mMachine.requestState(DozeMachine.State.DOZE_AOD);
} else if (near && aod) {
- if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
+ if (DEBUG) {
+ Log.i(TAG, "Prox NEAR, pausing AOD");
+ }
mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
}
}
@@ -282,6 +296,7 @@
case DOZE_AOD:
mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
mDozeSensors.setListening(true);
+ mDozeSensors.setPaused(false);
if (newState == DozeMachine.State.DOZE_AOD && !sWakeDisplaySensorState) {
onWakeScreen(false, newState);
}
@@ -289,12 +304,13 @@
case DOZE_AOD_PAUSED:
case DOZE_AOD_PAUSING:
mDozeSensors.setProxListening(true);
- mDozeSensors.setListening(false);
+ mDozeSensors.setPaused(true);
break;
case DOZE_PULSING:
case DOZE_PULSING_BRIGHT:
mDozeSensors.setTouchscreenSensorsListening(false);
mDozeSensors.setProxListening(true);
+ mDozeSensors.setPaused(false);
break;
case DOZE_PULSE_DONE:
mDozeSensors.requestTemporaryDisable();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 0635231..5136682 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,6 +52,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -103,8 +104,8 @@
private final Date mCurrentTime = new Date();
private final Handler mHandler;
private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
- private final HashSet<Integer> mMediaInvisibleStates;
private final Object mMediaToken = new Object();
+ private DozeParameters mDozeParameters;
@VisibleForTesting
protected SettableWakeLock mMediaWakeLock;
@VisibleForTesting
@@ -184,11 +185,6 @@
mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
mDndUri = Uri.parse(KEYGUARD_DND_URI);
mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
-
- mMediaInvisibleStates = new HashSet<>();
- mMediaInvisibleStates.add(PlaybackState.STATE_NONE);
- mMediaInvisibleStates.add(PlaybackState.STATE_STOPPED);
- mMediaInvisibleStates.add(PlaybackState.STATE_PAUSED);
}
/**
@@ -201,12 +197,14 @@
public void initDependencies(
NotificationMediaManager mediaManager,
StatusBarStateController statusBarStateController,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ DozeParameters dozeParameters) {
mMediaManager = mediaManager;
mMediaManager.addCallback(this);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mKeyguardBypassController = keyguardBypassController;
+ mDozeParameters = dozeParameters;
}
@AnyThread
@@ -231,9 +229,9 @@
}
protected boolean needsMediaLocked() {
- boolean isBypass = mKeyguardBypassController != null
- && mKeyguardBypassController.getBypassEnabled();
- return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || isBypass);
+ boolean keepWhenAwake = mKeyguardBypassController != null
+ && mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn();
+ return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake);
}
protected void addMediaLocked(ListBuilder listBuilder) {
@@ -458,7 +456,7 @@
@Override
public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
synchronized (this) {
- boolean nextVisible = !mMediaInvisibleStates.contains(state);
+ boolean nextVisible = NotificationMediaManager.isPlayingState(state);
mHandler.removeCallbacksAndMessages(mMediaToken);
if (mMediaIsVisible && !nextVisible) {
// We need to delay this event for a few millis when stopping to avoid jank in the
@@ -477,7 +475,7 @@
}
private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) {
- boolean nextVisible = !mMediaInvisibleStates.contains(state);
+ boolean nextVisible = NotificationMediaManager.isPlayingState(state);
CharSequence title = null;
if (metadata != null) {
title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b9fb1a1..21f5812 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -239,9 +239,8 @@
});
mDismissButton = findViewById(R.id.dismiss);
mDismissButton.setAlpha(0);
- mDismissButton.setOnClickListener((v) -> {
- dismissPip();
- });
+ mDismissButton.setOnClickListener(v -> dismissPip());
+ findViewById(R.id.expand_button).setOnClickListener(v -> expandPip());
mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 99f9e99..ed6f599 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -119,7 +119,7 @@
private boolean mIsEnabled;
private int mCurrentBoundedUserId = -1;
private float mNavBarButtonAlpha;
- private MotionEvent mStatusBarGestureDownEvent;
+ private boolean mInputFocusTransferStarted;
private float mWindowCornerRadius;
private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
@@ -164,6 +164,7 @@
}
}
+ // TODO: change the method signature to use (boolean inputFocusTransferStarted)
@Override
public void onStatusBarMotionEvent(MotionEvent event) {
if (!verifyCaller("onStatusBarMotionEvent")) {
@@ -175,16 +176,16 @@
mHandler.post(()->{
StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
if (bar != null) {
- bar.dispatchNotificationsPanelTouchEvent(event);
int action = event.getActionMasked();
if (action == ACTION_DOWN) {
- mStatusBarGestureDownEvent = MotionEvent.obtain(event);
+ mInputFocusTransferStarted = true;
+
}
if (action == ACTION_UP || action == ACTION_CANCEL) {
- mStatusBarGestureDownEvent.recycle();
- mStatusBarGestureDownEvent = null;
+ mInputFocusTransferStarted = false;
}
+ bar.onInputFocusTransfer(mInputFocusTransferStarted);
event.recycle();
}
});
@@ -590,14 +591,12 @@
}
public void cleanupAfterDeath() {
- if (mStatusBarGestureDownEvent != null) {
+ if (mInputFocusTransferStarted) {
mHandler.post(()-> {
StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
if (bar != null) {
- mStatusBarGestureDownEvent.setAction(MotionEvent.ACTION_CANCEL);
- bar.dispatchNotificationsPanelTouchEvent(mStatusBarGestureDownEvent);
- mStatusBarGestureDownEvent.recycle();
- mStatusBarGestureDownEvent = null;
+ mInputFocusTransferStarted = false;
+ bar.onInputFocusTransfer(false);
}
});
}
@@ -782,6 +781,7 @@
pw.println(QuickStepContract.isBackGestureDisabled(mSysUiStateFlags));
pw.print(" assistantGestureDisabled=");
pw.println(QuickStepContract.isAssistantGestureDisabled(mSysUiStateFlags));
+ pw.print(" mInputFocusTransferStarted="); pw.println(mInputFocusTransferStarted);
}
public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index a59d590..f001561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -69,6 +69,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -91,6 +92,14 @@
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
private final KeyguardBypassController mKeyguardBypassController;
+ private static final HashSet<Integer> PAUSED_MEDIA_STATES = new HashSet<>();
+ static {
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_NONE);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_STOPPED);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_PAUSED);
+ PAUSED_MEDIA_STATES.add(PlaybackState.STATE_ERROR);
+ }
+
// Late binding
private NotificationEntryManager mEntryManager;
@@ -207,6 +216,10 @@
mPropertiesChangedListener);
}
+ public static boolean isPlayingState(int state) {
+ return !PAUSED_MEDIA_STATES.contains(state);
+ }
+
public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0a8b7f8..4ccd0cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,6 +18,7 @@
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
import android.content.res.Configuration;
@@ -48,8 +49,12 @@
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import javax.inject.Inject;
+import javax.inject.Named;
+
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
@@ -63,6 +68,7 @@
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
+ private final KeyguardBypassController mBypassController;
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
@@ -93,8 +99,12 @@
private int mCutoutHeight;
private int mGapHeight;
- public NotificationShelf(Context context, AttributeSet attrs) {
+ @Inject
+ public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
+ AttributeSet attrs,
+ KeyguardBypassController keyguardBypassController) {
super(context, attrs);
+ mBypassController = keyguardBypassController;
}
@Override
@@ -309,7 +319,10 @@
colorTwoBefore = previousColor;
transitionAmount = inShelfAmount;
}
- if (isLastChild) {
+ // We don't want to modify the color if the notification is hun'd
+ boolean canModifyColor = mAmbientState.isShadeExpanded()
+ && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
+ if (isLastChild && canModifyColor) {
if (colorOfViewBeforeLast == NO_COLOR) {
colorOfViewBeforeLast = ownColorUntinted;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
new file mode 100644
index 0000000..ea474ce
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.content.Context
+import android.media.MediaMetadata
+import android.provider.Settings
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.tuner.TunerService
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class that automatically creates heads up for important notification when bypassing the
+ * lockscreen
+ */
+@Singleton
+class BypassHeadsUpNotifier @Inject constructor(
+ private val context: Context,
+ private val bypassController: KeyguardBypassController,
+ private val statusBarStateController: StatusBarStateController,
+ private val headsUpManager: HeadsUpManagerPhone,
+ private val mediaManager: NotificationMediaManager,
+ tunerService: TunerService) : StatusBarStateController.StateListener,
+ NotificationMediaManager.MediaListener {
+
+ private lateinit var entryManager: NotificationEntryManager
+ private var currentMediaEntry: NotificationEntry? = null
+ private var enabled = true
+
+ var fullyAwake = false
+ set(value) {
+ field = value
+ if (value) {
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+ }
+
+ init {
+ statusBarStateController.addCallback(this)
+ tunerService.addTunable(
+ TunerService.Tunable { _, _ ->
+ enabled = Settings.Secure.getIntForUser(
+ context.contentResolver,
+ Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING,
+ 1 /* default */,
+ KeyguardUpdateMonitor.getCurrentUser()) != 0
+ }, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING)
+ }
+
+ fun setUp(entryManager: NotificationEntryManager) {
+ this.entryManager = entryManager
+ mediaManager.addCallback(this)
+ }
+
+ override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
+ val previous = currentMediaEntry
+ var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
+ if (!NotificationMediaManager.isPlayingState(state)) {
+ newEntry = null
+ }
+ if (newEntry?.isSensitive == true) {
+ newEntry = null
+ }
+ currentMediaEntry = newEntry
+ updateAutoHeadsUp(previous)
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+
+ private fun updateAutoHeadsUp(entry: NotificationEntry?) {
+ entry?.let {
+ val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp()
+ it.isAutoHeadsUp = autoHeadsUp
+ if (autoHeadsUp) {
+ headsUpManager.showNotification(it)
+ }
+ }
+ }
+
+ override fun onStatePostChange() {
+ updateAutoHeadsUp(currentMediaEntry)
+ }
+
+ private fun canAutoHeadsUp() : Boolean {
+ if (!enabled) {
+ return false
+ }
+ if (!bypassController.bypassEnabled) {
+ return false
+ }
+ if (statusBarStateController.state != StatusBarState.KEYGUARD) {
+ return false
+ }
+ if (!fullyAwake) {
+ return false
+ }
+ return true
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 8a23f71..d71d407 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -24,7 +24,6 @@
import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -119,12 +118,11 @@
shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
if (wasAlerting) {
- if (!shouldAlert) {
- // We don't want this to be interrupting anymore, let's remove it
- mHeadsUpManager.removeNotification(entry.key,
- false /* ignoreEarliestRemovalTime */);
- } else {
+ if (shouldAlert) {
mHeadsUpManager.updateNotification(entry.key, alertAgain);
+ } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+ // We don't want this to be interrupting anymore, let's remove it
+ mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
}
} else if (shouldAlert && alertAgain) {
// This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 1aa6bc9..dfc6450 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -24,6 +24,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import androidx.annotation.NonNull;
+
/**
* Listener interface for changes sent by NotificationEntryManager.
*/
@@ -45,7 +47,7 @@
/**
* Called when a new entry is created.
*/
- default void onNotificationAdded(NotificationEntry entry) {
+ default void onNotificationAdded(@NonNull NotificationEntry entry) {
}
/**
@@ -61,7 +63,7 @@
/**
* Called when a notification was updated, after any filtering of notifications have occurred.
*/
- default void onPostEntryUpdated(NotificationEntry entry) {
+ default void onPostEntryUpdated(@NonNull NotificationEntry entry) {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 9db715d..b19d2ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -175,6 +175,7 @@
private boolean mHighPriority;
private boolean mSensitive = true;
private Runnable mOnSensitiveChangedListener;
+ private boolean mAutoHeadsUp;
public NotificationEntry(StatusBarNotification n) {
this(n, null);
@@ -670,11 +671,25 @@
if (row != null) row.setHeadsUp(shouldHeadsUp);
}
-
public void setHeadsUpAnimatingAway(boolean animatingAway) {
if (row != null) row.setHeadsUpAnimatingAway(animatingAway);
}
+ /**
+ * Set that this notification was automatically heads upped. This happens for example when
+ * the user bypasses the lockscreen and media is playing.
+ */
+ public void setAutoHeadsUp(boolean autoHeadsUp) {
+ mAutoHeadsUp = autoHeadsUp;
+ }
+
+ /**
+ * @return if this notification was automatically heads upped. This happens for example when
+ * * the user bypasses the lockscreen and media is playing.
+ */
+ public boolean isAutoHeadsUp() {
+ return mAutoHeadsUp;
+ }
public boolean mustStayOnScreen() {
return row != null && row.mustStayOnScreen();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index ae534d2..a8327f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2698,6 +2698,8 @@
l.setAlpha(1.0f);
l.setLayerType(LAYER_TYPE_NONE, null);
}
+ } else {
+ setHeadsUpAnimatingAway(false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index e2cb8d4..58e6399 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -837,7 +837,13 @@
break;
}
}
- if (!mAmbientState.isDozing() || anySectionHasVisibleChild) {
+ boolean shouldDrawBackground;
+ if (mKeyguardBypassController.getBypassEnabled() && onKeyguard()) {
+ shouldDrawBackground = isPulseExpanding();
+ } else {
+ shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild;
+ }
+ if (shouldDrawBackground) {
drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
}
@@ -3396,10 +3402,20 @@
for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
ExpandableNotificationRow row = eventPair.first;
boolean isHeadsUp = eventPair.second;
+ if (isHeadsUp != row.isHeadsUp()) {
+ // For cases where we have a heads up showing and appearing again we shouldn't
+ // do the animations at all.
+ continue;
+ }
int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
boolean onBottom = false;
boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
- if (!mIsExpanded && !isHeadsUp) {
+ boolean performDisappearAnimation = !mIsExpanded
+ // Only animate if we still have pinned heads up, otherwise we just have the
+ // regular collapse animation of the lock screen
+ || (mKeyguardBypassController.getBypassEnabled() && onKeyguard()
+ && mHeadsUpManager.hasPinnedHeadsUp());
+ if (performDisappearAnimation && !isHeadsUp) {
type = row.wasJustClicked()
? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
: AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
@@ -6246,6 +6262,15 @@
mAmbientState.onDragFinished(animView);
updateContinuousShadowDrawing();
updateContinuousBackgroundDrawing();
+ if (animView instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
+ if (row.isPinned() && !canChildBeDismissed(row)
+ && row.getStatusBarNotification().getNotification().fullScreenIntent
+ == null) {
+ mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
+ true /* removeImmediately */);
+ }
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 09c6968..35ba801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -546,12 +546,12 @@
ExpandableViewState topState =
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
if (topState != null && !isTopEntry && (!mIsExpanded
- || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
+ || unmodifiedEndLocation > topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
childState.height = row.getIntrinsicHeight();
- childState.yTranslation = topState.yTranslation + topState.height
- - childState.height;
+ childState.yTranslation = Math.min(topState.yTranslation + topState.height
+ - childState.height, childState.yTranslation);
}
// heads up notification show and this row is the top entry of heads up
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 4f169eb..0996ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -28,6 +28,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -451,7 +452,11 @@
if (row.isDismissed()) {
needsAnimation = false;
}
- StatusBarIconView icon = row.getEntry().icon;
+ NotificationEntry entry = row.getEntry();
+ StatusBarIconView icon = entry.icon;
+ if (entry.centeredIcon != null && entry.centeredIcon.getParent() != null) {
+ icon = entry.centeredIcon;
+ }
if (icon.getParent() != null) {
icon.getLocationOnScreen(mTmpLocation);
float iconPosition = mTmpLocation[0] - icon.getTranslationX()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 89bd1b6..10b48e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -22,9 +22,7 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.MathUtils;
-import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
@@ -41,13 +39,11 @@
public class DozeParameters implements TunerService.Tunable,
com.android.systemui.plugins.statusbar.DozeParameters {
private static final int MAX_DURATION = 60 * 1000;
- public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
public static final boolean FORCE_NO_BLANKING =
SystemProperties.getBoolean("debug.force_no_blanking", false);
public static final boolean FORCE_BLANKING =
SystemProperties.getBoolean("debug.force_blanking", false);
- private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
private static DozeParameters sInstance;
private final Context mContext;
@@ -92,20 +88,6 @@
pw.print(" getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
pw.print(" getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
- pw.print(" getPickupSubtypePerformsProxCheck(): ");pw.println(
- dumpPickupSubtypePerformsProxCheck());
- }
-
- private String dumpPickupSubtypePerformsProxCheck() {
- // Refresh sPickupSubtypePerformsProxMatcher
- getPickupSubtypePerformsProxCheck(0);
-
- if (sPickupSubtypePerformsProxMatcher == null) {
- return "fallback: " + mContext.getResources().getBoolean(
- R.bool.doze_pickup_performs_proximity_check);
- } else {
- return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
- }
}
public boolean getDisplayStateSupported() {
@@ -225,21 +207,8 @@
return SystemProperties.get(propName, mContext.getString(resId));
}
- public boolean getPickupSubtypePerformsProxCheck(int subType) {
- String spec = getString("doze.pickup.proxcheck",
- R.string.doze_pickup_subtype_performs_proximity_check);
-
- if (TextUtils.isEmpty(spec)) {
- // Fall back to non-subtype based property.
- return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
- }
-
- if (sPickupSubtypePerformsProxMatcher == null
- || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
- sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
- }
-
- return sPickupSubtypePerformsProxMatcher.isIn(subType);
+ public boolean getPickupPerformsProxCheck() {
+ return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
}
public int getPulseVisibleDurationExtended() {
@@ -258,81 +227,4 @@
public AlwaysOnDisplayPolicy getPolicy() {
return mAlwaysOnPolicy;
}
-
- /**
- * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
- * listed, will not match numbers that are listed with a ! prefix, and will match / not match
- * unlisted numbers depending on whether * or !* is present.
- *
- * * -> match any numbers that are not explicitly listed
- * !* -> don't match any numbers that are not explicitly listed
- * 2 -> match 2
- * !3 -> don't match 3
- *
- * It is illegal to specify:
- * - an empty spec
- * - a spec containing that are empty, or a lone !
- * - a spec for anything other than numbers or *
- * - multiple terms for the same number / multiple *s
- */
- public static class IntInOutMatcher {
- private static final String WILDCARD = "*";
- private static final char OUT_PREFIX = '!';
-
- private final SparseBooleanArray mIsIn;
- private final boolean mDefaultIsIn;
- final String mSpec;
-
- public IntInOutMatcher(String spec) {
- if (TextUtils.isEmpty(spec)) {
- throw new IllegalArgumentException("Spec must not be empty");
- }
-
- boolean defaultIsIn = false;
- boolean foundWildcard = false;
-
- mSpec = spec;
- mIsIn = new SparseBooleanArray();
-
- for (String itemPrefixed : spec.split(",", -1)) {
- if (itemPrefixed.length() == 0) {
- throw new IllegalArgumentException(
- "Illegal spec, must not have zero-length items: `" + spec + "`");
- }
- boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
- String item = isIn ? itemPrefixed : itemPrefixed.substring(1);
-
- if (itemPrefixed.length() == 0) {
- throw new IllegalArgumentException(
- "Illegal spec, must not have zero-length items: `" + spec + "`");
- }
-
- if (WILDCARD.equals(item)) {
- if (foundWildcard) {
- throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
- "` must not appear multiple times in `" + spec + "`");
- }
- defaultIsIn = isIn;
- foundWildcard = true;
- } else {
- int key = Integer.parseInt(item);
- if (mIsIn.indexOfKey(key) >= 0) {
- throw new IllegalArgumentException("Illegal spec, `" + key +
- "` must not appear multiple times in `" + spec + "`");
- }
- mIsIn.put(key, isIn);
- }
- }
-
- if (!foundWildcard) {
- throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
- }
-
- mDefaultIsIn = defaultIsIn;
- }
-
- public boolean isIn(int value) {
- return (mIsIn.get(value, mDefaultIsIn));
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index ade855e..c44f953 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -32,7 +32,6 @@
import androidx.collection.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
@@ -67,6 +66,7 @@
final int mExtensionTime;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mBypassController;
+ private final int mAutoHeadsUpNotificationDecay;
private View mStatusBarWindowView;
private NotificationGroupManager mGroupManager;
private VisualStabilityManager mVisualStabilityManager;
@@ -81,6 +81,7 @@
private boolean mTrackingHeadsUp;
private HashSet<String> mSwipedOutKeys = new HashSet<>();
private HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
+ private HashSet<String> mKeysToRemoveWhenLeavingKeyguard = new HashSet<>();
private ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
= new ArraySet<>();
private boolean mIsExpanded;
@@ -121,6 +122,8 @@
mAutoDismissNotificationDecayDozing = resources.getInteger(
R.integer.heads_up_notification_decay_dozing);
mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
+ mAutoHeadsUpNotificationDecay = resources.getInteger(
+ R.integer.auto_heads_up_notification_decay);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mBypassController = bypassController;
@@ -231,7 +234,16 @@
@Override
public void onStateChanged(int newState) {
+ boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
+ boolean isKeyguard = newState == StatusBarState.KEYGUARD;
mStatusBarState = newState;
+ if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
+ String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
+ for (String key : keys) {
+ removeAlertEntry(key);
+ }
+ mKeysToRemoveWhenLeavingKeyguard.clear();
+ }
}
@Override
@@ -245,6 +257,15 @@
}
}
+ @Override
+ public boolean isEntryAutoHeadsUpped(String key) {
+ HeadsUpEntryPhone headsUpEntryPhone = getHeadsUpEntryPhone(key);
+ if (headsUpEntryPhone == null) {
+ return false;
+ }
+ return headsUpEntryPhone.isAutoHeadsUp();
+ }
+
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a sane state.
@@ -420,6 +441,7 @@
@Override
protected void onAlertEntryRemoved(AlertEntry alertEntry) {
+ mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
super.onAlertEntryRemoved(alertEntry);
mEntryPool.release((HeadsUpEntryPhone) alertEntry);
}
@@ -479,6 +501,11 @@
*/
private boolean extended;
+ /**
+ * Was this entry received while on keyguard
+ */
+ private boolean mIsAutoHeadsUp;
+
@Override
protected boolean isSticky() {
@@ -494,10 +521,12 @@
mEntriesToRemoveWhenReorderingAllowed.add(entry);
mVisualStabilityManager.addReorderingAllowedCallback(
HeadsUpManagerPhone.this);
- } else if (!mTrackingHeadsUp) {
- removeAlertEntry(entry.key);
- } else {
+ } else if (mTrackingHeadsUp) {
mEntriesToRemoveAfterExpand.add(entry);
+ } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
+ mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+ } else {
+ removeAlertEntry(entry.key);
}
};
@@ -506,6 +535,7 @@
@Override
public void updateEntry(boolean updatePostTime) {
+ mIsAutoHeadsUp = mEntry.isAutoHeadsUp();
super.updateEntry(updatePostTime);
if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
@@ -514,6 +544,7 @@
if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
}
+ mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
}
@Override
@@ -548,6 +579,7 @@
super.reset();
mMenuShownPinned = false;
extended = false;
+ mIsAutoHeadsUp = false;
}
private void extendPulse() {
@@ -558,13 +590,35 @@
}
@Override
+ public int compareTo(AlertEntry alertEntry) {
+ HeadsUpEntryPhone headsUpEntry = (HeadsUpEntryPhone) alertEntry;
+ boolean autoShown = isAutoHeadsUp();
+ boolean otherAutoShown = headsUpEntry.isAutoHeadsUp();
+ if (autoShown && !otherAutoShown) {
+ return 1;
+ } else if (!autoShown && otherAutoShown) {
+ return -1;
+ }
+ return super.compareTo(alertEntry);
+ }
+
+ @Override
protected long calculateFinishTime() {
return mPostTime + getDecayDuration() + (extended ? mExtensionTime : 0);
}
private int getDecayDuration() {
- return mStatusBarStateController.isDozing() ? mAutoDismissNotificationDecayDozing
- : getRecommendedHeadsUpTimeoutMs();
+ if (mStatusBarStateController.isDozing()) {
+ return mAutoDismissNotificationDecayDozing;
+ } else if (isAutoHeadsUp()) {
+ return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay);
+ } else {
+ return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
+ }
+ }
+
+ private boolean isAutoHeadsUp() {
+ return mIsAutoHeadsUp;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
new file mode 100644
index 0000000..f4635d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.content.Context
+import android.hardware.Sensor
+import android.hardware.TriggerEvent
+import android.hardware.TriggerEventListener
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.AsyncSensorManager
+
+class KeyguardLiftController constructor(
+ context: Context,
+ private val statusBarStateController: StatusBarStateController,
+ private val asyncSensorManager: AsyncSensorManager
+) : StatusBarStateController.StateListener, KeyguardUpdateMonitorCallback() {
+
+ private val keyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context)
+ private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
+ private var isListening = false
+ private var bouncerVisible = false
+
+ init {
+ statusBarStateController.addCallback(this)
+ keyguardUpdateMonitor.registerCallback(this)
+ updateListeningState()
+ }
+
+ private val listener: TriggerEventListener = object : TriggerEventListener() {
+ override fun onTrigger(event: TriggerEvent?) {
+ Assert.isMainThread()
+ // Not listening anymore since trigger events unregister themselves
+ isListening = false
+ updateListeningState()
+ keyguardUpdateMonitor.requestFaceAuth()
+ }
+ }
+
+ override fun onDozingChanged(isDozing: Boolean) {
+ updateListeningState()
+ }
+
+ override fun onKeyguardBouncerChanged(bouncer: Boolean) {
+ bouncerVisible = bouncer
+ updateListeningState()
+ }
+
+ override fun onKeyguardVisibilityChanged(showing: Boolean) {
+ updateListeningState()
+ }
+
+ private fun updateListeningState() {
+ val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
+ !statusBarStateController.isDozing
+
+ val shouldListen = onKeyguard || bouncerVisible
+ if (shouldListen != isListening) {
+ isListening = shouldListen
+
+ if (shouldListen) {
+ asyncSensorManager.requestTriggerSensor(listener, pickupSensor)
+ } else {
+ asyncSensorManager.cancelTriggerSensor(listener, pickupSensor)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index ca001c6..ea434fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.annotation.IntDef;
@@ -29,12 +28,12 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricSourceType;
-import android.os.Handler;
import android.os.Trace;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.Nullable;
@@ -43,6 +42,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -53,6 +53,7 @@
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import java.lang.annotation.Retention;
@@ -67,7 +68,8 @@
public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
- NotificationWakeUpCoordinator.WakeUpListener {
+ NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener,
+ OnHeadsUpChangedListener {
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
@@ -79,12 +81,13 @@
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AccessibilityController mAccessibilityController;
private final DockManager mDockManager;
- private final Handler mMainHandler;
private final KeyguardMonitor mKeyguardMonitor;
private final KeyguardBypassController mBypassController;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+ private final HeadsUpManagerPhone mHeadsUpManager;
private int mLastState = 0;
+ private boolean mForceUpdate;
private boolean mTransientBiometricsError;
private boolean mIsFaceUnlockState;
private boolean mSimLocked;
@@ -92,23 +95,20 @@
private boolean mPulsing;
private boolean mDozing;
private boolean mDocked;
- private boolean mLastDozing;
- private boolean mLastPulsing;
private int mIconColor;
private float mDozeAmount;
- private int mIconRes;
- private boolean mBouncerShowing;
- private boolean mWasPulsingOnThisFrame;
+ private boolean mBouncerShowingScrimmed;
private boolean mWakeAndUnlockRunning;
private boolean mKeyguardShowing;
private boolean mShowingLaunchAffordance;
+ private boolean mUpdatePending;
private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
new KeyguardMonitor.Callback() {
@Override
public void onKeyguardShowingChanged() {
mKeyguardShowing = mKeyguardMonitor.isShowing();
- update(false /* force */);
+ update();
}
};
private final DockManager.DockEventListener mDockEventListener =
@@ -119,7 +119,7 @@
|| event == DockManager.STATE_DOCKED_HIDE;
if (docked != mDocked) {
mDocked = docked;
- update(true /* force */);
+ update();
}
}
};
@@ -129,9 +129,8 @@
@Override
public void onSimStateChanged(int subId, int slotId,
IccCardConstants.State simState) {
- boolean oldSimLocked = mSimLocked;
mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
- update(oldSimLocked != mSimLocked);
+ update();
}
@Override
@@ -149,11 +148,6 @@
public void onStrongAuthStateChanged(int userId) {
update();
}
-
- @Override
- public void onBiometricsCleared() {
- update();
- }
};
@Inject
@@ -165,7 +159,7 @@
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardMonitor keyguardMonitor,
@Nullable DockManager dockManager,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ HeadsUpManagerPhone headsUpManager) {
super(context, attrs);
mContext = context;
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
@@ -177,7 +171,7 @@
mWakeUpCoordinator = wakeUpCoordinator;
mKeyguardMonitor = keyguardMonitor;
mDockManager = dockManager;
- mMainHandler = mainHandler;
+ mHeadsUpManager = headsUpManager;
}
@Override
@@ -194,6 +188,7 @@
mDockManager.addListener(mDockEventListener);
}
onThemeChanged();
+ update();
}
@Override
@@ -247,63 +242,92 @@
}
public void update(boolean force) {
- int state = getState();
- mIsFaceUnlockState = state == STATE_SCANNING_FACE;
- if (state != mLastState || mLastDozing != mDozing || mLastPulsing != mPulsing || force) {
- @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(mLastState,
- state, mLastPulsing, mPulsing, mLastDozing, mDozing);
- boolean isAnim = lockAnimIndex != -1;
-
- int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
- if (iconRes != mIconRes) {
- mIconRes = iconRes;
-
- Drawable icon = mContext.getDrawable(iconRes);
- final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
- ? (AnimatedVectorDrawable) icon
- : null;
- setImageDrawable(icon, false);
- if (mIsFaceUnlockState) {
- announceForAccessibility(getContext().getString(
- R.string.accessibility_scanning_face));
- }
-
- if (animation != null && isAnim) {
- animation.forceAnimationOnUI();
- animation.clearAnimationCallbacks();
- animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
- @Override
- public void onAnimationEnd(Drawable drawable) {
- if (getDrawable() == animation && state == getState()
- && doesAnimationLoop(lockAnimIndex)) {
- animation.start();
- } else {
- Trace.endAsyncSection("LockIcon#Animation", state);
- }
- }
- });
- Trace.beginAsyncSection("LockIcon#Animation", state);
- animation.start();
- }
- }
- updateDarkTint();
-
- mLastState = state;
- mLastDozing = mDozing;
- mLastPulsing = mPulsing;
+ if (force) {
+ mForceUpdate = true;
}
+ if (!mUpdatePending) {
+ mUpdatePending = true;
+ getViewTreeObserver().addOnPreDrawListener(this);
+ }
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ mUpdatePending = false;
+ getViewTreeObserver().removeOnPreDrawListener(this);
+
+ int state = getState();
+ int lastState = mLastState;
+ mIsFaceUnlockState = state == STATE_SCANNING_FACE;
+ mLastState = state;
+
+ if (lastState != state || mForceUpdate) {
+ mForceUpdate = false;
+ @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState,
+ state, mPulsing, mDozing);
+ boolean isAnim = lockAnimIndex != -1;
+ int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
+
+ Drawable icon = mContext.getDrawable(iconRes);
+ final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
+ ? (AnimatedVectorDrawable) icon
+ : null;
+ setImageDrawable(icon, false);
+ if (mIsFaceUnlockState) {
+ announceForAccessibility(getContext().getString(
+ R.string.accessibility_scanning_face));
+ }
+
+ if (animation != null && isAnim) {
+ animation.forceAnimationOnUI();
+ animation.clearAnimationCallbacks();
+ animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ if (getDrawable() == animation && state == getState()
+ && doesAnimationLoop(lockAnimIndex)) {
+ animation.start();
+ } else {
+ Trace.endAsyncSection("LockIcon#Animation", state);
+ }
+ }
+ });
+ Trace.beginAsyncSection("LockIcon#Animation", state);
+ animation.start();
+ }
+ }
+ updateDarkTint();
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
|| mShowingLaunchAffordance;
- if (mBypassController.getBypassEnabled()
- && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
- && !mWakeUpCoordinator.getNotificationsFullyHidden()
- && !mBouncerShowing) {
- invisible = true;
+ if (mBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) {
+ if (mHeadsUpManager.isHeadsUpGoingAway()
+ || mHeadsUpManager.hasPinnedHeadsUp()
+ || (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+ && !mWakeUpCoordinator.getNotificationsFullyHidden())) {
+ invisible = true;
+ }
}
- setVisibility(invisible ? INVISIBLE : VISIBLE);
+ boolean wasInvisible = getVisibility() == INVISIBLE;
+ if (invisible != wasInvisible) {
+ setVisibility(invisible ? INVISIBLE : VISIBLE);
+ animate().cancel();
+ if (!invisible) {
+ setScaleX(0);
+ setScaleY(0);
+ animate()
+ .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+ .scaleX(1)
+ .scaleY(1)
+ .withLayer()
+ .setDuration(233)
+ .start();
+ }
+ }
updateClickability();
+
+ return true;
}
private void updateClickability() {
@@ -364,30 +388,22 @@
return lockAnimIndex == SCANNING;
}
- private int getAnimationIndexForTransition(int oldState, int newState,
- boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing) {
+ private static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing,
+ boolean dozing) {
// Never animate when screen is off
- if (dozing && !pulsing && !mWasPulsingOnThisFrame) {
+ if (dozing && !pulsing) {
return -1;
}
- boolean isError = oldState != STATE_BIOMETRICS_ERROR && newState == STATE_BIOMETRICS_ERROR;
- boolean justUnlocked = oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN;
- boolean justLocked = oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED;
- boolean nowPulsing = !wasPulsing && pulsing;
- boolean turningOn = wasDozing && !dozing && !mWasPulsingOnThisFrame;
-
- if (isError) {
+ if (newState == STATE_BIOMETRICS_ERROR) {
return ERROR;
- } else if (justUnlocked) {
+ } else if (oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN) {
return UNLOCK;
- } else if (justLocked) {
+ } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED) {
return LOCK;
} else if (newState == STATE_SCANNING_FACE) {
return SCANNING;
- } else if ((nowPulsing || turningOn) && newState != STATE_LOCK_OPEN) {
- return LOCK_IN;
}
return -1;
}
@@ -399,45 +415,41 @@
}
}
- public void setBouncerShowing(boolean bouncerShowing) {
- mBouncerShowing = bouncerShowing;
+ public void setBouncerShowingScrimmed(boolean bouncerShowing) {
+ mBouncerShowingScrimmed = bouncerShowing;
if (mBypassController.getBypassEnabled()) {
update();
}
}
@Retention(RetentionPolicy.SOURCE)
- @IntDef({ERROR, UNLOCK, LOCK, SCANNING, LOCK_IN})
+ @IntDef({ERROR, UNLOCK, LOCK, SCANNING})
@interface LockAnimIndex {}
- private static final int ERROR = 0, UNLOCK = 1, LOCK = 2, SCANNING = 3, LOCK_IN = 4;
+ private static final int ERROR = 0, UNLOCK = 1, LOCK = 2, SCANNING = 3;
private static final int[][] LOCK_ANIM_RES_IDS = new int[][] {
{
R.anim.lock_to_error,
R.anim.lock_unlock,
R.anim.lock_lock,
- R.anim.lock_scanning,
- R.anim.lock_in,
+ R.anim.lock_scanning
},
{
R.anim.lock_to_error_circular,
R.anim.lock_unlock_circular,
R.anim.lock_lock_circular,
- R.anim.lock_scanning_circular,
- R.anim.lock_in_circular,
+ R.anim.lock_scanning_circular
},
{
R.anim.lock_to_error_filled,
R.anim.lock_unlock_filled,
R.anim.lock_lock_filled,
- R.anim.lock_scanning_filled,
- R.anim.lock_in_filled,
+ R.anim.lock_scanning_filled
},
{
R.anim.lock_to_error_rounded,
R.anim.lock_unlock_rounded,
R.anim.lock_lock_rounded,
- R.anim.lock_scanning_rounded,
- R.anim.lock_in_rounded,
+ R.anim.lock_scanning_rounded
},
};
@@ -462,7 +474,7 @@
return STATE_LOCK_OPEN;
} else if (mTransientBiometricsError) {
return STATE_BIOMETRICS_ERROR;
- } else if (updateMonitor.isFaceDetectionRunning()) {
+ } else if (updateMonitor.isFaceDetectionRunning() && !mPulsing) {
return STATE_SCANNING_FACE;
} else {
return STATE_LOCKED;
@@ -481,12 +493,6 @@
*/
public void setPulsing(boolean pulsing) {
mPulsing = pulsing;
- if (!mPulsing) {
- mWasPulsingOnThisFrame = true;
- mMainHandler.post(() -> {
- mWasPulsingOnThisFrame = false;
- });
- }
update();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index cd97722..d2159ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -248,7 +248,7 @@
if (onlyShowCenteredIcon) {
return isCenteredNotificationIcon;
}
- if (hideCenteredIcon && isCenteredNotificationIcon) {
+ if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
return false;
}
if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 32dc96d..53ce167 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -290,6 +290,8 @@
private boolean mIsFullWidth;
private boolean mBlockingExpansionForCurrentTouch;
+ private boolean mExpectingOpenPanelGesture;
+
/**
* Current dark amount that follows regular interpolation curve of animation.
*/
@@ -1246,6 +1248,28 @@
}
}
+ /**
+ * Input focus transfer is about to happen.
+ */
+ public void startWaitingForOpenPanelGesture() {
+ if (!isFullyCollapsed()) {
+ return;
+ }
+ mExpectingOpenPanelGesture = true;
+ onTrackingStarted();
+ }
+
+ /**
+ * Input focus transfer has already happened as this view decided to intercept
+ * very first down event.
+ */
+ public void stopWaitingForOpenPanelGesture() {
+ if (mExpectingOpenPanelGesture) {
+ mExpectingOpenPanelGesture = false;
+ onTrackingStopped(false);
+ }
+ }
+
@Override
protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
boolean expands = super.flingExpands(vel, vectorVel, x, y);
@@ -1258,8 +1282,12 @@
}
@Override
- protected boolean hasConflictingGestures() {
- return mBarState != StatusBarState.SHADE;
+ protected boolean shouldGestureWaitForTouchSlop() {
+ if (mExpectingOpenPanelGesture) {
+ mExpectingOpenPanelGesture = false;
+ return false;
+ }
+ return isFullyCollapsed() || mBarState != StatusBarState.SHADE;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a9a3b2d..a5b221b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -301,7 +301,7 @@
final float y = event.getY(pointerIndex);
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures();
+ mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
}
@@ -519,7 +519,7 @@
return (int) (mUnlockFalsingThreshold * factor);
}
- protected abstract boolean hasConflictingGestures();
+ protected abstract boolean shouldGestureWaitForTouchSlop();
protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y);
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 7db4afc..e756d3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -80,6 +80,7 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -193,6 +194,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -373,6 +375,11 @@
KeyguardBypassController mKeyguardBypassController;
@Inject
protected HeadsUpManagerPhone mHeadsUpManager;
+ @Inject
+ BypassHeadsUpNotifier mBypassHeadsUpNotifier;
+ @Nullable
+ @Inject
+ protected KeyguardLiftController mKeyguardLiftController;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -630,6 +637,7 @@
mGutsManager = Dependency.get(NotificationGutsManager.class);
mMediaManager = Dependency.get(NotificationMediaManager.class);
mEntryManager = Dependency.get(NotificationEntryManager.class);
+ mBypassHeadsUpNotifier.setUp(mEntryManager);
mNotificationInterruptionStateProvider =
Dependency.get(NotificationInterruptionStateProvider.class);
mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
@@ -646,7 +654,7 @@
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
if (sliceProvider != null) {
sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
- mKeyguardBypassController);
+ mKeyguardBypassController, DozeParameters.getInstance(mContext));
} else {
Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
}
@@ -1151,8 +1159,9 @@
private void inflateShelf() {
mNotificationShelf =
- (NotificationShelf) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_notification_shelf, mStackScroller, false);
+ (NotificationShelf) mInjectionInflater.injectable(
+ LayoutInflater.from(mContext)).inflate(
+ R.layout.status_bar_notification_shelf, mStackScroller, false);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -1918,19 +1927,18 @@
mStatusBarKeyguardViewManager.readyForKeyguardDone();
}
- public void dispatchNotificationsPanelTouchEvent(MotionEvent ev) {
+ /**
+ * Called when another window is about to transfer it's input focus.
+ */
+ public void onInputFocusTransfer(boolean start) {
if (!mCommandQueue.panelsEnabled()) {
return;
}
- mNotificationPanel.dispatchTouchEvent(ev);
- int action = ev.getAction();
- if (action == MotionEvent.ACTION_DOWN) {
- // Start ignoring all touch events coming to status bar window.
- // TODO: handle case where ACTION_UP is not sent over the binder
- mStatusBarWindowController.setNotTouchable(true);
- } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mStatusBarWindowController.setNotTouchable(false);
+ if (start) {
+ mNotificationPanel.startWaitingForOpenPanelGesture();
+ } else {
+ mNotificationPanel.stopWaitingForOpenPanelGesture();
}
}
@@ -3574,7 +3582,7 @@
mBouncerShowing = bouncerShowing;
mKeyguardBypassController.setBouncerShowing(bouncerShowing);
mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
- mStatusBarWindow.setBouncerShowing(bouncerShowing);
+ mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
updateHideIconsForBouncer(true /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3627,6 +3635,7 @@
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
mWakeUpCoordinator.setFullyAwake(false);
+ mBypassHeadsUpNotifier.setFullyAwake(false);
mKeyguardBypassController.onStartedGoingToSleep();
}
@@ -3651,6 +3660,7 @@
@Override
public void onFinishedWakingUp() {
mWakeUpCoordinator.setFullyAwake(true);
+ mBypassHeadsUpNotifier.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a82e14e..667521b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -525,9 +525,9 @@
mBypassController = bypassController;
}
- public void setBouncerShowing(boolean bouncerShowing) {
+ public void setBouncerShowingScrimmed(boolean bouncerShowing) {
if (mLockIcon != null) {
- mLockIcon.setBouncerShowing(bouncerShowing);
+ mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 78eb394..f36c56f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -190,6 +190,11 @@
public void onKeyguardVisibilityChanged(boolean showing) {
update(false /* updateAlways */);
}
+
+ @Override
+ public void onBiometricsCleared() {
+ update(false /* alwaysUpdate */);
+ }
};
public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 40d5e4d..b84dc47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -356,6 +356,10 @@
public void onDensityOrFontScaleChanged() {
}
+ public boolean isEntryAutoHeadsUpped(String key) {
+ return false;
+ }
+
/**
* This represents a notification and how long it is in a heads up mode. It also manages its
* lifecycle automatically when created.
@@ -416,16 +420,17 @@
@Override
protected long calculateFinishTime() {
- return mPostTime + getRecommendedHeadsUpTimeoutMs();
+ return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
}
/**
* Get user-preferred or default timeout duration. The larger one will be returned.
* @return milliseconds before auto-dismiss
+ * @param requestedTimeout
*/
- protected int getRecommendedHeadsUpTimeoutMs() {
+ protected int getRecommendedHeadsUpTimeoutMs(int requestedTimeout) {
return mAccessibilityMgr.getRecommendedTimeoutMillis(
- mAutoDismissNotificationDecay,
+ requestedTimeout,
AccessibilityManager.FLAG_CONTENT_CONTROLS
| AccessibilityManager.FLAG_CONTENT_ICONS
| AccessibilityManager.FLAG_CONTENT_TEXT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 13f93b9..b21ba09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -376,9 +376,9 @@
}
private void updateDataSim() {
- int defaultDataSub = mDefaults.getDefaultDataSubId();
- if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
- mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
+ int activeDataSubId = mDefaults.getActiveDataSubId();
+ if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
+ mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
} else {
// There doesn't seem to be a data sim selected, however if
// there isn't a MobileSignalController with dataSim set, then
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b2972fc..d545dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -361,7 +361,7 @@
}
private MobileSignalController getDataController() {
- int dataSubId = mSubDefaults.getDefaultDataSubId();
+ int dataSubId = mSubDefaults.getActiveDataSubId();
if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
if (DEBUG) Log.e(TAG, "No data sim selected");
return mDefaultSignalController;
@@ -1098,6 +1098,10 @@
public int getDefaultDataSubId() {
return SubscriptionManager.getDefaultDataSubscriptionId();
}
+
+ public int getActiveDataSubId() {
+ return SubscriptionManager.getActiveDataSubscriptionId();
+ }
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
index 31f4991..b9c5ee5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
@@ -156,17 +156,21 @@
* Requests for all sensors that match the given type from all plugins.
* @param sensor
* @param listener
+ * @return true if there were plugins to register the listener to
*/
- public void registerPluginListener(SensorManagerPlugin.Sensor sensor,
+ public boolean registerPluginListener(SensorManagerPlugin.Sensor sensor,
SensorManagerPlugin.SensorEventListener listener) {
if (mPlugins.isEmpty()) {
Log.w(TAG, "No plugins registered");
+ return false;
}
mHandler.post(() -> {
for (int i = 0; i < mPlugins.size(); i++) {
mPlugins.get(i).registerListener(sensor, listener);
}
});
+
+ return true;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index d521e55..ede3004 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -32,6 +32,7 @@
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -138,6 +139,11 @@
QSCarrierGroup createQSCarrierGroup();
/**
+ * Creates the Shelf.
+ */
+ NotificationShelf creatNotificationShelf();
+
+ /**
* Creates the KeyguardClockSwitch.
*/
KeyguardClockSwitch createKeyguardClockSwitch();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 9438cbb..2d6ae26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -36,7 +36,7 @@
when(params.getPulseOnSigMotion()).thenReturn(false);
when(params.getPickupVibrationThreshold()).thenReturn(0);
when(params.getProxCheckBeforePulse()).thenReturn(true);
- when(params.getPickupSubtypePerformsProxCheck(anyInt())).thenReturn(true);
+ when(params.getPickupPerformsProxCheck()).thenReturn(true);
when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 3304291..7df45a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -77,7 +78,9 @@
@Mock
private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
@Mock
- private TriggerSensor mMockTriggerSensor;
+ private TriggerSensor mTriggerSensor;
+ @Mock
+ private TriggerSensor mProxGatedTriggerSensor;
private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
private TestableLooper mTestableLooper;
private DozeSensors mDozeSensors;
@@ -85,6 +88,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mProxGatedTriggerSensor.performsProxCheck()).thenReturn(true);
mTestableLooper = TestableLooper.get(this);
when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
@@ -114,21 +118,34 @@
@Test
public void testSetListening_firstTrue_registerSettingsObserver() {
- mDozeSensors.mSensors = new TriggerSensor[] {mMockTriggerSensor};
-
mDozeSensors.setListening(true);
- verify(mMockTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
+ verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
}
@Test
public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() {
- mDozeSensors.mSensors = new TriggerSensor[] {mMockTriggerSensor};
+ mDozeSensors.setListening(true);
mDozeSensors.setListening(true);
- mDozeSensors.setListening(true);
+ verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
+ }
- verify(mMockTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
+ @Test
+ public void testSetPaused_onlyPausesNonGatedSensors() {
+ mDozeSensors.setListening(true);
+ verify(mTriggerSensor).setListening(eq(true));
+ verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+ clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+ mDozeSensors.setPaused(true);
+ verify(mTriggerSensor).setListening(eq(false));
+ verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+ clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+ mDozeSensors.setPaused(false);
+ verify(mTriggerSensor).setListening(eq(true));
+ verify(mProxGatedTriggerSensor).setListening(eq(true));
}
private class TestableDozeSensors extends DozeSensors {
@@ -144,6 +161,7 @@
mWakeLockScreenListener = (PluginSensor) sensor;
}
}
+ mSensors = new TriggerSensor[] {mTriggerSensor, mProxGatedTriggerSensor};
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index bf06794..893f3d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -84,6 +85,8 @@
private SettableWakeLock mMediaWakeLock;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private DozeParameters mDozeParameters;
private TestableKeyguardSliceProvider mProvider;
private boolean mIsZenMode;
@@ -94,7 +97,7 @@
mProvider = new TestableKeyguardSliceProvider();
mProvider.attachInfo(getContext(), null);
mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController,
- mKeyguardBypassController);
+ mKeyguardBypassController, mDozeParameters);
SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
}
@@ -130,6 +133,7 @@
MediaMetadata metadata = mock(MediaMetadata.class);
when(metadata.getText(any())).thenReturn("metadata");
when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ when(mDozeParameters.getAlwaysOn()).thenReturn(true);
mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
mProvider.onBindSlice(mProvider.getUri());
verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index f6f4eb48..60050b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -33,7 +29,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.doze.DozeScreenState;
-import com.android.systemui.statusbar.phone.DozeParameters.IntInOutMatcher;
import org.junit.Assert;
import org.junit.Test;
@@ -44,160 +39,6 @@
public class DozeParametersTest extends SysuiTestCase {
@Test
- public void test_inOutMatcher_defaultIn() {
- IntInOutMatcher intInOutMatcher = new IntInOutMatcher("*");
-
- assertTrue(intInOutMatcher.isIn(1));
- assertTrue(intInOutMatcher.isIn(-1));
- assertTrue(intInOutMatcher.isIn(0));
- }
-
- @Test
- public void test_inOutMatcher_defaultOut() {
- IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!*");
-
- assertFalse(intInOutMatcher.isIn(1));
- assertFalse(intInOutMatcher.isIn(-1));
- assertFalse(intInOutMatcher.isIn(0));
- }
-
- @Test
- public void test_inOutMatcher_someIn() {
- IntInOutMatcher intInOutMatcher = new IntInOutMatcher("1,2,3,!*");
-
- assertTrue(intInOutMatcher.isIn(1));
- assertTrue(intInOutMatcher.isIn(2));
- assertTrue(intInOutMatcher.isIn(3));
-
- assertFalse(intInOutMatcher.isIn(0));
- assertFalse(intInOutMatcher.isIn(4));
- }
-
- @Test
- public void test_inOutMatcher_someOut() {
- IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,!2,!3,*");
-
- assertFalse(intInOutMatcher.isIn(1));
- assertFalse(intInOutMatcher.isIn(2));
- assertFalse(intInOutMatcher.isIn(3));
-
- assertTrue(intInOutMatcher.isIn(0));
- assertTrue(intInOutMatcher.isIn(4));
- }
-
- @Test
- public void test_inOutMatcher_mixed() {
- IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,2,!3,*");
-
- assertFalse(intInOutMatcher.isIn(1));
- assertTrue(intInOutMatcher.isIn(2));
- assertFalse(intInOutMatcher.isIn(3));
-
- assertTrue(intInOutMatcher.isIn(0));
- assertTrue(intInOutMatcher.isIn(4));
- }
-
- @Test
- public void test_inOutMatcher_failEmpty() {
- try {
- new IntInOutMatcher("");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failNull() {
- try {
- new IntInOutMatcher(null);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failEmptyClause() {
- try {
- new IntInOutMatcher("!1,*,");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failDuplicate() {
- try {
- new IntInOutMatcher("!1,*,!1");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failDuplicateDefault() {
- try {
- new IntInOutMatcher("!1,*,*");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failMalformedNot() {
- try {
- new IntInOutMatcher("!,*");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failText() {
- try {
- new IntInOutMatcher("!abc,*");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failContradiction() {
- try {
- new IntInOutMatcher("1,!1,*");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failContradictionDefault() {
- try {
- new IntInOutMatcher("1,*,!*");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
- public void test_inOutMatcher_failMissingDefault() {
- try {
- new IntInOutMatcher("1");
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @Test
public void test_setControlScreenOffAnimation_setsDozeAfterScreenOff_false() {
TestableDozeParameters dozeParameters = new TestableDozeParameters(getContext());
PowerManager mockedPowerManager = dozeParameters.getPowerManager();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 3464fe5..9ae9ceb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -181,6 +181,7 @@
protected void setDefaultSubId(int subId) {
when(mMockSubDefaults.getDefaultDataSubId()).thenReturn(subId);
when(mMockSubDefaults.getDefaultVoiceSubId()).thenReturn(subId);
+ when(mMockSubDefaults.getActiveDataSubId()).thenReturn(subId);
}
protected void setSubscriptions(int... subIds) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3764ca4..988db6a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2924,6 +2924,7 @@
if (sVerbose) {
Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
}
+ viewState.setCurrentValue(findValueLocked(id));
mViewStates.put(id, viewState);
}
if ((state & ViewState.STATE_AUTOFILLED) != 0) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index e1b089c..84886f8 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -227,6 +227,7 @@
if (mVirtualBounds != null) {
builder.append(", virtualBounds:" ).append(mVirtualBounds);
}
+ builder.append("]");
return builder.toString();
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f0321c1..4f7900e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2579,8 +2579,8 @@
if (nai.everConnected) {
loge("ERROR: cannot call explicitlySelected on already-connected network");
}
- nai.networkMisc.explicitlySelected = (msg.arg1 == 1);
- nai.networkMisc.acceptUnvalidated = (msg.arg1 == 1) && (msg.arg2 == 1);
+ nai.networkMisc.explicitlySelected = toBool(msg.arg1);
+ nai.networkMisc.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
// Mark the network as temporarily accepting partial connectivity so that it
// will be validated (and possibly become default) even if it only provides
// partial internet access. Note that if user connects to partial connectivity
@@ -2588,7 +2588,7 @@
// out of wifi coverage) and if the same wifi is available again, the device
// will auto connect to this wifi even though the wifi has "no internet".
// TODO: Evaluate using a separate setting in IpMemoryStore.
- nai.networkMisc.acceptPartialConnectivity = (msg.arg2 == 1);
+ nai.networkMisc.acceptPartialConnectivity = toBool(msg.arg2);
break;
}
case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
new file mode 100644
index 0000000..d1e09db
--- /dev/null
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.MessageQueue;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Lmkd connection to communicate with lowmemorykiller daemon.
+ */
+public class LmkdConnection {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
+
+ // lmkd reply max size in bytes
+ private static final int LMKD_REPLY_MAX_SIZE = 8;
+
+ // connection listener interface
+ interface LmkdConnectionListener {
+ public boolean onConnect(OutputStream ostream);
+ public void onDisconnect();
+ /**
+ * Check if received reply was expected (reply to an earlier request)
+ *
+ * @param replyBuf The buffer provided in exchange() to receive the reply.
+ * It can be used by exchange() caller to store reply-specific
+ * tags for later use in isReplyExpected() to verify if
+ * received packet is the expected reply.
+ * @param dataReceived The buffer holding received data
+ * @param receivedLen Size of the data received
+ */
+ public boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
+ int receivedLen);
+ }
+
+ private final MessageQueue mMsgQueue;
+
+ // lmkd connection listener
+ private final LmkdConnectionListener mListener;
+
+ // mutex to synchronize access to the socket
+ private final Object mLmkdSocketLock = new Object();
+
+ // socket to communicate with lmkd
+ @GuardedBy("mLmkdSocketLock")
+ private LocalSocket mLmkdSocket = null;
+
+ // socket I/O streams
+ @GuardedBy("mLmkdSocketLock")
+ private OutputStream mLmkdOutputStream = null;
+ @GuardedBy("mLmkdSocketLock")
+ private InputStream mLmkdInputStream = null;
+
+ // buffer to store incoming data
+ private final ByteBuffer mInputBuf =
+ ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
+
+ // object to protect mReplyBuf and to wait/notify when reply is received
+ private final Object mReplyBufLock = new Object();
+
+ // reply buffer
+ @GuardedBy("mReplyBufLock")
+ private ByteBuffer mReplyBuf = null;
+
+ //////////////////// END FIELDS ////////////////////
+
+ LmkdConnection(MessageQueue msgQueue, LmkdConnectionListener listener) {
+ mMsgQueue = msgQueue;
+ mListener = listener;
+ }
+
+ public boolean connect() {
+ synchronized (mLmkdSocketLock) {
+ if (mLmkdSocket != null) {
+ return true;
+ }
+ // temporary sockets and I/O streams
+ final LocalSocket socket = openSocket();
+
+ if (socket == null) {
+ Slog.w(TAG, "Failed to connect to lowmemorykiller, retry later");
+ return false;
+ }
+
+ final OutputStream ostream;
+ final InputStream istream;
+ try {
+ ostream = socket.getOutputStream();
+ istream = socket.getInputStream();
+ } catch (IOException ex) {
+ IoUtils.closeQuietly(socket);
+ return false;
+ }
+ // execute onConnect callback
+ if (mListener != null && !mListener.onConnect(ostream)) {
+ Slog.w(TAG, "Failed to communicate with lowmemorykiller, retry later");
+ IoUtils.closeQuietly(socket);
+ return false;
+ }
+ // connection established
+ mLmkdSocket = socket;
+ mLmkdOutputStream = ostream;
+ mLmkdInputStream = istream;
+ mMsgQueue.addOnFileDescriptorEventListener(mLmkdSocket.getFileDescriptor(),
+ EVENT_INPUT | EVENT_ERROR,
+ new MessageQueue.OnFileDescriptorEventListener() {
+ public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+ return fileDescriptorEventHandler(fd, events);
+ }
+ }
+ );
+ mLmkdSocketLock.notifyAll();
+ }
+ return true;
+ }
+
+ private int fileDescriptorEventHandler(FileDescriptor fd, int events) {
+ if (mListener == null) {
+ return 0;
+ }
+ if ((events & EVENT_INPUT) != 0) {
+ processIncomingData();
+ }
+ if ((events & EVENT_ERROR) != 0) {
+ synchronized (mLmkdSocketLock) {
+ // stop listening on this socket
+ mMsgQueue.removeOnFileDescriptorEventListener(
+ mLmkdSocket.getFileDescriptor());
+ IoUtils.closeQuietly(mLmkdSocket);
+ mLmkdSocket = null;
+ }
+ // wake up reply waiters if any
+ synchronized (mReplyBufLock) {
+ if (mReplyBuf != null) {
+ mReplyBuf = null;
+ mReplyBufLock.notifyAll();
+ }
+ }
+ // notify listener
+ mListener.onDisconnect();
+ return 0;
+ }
+ return (EVENT_INPUT | EVENT_ERROR);
+ }
+
+ private void processIncomingData() {
+ int len = read(mInputBuf);
+ if (len > 0) {
+ synchronized (mReplyBufLock) {
+ if (mReplyBuf != null) {
+ if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
+ // copy into reply buffer
+ mReplyBuf.put(mInputBuf.array(), 0, len);
+ mReplyBuf.rewind();
+ // wakeup the waiting thread
+ mReplyBufLock.notifyAll();
+ } else {
+ // received asynchronous or unexpected packet
+ // treat this as an error
+ mReplyBuf = null;
+ mReplyBufLock.notifyAll();
+ Slog.e(TAG, "Received unexpected packet from lmkd");
+ }
+ } else {
+ // received asynchronous communication from lmkd
+ // we don't support this yet
+ Slog.w(TAG, "Received an asynchronous packet from lmkd");
+ }
+ }
+ }
+ }
+
+ public boolean isConnected() {
+ synchronized (mLmkdSocketLock) {
+ return (mLmkdSocket != null);
+ }
+ }
+
+ public boolean waitForConnection(long timeoutMs) {
+ synchronized (mLmkdSocketLock) {
+ if (mLmkdSocket != null) {
+ return true;
+ }
+ try {
+ mLmkdSocketLock.wait(timeoutMs);
+ return (mLmkdSocket != null);
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+ }
+
+ private LocalSocket openSocket() {
+ final LocalSocket socket;
+
+ try {
+ socket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
+ socket.connect(
+ new LocalSocketAddress("lmkd",
+ LocalSocketAddress.Namespace.RESERVED));
+ } catch (IOException ex) {
+ Slog.e(TAG, "Connection failed: " + ex.toString());
+ return null;
+ }
+ return socket;
+ }
+
+ private boolean write(ByteBuffer buf) {
+ synchronized (mLmkdSocketLock) {
+ try {
+ mLmkdOutputStream.write(buf.array(), 0, buf.position());
+ } catch (IOException ex) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private int read(ByteBuffer buf) {
+ synchronized (mLmkdSocketLock) {
+ try {
+ return mLmkdInputStream.read(buf.array(), 0, buf.array().length);
+ } catch (IOException ex) {
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Exchange a request/reply packets with lmkd
+ *
+ * @param req The buffer holding the request data to be sent
+ * @param repl The buffer to receive the reply
+ */
+ public boolean exchange(ByteBuffer req, ByteBuffer repl) {
+ if (repl == null) {
+ return write(req);
+ }
+
+ boolean result = false;
+ // set reply buffer to user-defined one to fill it
+ synchronized (mReplyBufLock) {
+ mReplyBuf = repl;
+
+ if (write(req)) {
+ try {
+ // wait for the reply
+ mReplyBufLock.wait();
+ result = (mReplyBuf != null);
+ } catch (InterruptedException ie) {
+ result = false;
+ }
+ }
+
+ // reset reply buffer
+ mReplyBuf = null;
+ }
+ return result;
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9346ab5..ffbc6b3 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -57,8 +57,6 @@
import android.content.pm.IPackageManager;
import android.content.res.Resources;
import android.graphics.Point;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
import android.os.AppZygote;
import android.os.Binder;
import android.os.Build;
@@ -67,6 +65,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.MessageQueue;
import android.os.Process;
import android.os.RemoteException;
import android.os.StrictMode;
@@ -117,11 +116,6 @@
/**
* Activity manager code dealing with processes.
- *
- * Method naming convention:
- * <ul>
- * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
- * </ul>
*/
public final class ProcessList {
static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -268,6 +262,9 @@
static final byte LMK_PROCPURGE = 3;
static final byte LMK_GETKILLCNT = 4;
+ // lmkd reconnect delay in msecs
+ private final static long LMDK_RECONNECT_DELAY_MS = 1000;
+
ActivityManagerService mService = null;
// To kill process groups asynchronously
@@ -302,16 +299,9 @@
private boolean mHaveDisplaySize;
- private static Object sLmkdSocketLock = new Object();
+ private static LmkdConnection sLmkdConnection = null;
- @GuardedBy("sLmkdSocketLock")
- private static LocalSocket sLmkdSocket;
-
- @GuardedBy("sLmkdSocketLock")
- private static OutputStream sLmkdOutputStream;
-
- @GuardedBy("sLmkdSocketLock")
- private static InputStream sLmkdInputStream;
+ private boolean mOomLevelsSet = false;
/**
* Temporary to avoid allocations. Protected by main lock.
@@ -536,6 +526,7 @@
final class KillHandler extends Handler {
static final int KILL_PROCESS_GROUP_MSG = 4000;
+ static final int LMDK_RECONNECT_MSG = 4001;
public KillHandler(Looper looper) {
super(looper, null, true);
@@ -549,6 +540,15 @@
Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
+ case LMDK_RECONNECT_MSG:
+ if (!sLmkdConnection.connect()) {
+ Slog.i(TAG, "Failed to connect to lmkd, retry after " +
+ LMDK_RECONNECT_DELAY_MS + " ms");
+ // retry after LMDK_RECONNECT_DELAY_MS
+ sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+ KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+ }
+ break;
default:
super.handleMessage(msg);
@@ -574,6 +574,30 @@
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
+ sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
+ new LmkdConnection.LmkdConnectionListener() {
+ @Override
+ public boolean onConnect(OutputStream ostream) {
+ Slog.i(TAG, "Connection with lmkd established");
+ return onLmkdConnect(ostream);
+ }
+ @Override
+ public void onDisconnect() {
+ Slog.w(TAG, "Lost connection to lmkd");
+ // start reconnection after delay to let lmkd restart
+ sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+ KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+ }
+ @Override
+ public boolean isReplyExpected(ByteBuffer replyBuf,
+ ByteBuffer dataReceived, int receivedLen) {
+ // compare the preambule (currently one integer) to check if
+ // this is the reply packet we are waiting for
+ return (receivedLen == replyBuf.array().length &&
+ dataReceived.getInt(0) == replyBuf.getInt(0));
+ }
+ }
+ );
}
}
@@ -679,6 +703,7 @@
writeLmkd(buf, null);
SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
+ mOomLevelsSet = true;
}
// GB: 2048,3072,4096,6144,7168,8192
// HC: 8192,10240,12288,14336,16384,20480
@@ -1218,93 +1243,50 @@
buf.putInt(LMK_GETKILLCNT);
buf.putInt(min_oom_adj);
buf.putInt(max_oom_adj);
- if (writeLmkd(buf, repl)) {
- int i = repl.getInt();
- if (i != LMK_GETKILLCNT) {
- Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
- return null;
- }
+ // indicate what we are waiting for
+ repl.putInt(LMK_GETKILLCNT);
+ repl.rewind();
+ if (writeLmkd(buf, repl) && repl.getInt() == LMK_GETKILLCNT) {
return new Integer(repl.getInt());
}
return null;
}
- @GuardedBy("sLmkdSocketLock")
- private static boolean openLmkdSocketLS() {
+ public boolean onLmkdConnect(OutputStream ostream) {
try {
- sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
- sLmkdSocket.connect(
- new LocalSocketAddress("lmkd",
- LocalSocketAddress.Namespace.RESERVED));
- sLmkdOutputStream = sLmkdSocket.getOutputStream();
- sLmkdInputStream = sLmkdSocket.getInputStream();
- } catch (IOException ex) {
- Slog.w(TAG, "lowmemorykiller daemon socket open failed");
- sLmkdSocket = null;
- return false;
- }
-
- return true;
- }
-
- // Never call directly, use writeLmkd() instead
- @GuardedBy("sLmkdSocketLock")
- private static boolean writeLmkdCommandLS(ByteBuffer buf) {
- try {
- sLmkdOutputStream.write(buf.array(), 0, buf.position());
- } catch (IOException ex) {
- Slog.w(TAG, "Error writing to lowmemorykiller socket");
- IoUtils.closeQuietly(sLmkdSocket);
- sLmkdSocket = null;
- return false;
- }
- return true;
- }
-
- // Never call directly, use writeLmkd() instead
- @GuardedBy("sLmkdSocketLock")
- private static boolean readLmkdReplyLS(ByteBuffer buf) {
- int len;
- try {
- len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
- if (len == buf.array().length) {
- return true;
+ // Purge any previously registered pids
+ ByteBuffer buf = ByteBuffer.allocate(4);
+ buf.putInt(LMK_PROCPURGE);
+ ostream.write(buf.array(), 0, buf.position());
+ if (mOomLevelsSet) {
+ // Reset oom_adj levels
+ buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
+ buf.putInt(LMK_TARGET);
+ for (int i = 0; i < mOomAdj.length; i++) {
+ buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
+ buf.putInt(mOomAdj[i]);
+ }
+ ostream.write(buf.array(), 0, buf.position());
}
} catch (IOException ex) {
- Slog.w(TAG, "Error reading from lowmemorykiller socket");
+ return false;
}
-
- IoUtils.closeQuietly(sLmkdSocket);
- sLmkdSocket = null;
- return false;
+ return true;
}
private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
- synchronized (sLmkdSocketLock) {
- for (int i = 0; i < 3; i++) {
- if (sLmkdSocket == null) {
- if (openLmkdSocketLS() == false) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- continue;
- }
+ if (!sLmkdConnection.isConnected()) {
+ // try to connect immediately and then keep retrying
+ sKillHandler.sendMessage(
+ sKillHandler.obtainMessage(KillHandler.LMDK_RECONNECT_MSG));
- // Purge any previously registered pids
- ByteBuffer purge_buf = ByteBuffer.allocate(4);
- purge_buf.putInt(LMK_PROCPURGE);
- if (writeLmkdCommandLS(purge_buf) == false) {
- // Write failed, skip the rest and retry
- continue;
- }
- }
- if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
- return true;
- }
+ // wait for connection retrying 3 times (up to 3 seconds)
+ if (!sLmkdConnection.waitForConnection(3 * LMDK_RECONNECT_DELAY_MS)) {
+ return false;
}
}
- return false;
+
+ return sLmkdConnection.exchange(buf, repl);
}
static void killProcessGroup(int uid, int pid) {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index dd3876d..02ec10e 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -356,13 +356,15 @@
float ambientBrightness = mBrightnessFilter.getEstimate(time);
- if (mLowLightAmbientBrightnessToBiasSpline != null) {
+ if (ambientColorTemperature != -1.0f &&
+ mLowLightAmbientBrightnessToBiasSpline != null) {
float bias = mLowLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
ambientColorTemperature =
bias * ambientColorTemperature + (1.0f - bias)
* mLowLightAmbientColorTemperature;
}
- if (mHighLightAmbientBrightnessToBiasSpline != null) {
+ if (ambientColorTemperature != -1.0f &&
+ mHighLightAmbientBrightnessToBiasSpline != null) {
float bias = mHighLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
ambientColorTemperature =
(1.0f - bias) * ambientColorTemperature + bias
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 82aacfe..9f98d63 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -919,16 +919,12 @@
}
}
// Init arc whenever System Audio Mode is on
- // Terminate arc when System Audio Mode is off
// Since some TVs don't request ARC on with System Audio Mode on request
if (SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)
&& isDirectConnectToTv()) {
if (newSystemAudioMode && !isArcEnabled()
&& !hasAction(ArcInitiationActionFromAvr.class)) {
addAndStartAction(new ArcInitiationActionFromAvr(this));
- } else if (!newSystemAudioMode && isArcEnabled()) {
- removeAction(ArcTerminationActionFromAvr.class);
- addAndStartAction(new ArcTerminationActionFromAvr(this));
}
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 440676a..df4674c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1498,6 +1498,11 @@
Slog.e(TAG, "Callback cannot be null");
return;
}
+ if (isPowerStandby()) {
+ Slog.e(TAG, "Device is in standby. Not handling deviceSelect");
+ invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
+ return;
+ }
HdmiCecLocalDeviceTv tv = tv();
if (tv == null) {
if (!mAddressAllocated) {
@@ -1540,6 +1545,11 @@
Slog.e(TAG, "Callback cannot be null");
return;
}
+ if (isPowerStandby()) {
+ Slog.e(TAG, "Device is in standby. Not handling portSelect");
+ invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
+ return;
+ }
HdmiCecLocalDeviceTv tv = tv();
if (tv != null) {
tv.doManualPortSwitching(portId, callback);
diff --git a/services/core/java/com/android/server/pm/ShareTargetInfo.java b/services/core/java/com/android/server/pm/ShareTargetInfo.java
index 9e8b73e..fdfee77 100644
--- a/services/core/java/com/android/server/pm/ShareTargetInfo.java
+++ b/services/core/java/com/android/server/pm/ShareTargetInfo.java
@@ -15,12 +15,36 @@
*/
package com.android.server.pm;
+import android.annotation.NonNull;
import android.text.TextUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
/**
* Represents a Share Target definition, read from the application's manifest (shortcuts.xml)
*/
class ShareTargetInfo {
+
+ private static final String TAG_SHARE_TARGET = "share-target";
+ private static final String ATTR_TARGET_CLASS = "targetClass";
+
+ private static final String TAG_DATA = "data";
+ private static final String ATTR_SCHEME = "scheme";
+ private static final String ATTR_HOST = "host";
+ private static final String ATTR_PORT = "port";
+ private static final String ATTR_PATH = "path";
+ private static final String ATTR_PATH_PATTERN = "pathPattern";
+ private static final String ATTR_PATH_PREFIX = "pathPrefix";
+ private static final String ATTR_MIME_TYPE = "mimeType";
+
+ private static final String TAG_CATEGORY = "category";
+ private static final String ATTR_NAME = "name";
+
static class TargetData {
final String mScheme;
final String mHost;
@@ -98,4 +122,72 @@
return strBuilder.toString();
}
+
+ void saveToXml(@NonNull XmlSerializer out) throws IOException {
+ out.startTag(null, TAG_SHARE_TARGET);
+
+ ShortcutService.writeAttr(out, ATTR_TARGET_CLASS, mTargetClass);
+
+ for (int i = 0; i < mTargetData.length; i++) {
+ out.startTag(null, TAG_DATA);
+ ShortcutService.writeAttr(out, ATTR_SCHEME, mTargetData[i].mScheme);
+ ShortcutService.writeAttr(out, ATTR_HOST, mTargetData[i].mHost);
+ ShortcutService.writeAttr(out, ATTR_PORT, mTargetData[i].mPort);
+ ShortcutService.writeAttr(out, ATTR_PATH, mTargetData[i].mPath);
+ ShortcutService.writeAttr(out, ATTR_PATH_PATTERN, mTargetData[i].mPathPattern);
+ ShortcutService.writeAttr(out, ATTR_PATH_PREFIX, mTargetData[i].mPathPrefix);
+ ShortcutService.writeAttr(out, ATTR_MIME_TYPE, mTargetData[i].mMimeType);
+ out.endTag(null, TAG_DATA);
+ }
+
+ for (int i = 0; i < mCategories.length; i++) {
+ out.startTag(null, TAG_CATEGORY);
+ ShortcutService.writeAttr(out, ATTR_NAME, mCategories[i]);
+ out.endTag(null, TAG_CATEGORY);
+ }
+
+ out.endTag(null, TAG_SHARE_TARGET);
+ }
+
+ static ShareTargetInfo loadFromXml(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ final String targetClass = ShortcutService.parseStringAttribute(parser, ATTR_TARGET_CLASS);
+ final ArrayList<ShareTargetInfo.TargetData> targetData = new ArrayList<>();
+ final ArrayList<String> categories = new ArrayList<>();
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG) {
+ switch (parser.getName()) {
+ case TAG_DATA:
+ targetData.add(parseTargetData(parser));
+ break;
+ case TAG_CATEGORY:
+ categories.add(ShortcutService.parseStringAttribute(parser, ATTR_NAME));
+ break;
+ }
+ } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_SHARE_TARGET)) {
+ break;
+ }
+ }
+ if (targetData.isEmpty() || targetClass == null || categories.isEmpty()) {
+ return null;
+ }
+ return new ShareTargetInfo(
+ targetData.toArray(new ShareTargetInfo.TargetData[targetData.size()]),
+ targetClass, categories.toArray(new String[categories.size()]));
+ }
+
+ private static ShareTargetInfo.TargetData parseTargetData(XmlPullParser parser) {
+ final String scheme = ShortcutService.parseStringAttribute(parser, ATTR_SCHEME);
+ final String host = ShortcutService.parseStringAttribute(parser, ATTR_HOST);
+ final String port = ShortcutService.parseStringAttribute(parser, ATTR_PORT);
+ final String path = ShortcutService.parseStringAttribute(parser, ATTR_PATH);
+ final String pathPattern = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PATTERN);
+ final String pathPrefix = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PREFIX);
+ final String mimeType = ShortcutService.parseStringAttribute(parser, ATTR_MIME_TYPE);
+
+ return new ShareTargetInfo.TargetData(scheme, host, port, path, pathPattern, pathPrefix,
+ mimeType);
+ }
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d6e87aa..06c71ba 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -73,6 +73,7 @@
private static final String TAG_INTENT = "intent";
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
+ private static final String TAG_SHARE_TARGET = "share-target";
private static final String TAG_CATEGORIES = "categories";
private static final String TAG_PERSON = "person";
@@ -1453,8 +1454,9 @@
public void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException {
final int size = mShortcuts.size();
+ final int shareTargetSize = mShareTargets.size();
- if (size == 0 && mApiCallCount == 0) {
+ if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
return; // nothing to write.
}
@@ -1470,6 +1472,12 @@
getPackageInfo().isBackupAllowed());
}
+ if (!forBackup) {
+ for (int j = 0; j < shareTargetSize; j++) {
+ mShareTargets.get(j).saveToXml(out);
+ }
+ }
+
out.endTag(null, TAG_ROOT);
}
@@ -1627,6 +1635,9 @@
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
continue;
+ case TAG_SHARE_TARGET:
+ ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ continue;
}
}
ShortcutService.warnForInvalidTag(depth, tag);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 505e89d..de3e89f 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -45,10 +45,9 @@
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.UserHandle; // duped to avoid merge conflict
-import android.os.UserManager; // out of order to avoid merge conflict
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IntArray;
@@ -326,7 +325,7 @@
}
@Override
- public ParceledListSlice<RollbackInfo> getRecentlyExecutedRollbacks() {
+ public ParceledListSlice<RollbackInfo> getRecentlyCommittedRollbacks() {
enforceManageRollbacks("getRecentlyCommittedRollbacks");
synchronized (mLock) {
@@ -345,7 +344,7 @@
@Override
public void commitRollback(int rollbackId, ParceledListSlice causePackages,
String callerPackageName, IntentSender statusReceiver) {
- enforceManageRollbacks("executeRollback");
+ enforceManageRollbacks("commitRollback");
final int callingUid = Binder.getCallingUid();
AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -575,6 +574,20 @@
}
}
+ @Override
+ public void blockRollbackManager(long millis) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.TEST_MANAGE_ROLLBACKS,
+ "blockRollbackManager");
+ getHandler().post(() -> {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ // ignored.
+ }
+ });
+ }
+
void onUnlockUser(int userId) {
getHandler().post(() -> {
final List<RollbackData> rollbacks;
@@ -677,8 +690,7 @@
/**
* Load rollback data from storage if it has not already been loaded.
- * After calling this funciton, mAvailableRollbacks and
- * mRecentlyExecutedRollbacks will be non-null.
+ * After calling this function, mRollbacks will be non-null.
*/
private void ensureRollbackDataLoaded() {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 8b332d2..55f062b 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -1032,11 +1032,13 @@
// must always grant permissions on behalf of someone explicit.
final int callingAppId = UserHandle.getAppId(callingUid);
if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
- if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
+ if ("com.android.settings.files".equals(grantUri.uri.getAuthority())
+ || "com.android.settings.module_licenses".equals(grantUri.uri.getAuthority())) {
// Exempted authority for
// 1. cropping user photos and sharing a generated license html
// file in Settings app
// 2. sharing a generated license html file in TvSettings app
+ // 3. Sharing module license files from Settings app
} else {
Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
+ " grant to " + grantUri + "; use startActivityAsCaller() instead");
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 156fb98..157e15a 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1302,6 +1302,11 @@
return;
}
+ getDisplay().positionChildAtBottom(this, reason);
+ if (task != null) {
+ insertTaskAtBottom(task);
+ }
+
/**
* The intent behind moving a primary split screen stack to the back is usually to hide
* behind the home stack. Exit split screen in this case.
@@ -1309,11 +1314,6 @@
if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setWindowingMode(WINDOWING_MODE_UNDEFINED);
}
-
- getDisplay().positionChildAtBottom(this, reason);
- if (task != null) {
- insertTaskAtBottom(task);
- }
}
boolean isFocusable() {
@@ -1388,13 +1388,12 @@
}
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
- + taskIntent.getComponent().flattenToShortString()
+ + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
+ "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
- if (taskIntent != null && taskIntent.getComponent() != null &&
- taskIntent.getComponent().compareTo(cls) == 0 &&
- Objects.equals(documentData, taskDocumentData)) {
+ if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
+ && Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG_TASKS,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 16dd555..6728bd9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3918,10 +3918,10 @@
// Caller wants the current split-screen primary stack to be the top stack after
// it goes fullscreen, so move it to the front.
stack.moveToFront("dismissSplitScreenMode");
- } else if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
+ } else {
// In this case the current split-screen primary stack shouldn't be the top
- // stack after it goes fullscreen, but it current has focus, so we move the
- // focus to the top-most split-screen secondary stack next to it.
+ // stack after it goes fullscreen, so we move the focus to the top-most
+ // split-screen secondary stack next to it.
final ActivityStack otherStack = stack.getDisplay().getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
if (otherStack != null) {
@@ -4750,18 +4750,12 @@
private void applyUpdateVrModeLocked(ActivityRecord r) {
// VR apps are expected to run in a main display. If an app is turning on VR for
- // itself, but lives in a dynamic stack, then make sure that it is moved to the main
- // fullscreen stack before enabling VR Mode.
- // TODO: The goal of this code is to keep the VR app on the main display. When the
- // stack implementation changes in the future, keep in mind that the use of the fullscreen
- // stack is a means to move the activity to the main display and a moveActivityToDisplay()
- // option would be a better choice here.
+ // itself, but isn't on the main display, then move it there before enabling VR Mode.
if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
- Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
- + " to main stack for VR");
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
- WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
- moveTaskToStack(r.getTaskRecord().taskId, stack.mStackId, true /* toTop */);
+ Slog.i(TAG, "Moving " + r.shortComponentName + " from display " + r.getDisplayId()
+ + " to main display for VR");
+ mRootActivityContainer.moveStackToDisplay(
+ r.getStackId(), DEFAULT_DISPLAY, true /* toTop */);
}
mH.post(() -> {
if (!mVrController.onVrModeChanged(r)) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4a9a3f7..03cae42 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1322,7 +1322,15 @@
if (prevDc == null || prevDc == mDisplayContent) {
return;
}
- if (prevDc.mChangingApps.contains(this)) {
+
+ if (prevDc.mOpeningApps.remove(this)) {
+ // Transfer opening transition to new display.
+ mDisplayContent.mOpeningApps.add(this);
+ mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+ mDisplayContent.executeAppTransition();
+ }
+
+ if (prevDc.mChangingApps.remove(this)) {
// This gets called *after* the AppWindowToken has been reparented to the new display.
// That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
// so this token is now "frozen" while waiting for the animation to start on prevDc
@@ -1331,6 +1339,8 @@
// so we need to cancel the change transition here.
clearChangeLeash(getPendingTransaction(), true /* cancel */);
}
+ prevDc.mClosingApps.remove(this);
+
if (prevDc.mFocusedApp == this) {
prevDc.setFocusedApp(null);
final TaskStack stack = dc.getTopStack();
@@ -3216,16 +3226,6 @@
true /* topToBottom */);
}
- void removeFromPendingTransition() {
- if (isWaitingForTransitionStart() && mDisplayContent != null) {
- mDisplayContent.mOpeningApps.remove(this);
- if (mDisplayContent.mChangingApps.remove(this)) {
- clearChangeLeash(getPendingTransaction(), true /* cancel */);
- }
- mDisplayContent.mClosingApps.remove(this);
- }
- }
-
private void updateColorTransform() {
if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
getPendingTransaction().setColorTransform(mSurfaceControl,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 57ed92d..4d548bf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -30,16 +30,21 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_LEFT_GESTURES;
+import static android.view.InsetsState.TYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -135,6 +140,7 @@
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
import android.animation.AnimationHandler;
@@ -323,6 +329,7 @@
private final RemoteCallbackList<ISystemGestureExclusionListener>
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
private final Region mSystemGestureExclusion = new Region();
+ private int mSystemGestureExclusionLimit;
/**
* For default display it contains real metrics, empty for others.
@@ -893,6 +900,8 @@
mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
+ mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
@@ -1548,8 +1557,8 @@
longSize = height;
}
- final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
- final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+ final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
+ final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
@@ -2199,6 +2208,18 @@
onDisplayChanged(this);
}
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ updateSystemGestureExclusionLimit();
+ }
+
+ void updateSystemGestureExclusionLimit() {
+ mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
+ updateSystemGestureExclusion();
+ }
+
void initializeDisplayBaseInfo() {
final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
if (displayManagerInternal != null) {
@@ -2376,9 +2397,6 @@
+ " to its current displayId=" + mDisplayId);
}
- // Clean up all pending transitions when stack reparent to another display.
- stack.forAllAppWindows(AppWindowToken::removeFromPendingTransition);
-
prevDc.mTaskStackContainers.removeChild(stack);
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
@@ -5130,24 +5148,35 @@
@VisibleForTesting
Region calculateSystemGestureExclusion() {
+ final Region unhandled = Region.obtain();
+ unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
+
+ final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES)
+ .getSource().getFrame();
+ final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
+ .getSource().getFrame();
+
final Region global = Region.obtain();
final Region touchableRegion = Region.obtain();
final Region local = Region.obtain();
+ final int[] remainingLeftRight =
+ {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
// Traverse all windows bottom up to assemble the gesture exclusion rects.
// For each window, we only take the rects that fall within its touchable region.
forAllWindows(w -> {
if (w.cantReceiveTouchInput() || !w.isVisible()
- || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
+ || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
+ || unhandled.isEmpty()) {
return;
}
final boolean modal =
(w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
- // Only keep the exclusion zones from the windows behind where the current window
- // isn't touchable.
+ // Get the touchable region of the window, and intersect with where the screen is still
+ // touchable, i.e. touchable regions on top are not covering it yet.
w.getTouchableRegion(touchableRegion);
- global.op(touchableRegion, Op.DIFFERENCE);
+ touchableRegion.op(unhandled, Op.INTERSECT);
rectListToRegion(w.getSystemGestureExclusion(), local);
@@ -5159,13 +5188,78 @@
// A window can only exclude system gestures where it is actually touchable
local.op(touchableRegion, Op.INTERSECT);
- global.op(local, Op.UNION);
- }, false /* topToBottom */);
+ // Apply restriction if necessary.
+ if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
+
+ // Processes the region along the left edge.
+ remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
+ remainingLeftRight[0]);
+
+ // Processes the region along the right edge.
+ remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
+ remainingLeftRight[1]);
+
+ // Adds the middle (unrestricted area)
+ final Region middle = Region.obtain(local);
+ middle.op(leftEdge, Op.DIFFERENCE);
+ middle.op(rightEdge, Op.DIFFERENCE);
+ global.op(middle, Op.UNION);
+ middle.recycle();
+ } else {
+ global.op(local, Op.UNION);
+ }
+ unhandled.op(touchableRegion, Op.DIFFERENCE);
+ }, true /* topToBottom */);
local.recycle();
touchableRegion.recycle();
+ unhandled.recycle();
return global;
}
+ /**
+ * @return Whether gesture exclusion area should be restricted from the window depending on the
+ * current SystemUI visibility flags.
+ */
+ private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
+ final int type = win.mAttrs.type;
+ final int stickyHideNavFlags =
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ final boolean stickyHideNav =
+ (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
+ return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR
+ && win.getActivityType() != ACTIVITY_TYPE_HOME;
+ }
+
+ /**
+ * Adds a local gesture exclusion area to the global area while applying a limit per edge.
+ *
+ * @param local The gesture exclusion area to add.
+ * @param global The destination.
+ * @param edge Only processes the part in that region.
+ * @param limit How much limit in pixels we have.
+ * @return How much of the limit are remaining.
+ */
+ private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
+ int limit) {
+ final Region r = Region.obtain(local);
+ r.op(edge, Op.INTERSECT);
+
+ final int[] remaining = {limit};
+ forEachRect(r, rect -> {
+ if (remaining[0] <= 0) {
+ return;
+ }
+ final int height = rect.height();
+ if (height > remaining[0]) {
+ rect.bottom = rect.top + remaining[0];
+ }
+ remaining[0] -= height;
+ global.op(rect, Op.UNION);
+ });
+ r.recycle();
+ return remaining[0];
+ }
+
void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
mSystemGestureExclusionListeners.register(listener);
final boolean changed;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index fe4c9a4..dc62877 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -279,7 +279,8 @@
mService.mDisplayManagerInternal.screenshot(displayId);
if (gb != null) {
try {
- surface.attachAndQueueBuffer(gb.getGraphicBuffer());
+ surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
+ gb.getColorSpace());
} catch (RuntimeException e) {
Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage());
}
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 8031cfd..1a57168 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -68,7 +68,7 @@
if (buffer != null) {
final Surface surface = new Surface();
surface.copyFrom(mSurfaceControl);
- surface.attachAndQueueBuffer(buffer);
+ surface.attachAndQueueBufferWithColorSpace(buffer, screenshotBuffer.getColorSpace());
surface.release();
}
getPendingTransaction().show(mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 2696977..1b3e4c1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -284,7 +284,6 @@
}
private void drawSnapshot() {
- final GraphicBuffer buffer = mSnapshot.getSnapshot();
mSurface.copyFrom(mSurfaceControl);
if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch="
@@ -293,9 +292,9 @@
// The dimensions of the buffer and the window don't match, so attaching the buffer
// will fail. Better create a child window with the exact dimensions and fill the parent
// window with the background color!
- drawSizeMismatchSnapshot(buffer);
+ drawSizeMismatchSnapshot();
} else {
- drawSizeMatchSnapshot(buffer);
+ drawSizeMatchSnapshot();
}
synchronized (mService.mGlobalLock) {
mShownTime = SystemClock.uptimeMillis();
@@ -307,15 +306,17 @@
mSnapshot = null;
}
- private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
- mSurface.attachAndQueueBuffer(buffer);
+ private void drawSizeMatchSnapshot() {
+ mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getSnapshot(),
+ mSnapshot.getColorSpace());
mSurface.release();
}
- private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+ private void drawSizeMismatchSnapshot() {
if (!mSurface.isValid()) {
throw new IllegalStateException("mSurface does not hold a valid surface.");
}
+ final GraphicBuffer buffer = mSnapshot.getSnapshot();
final SurfaceSession session = new SurfaceSession();
// We consider nearly matched dimensions as there can be rounding errors and the user won't
// notice very minute differences from scaling one dimension more than the other
@@ -355,7 +356,7 @@
} finally {
SurfaceControl.closeTransaction();
}
- surface.attachAndQueueBuffer(buffer);
+ surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
surface.release();
if (aspectRatioMismatch) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6750ece1..54f712c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,6 +32,7 @@
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -155,6 +156,7 @@
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
@@ -176,6 +178,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -382,6 +385,8 @@
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
+ private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
+
final WindowTracing mWindowTracing;
final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -840,6 +845,8 @@
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
boolean mWindowsChanged = false;
+ int mSystemGestureExclusionLimitDp;
+
public interface WindowChangeListener {
public void windowsChanged();
public void focusChanged();
@@ -1134,6 +1141,21 @@
this, mInputManager, mActivityTaskManager, mH.getLooper());
mDragDropController = new DragDropController(this, mH.getLooper());
+ mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ new HandlerExecutor(mH), properties -> {
+ synchronized (mGlobalLock) {
+ final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ if (mSystemGestureExclusionLimitDp != exclusionLimitDp) {
+ mSystemGestureExclusionLimitDp = exclusionLimitDp;
+ mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
+ }
+ }
+ });
+
LocalServices.addService(WindowManagerInternal.class, new LocalService());
}
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index 1458440..8cd6f88 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -18,8 +18,10 @@
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.RegionIterator;
import java.util.List;
+import java.util.function.Consumer;
/**
* Utility methods to handle Regions.
@@ -42,4 +44,18 @@
outRegion.union(rects.get(i));
}
}
+
+ /**
+ * Applies actions on each rect contained within a {@code Region}.
+ *
+ * @param region the given region.
+ * @param rectConsumer the action holder.
+ */
+ public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
+ final RegionIterator it = new RegionIterator(region);
+ final Rect rect = new Rect();
+ while (it.next(rect)) {
+ rectConsumer.accept(rect);
+ }
+ }
}
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
index febfa17..a5ee3e2 100644
--- a/services/devicepolicy/TEST_MAPPING
+++ b/services/devicepolicy/TEST_MAPPING
@@ -1,12 +1,20 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "CtsDevicePolicyManagerTestCases",
"options": [
{
"exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.LargeTest"
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsDevicePolicyManagerTestCases"
+ }
]
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ec8b2e..47539d3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1893,6 +1893,10 @@
mSystemServiceManager.startService(IncidentCompanionService.class);
t.traceEnd();
+ if (safeMode) {
+ mActivityManagerService.enterSafeMode();
+ }
+
// MMS service broker
t.traceBegin("StartMmsService");
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
index 424142c..6b0798b 100644
--- a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
@@ -359,6 +359,33 @@
}
}
+ @Test
+ public void testLowLight_DefaultAmbient() throws Exception {
+ final float lowerBrightness = 10.0f;
+ final float upperBrightness = 50.0f;
+ setBrightnesses(lowerBrightness, upperBrightness);
+ setBiases(0.0f, 1.0f);
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = -1.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ for (float t = 0.0f; t <= 1.0f; t += 0.1f) {
+ setEstimatedBrightnessAndUpdate(controller,
+ mix(lowerBrightness, upperBrightness, t));
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature,
+ 0.001);
+ }
+
+ setEstimatedBrightnessAndUpdate(controller, 0.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+
+ setEstimatedBrightnessAndUpdate(controller, upperBrightness + 1.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+ }
+
void mockThrottler() {
when(mResourcesSpy.getInteger(
R.integer.config_displayWhiteBalanceDecreaseDebounce)).thenReturn(0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 7e6b7da..6c917b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -97,16 +97,25 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.SparseArray;
+import android.util.Xml;
import com.android.frameworks.servicestests.R;
+import com.android.internal.util.FastXmlSerializer;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import com.android.server.pm.ShortcutUser.PackageWithUser;
import org.mockito.ArgumentCaptor;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -8089,4 +8098,70 @@
}
}
}
+
+ public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
+ List<ShareTargetInfo> expectedValues = new ArrayList<>();
+ expectedValues.add(new ShareTargetInfo(
+ new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
+ "http", "www.google.com", "1234", "somePath", "somePathPattern",
+ "somePathPrefix", "text/plain")}, "com.test.directshare.TestActivity1",
+ new String[]{"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"}));
+ expectedValues.add(new ShareTargetInfo(new ShareTargetInfo.TargetData[]{
+ new ShareTargetInfo.TargetData(null, null, null, null, null, null, "video/mp4"),
+ new ShareTargetInfo.TargetData("content", null, null, null, null, null, "video/*")},
+ "com.test.directshare.TestActivity5",
+ new String[]{"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}));
+
+ // Write ShareTargets to Xml
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ final XmlSerializer outXml = new FastXmlSerializer();
+ outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
+ outXml.startDocument(null, true);
+ for (int i = 0; i < expectedValues.size(); i++) {
+ expectedValues.get(i).saveToXml(outXml);
+ }
+ outXml.endDocument();
+ outXml.flush();
+
+ // Read ShareTargets from Xml
+ ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new InputStreamReader(inStream));
+ List<ShareTargetInfo> shareTargets = new ArrayList<>();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG && parser.getName().equals("share-target")) {
+ shareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ }
+ }
+
+ // Assert two lists are equal
+ assertNotNull(shareTargets);
+ assertEquals(expectedValues.size(), shareTargets.size());
+
+ for (int i = 0; i < expectedValues.size(); i++) {
+ ShareTargetInfo expected = expectedValues.get(i);
+ ShareTargetInfo actual = shareTargets.get(i);
+
+ assertEquals(expected.mTargetData.length, actual.mTargetData.length);
+ for (int j = 0; j < expected.mTargetData.length; j++) {
+ assertEquals(expected.mTargetData[j].mScheme, actual.mTargetData[j].mScheme);
+ assertEquals(expected.mTargetData[j].mHost, actual.mTargetData[j].mHost);
+ assertEquals(expected.mTargetData[j].mPort, actual.mTargetData[j].mPort);
+ assertEquals(expected.mTargetData[j].mPath, actual.mTargetData[j].mPath);
+ assertEquals(expected.mTargetData[j].mPathPrefix,
+ actual.mTargetData[j].mPathPrefix);
+ assertEquals(expected.mTargetData[j].mPathPattern,
+ actual.mTargetData[j].mPathPattern);
+ assertEquals(expected.mTargetData[j].mMimeType, actual.mTargetData[j].mMimeType);
+ }
+
+ assertEquals(expected.mTargetClass, actual.mTargetClass);
+
+ assertEquals(expected.mCategories.length, actual.mCategories.length);
+ for (int j = 0; j < expected.mCategories.length; j++) {
+ assertEquals(expected.mCategories[j], actual.mCategories[j]);
+ }
+ }
+ }
}
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 4c27a3c..8c454424 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -36,6 +36,7 @@
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 757267e5..bde0ef6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -262,6 +262,35 @@
}
@Test
+ public void testFindTaskAlias() {
+ final String targetActivity = "target.activity";
+ final String aliasActivity = "alias.activity";
+ final ComponentName target = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+ targetActivity);
+ final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+ aliasActivity);
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+ task.origActivity = alias;
+ task.realActivity = target;
+ new ActivityBuilder(mService).setComponent(target).setTask(task).setTargetActivity(
+ targetActivity).build();
+
+ // Using target activity to find task.
+ final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
+ target).setTargetActivity(targetActivity).build();
+ RootActivityContainer.FindTaskResult result = new RootActivityContainer.FindTaskResult();
+ mStack.findTaskLocked(r1, result);
+ assertThat(result.mRecord).isNotNull();
+
+ // Using alias activity to find task.
+ final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
+ alias).setTargetActivity(targetActivity).build();
+ result = new RootActivityContainer.FindTaskResult();
+ mStack.findTaskLocked(r2, result);
+ assertThat(result.mRecord).isNotNull();
+ }
+
+ @Test
public void testMoveStackToBackIncludingParent() {
final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 484fd3b..4a9b174 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2121,24 +2121,27 @@
* @hide
*/
@UnsupportedAppUsage
- public @NonNull int[] getActiveSubscriptionIdList() {
- int[] subId = null;
+ public static @NonNull int[] getActiveSubscriptionIdList() {
+ return getActiveSubscriptionIdList(true);
+ }
+ /**
+ * @return a non-null list of subId's that are active.
+ *
+ * @hide
+ */
+ public static @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
+ int[] subId = iSub.getActiveSubIdList(visibleOnly);
+ if (subId != null) return subId;
}
} catch (RemoteException ex) {
// ignore it
}
- if (subId == null) {
- subId = new int[0];
- }
-
- return subId;
-
+ return new int[0];
}
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 7a0ab9c..5b57c9d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -605,15 +605,11 @@
*/
private static boolean checkCarrierPrivilegeForAnySubId(Context context,
Supplier<ITelephony> telephonySupplier, int uid) {
- SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- int[] activeSubIds = sm.getActiveSubscriptionIdList();
- if (activeSubIds != null) {
- for (int activeSubId : activeSubIds) {
- if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return true;
- }
+ int[] activeSubIds = SubscriptionManager.getActiveSubscriptionIdList(/*visibleOnly*/ false);
+ for (int activeSubId : activeSubIds) {
+ if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
}
}
return false;
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 8ab71fd..a27df47 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1058,6 +1058,10 @@
Uninstall.packages(TestApp.A);
Install.single(TestApp.A1).commit();
+
+ // Block the RollbackManager to make extra sure it will not be
+ // able to enable the rollback in time.
+ rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1));
Install.single(TestApp.A2).setEnableRollback().commit();
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2ce6b13..1b2a1288 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -71,6 +71,7 @@
import static com.android.testutils.ConcurrentUtilsKt.await;
import static com.android.testutils.ConcurrentUtilsKt.durationOf;
+import static com.android.testutils.ExceptionUtils.ignoreExceptions;
import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
import static com.android.testutils.MiscAssertsKt.assertEmpty;
@@ -205,8 +206,8 @@
import com.android.server.connectivity.Vpn;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.testutils.ExceptionUtils;
import com.android.testutils.HandlerUtilsKt;
-import com.android.testutils.ThrowingConsumer;
import org.junit.After;
import org.junit.Before;
@@ -227,7 +228,6 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
-import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -417,7 +417,7 @@
}
@Test
- public void testWaitForIdle() {
+ public void testWaitForIdle() throws Exception {
final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
// Tests that waitForIdle returns immediately if the service is already idle.
@@ -444,7 +444,7 @@
// This test has an inherent race condition in it, and cannot be enabled for continuous testing
// or presubmit tests. It is kept for manual runs and documentation purposes.
@Ignore
- public void verifyThatNotWaitingForIdleCausesRaceConditions() {
+ public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
// Bring up a network that we can use to send messages to ConnectivityService.
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -524,11 +524,11 @@
mNmValidationRedirectUrl = null;
}
- MockNetworkAgent(int transport) {
+ MockNetworkAgent(int transport) throws Exception {
this(transport, new LinkProperties());
}
- MockNetworkAgent(int transport, LinkProperties linkProperties) {
+ MockNetworkAgent(int transport, LinkProperties linkProperties) throws Exception {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
@@ -559,16 +559,12 @@
mNetworkMonitor = mock(INetworkMonitor.class);
final Answer validateAnswer = inv -> {
- new Thread(this::onValidationRequested).start();
+ new Thread(ignoreExceptions(this::onValidationRequested)).start();
return null;
};
- try {
- doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
- doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
+ doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
+ doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
@@ -623,35 +619,27 @@
assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
- try {
- mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
+ mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
// Waits for the NetworkAgent to be registered, which includes the creation of the
// NetworkMonitor.
waitForIdle();
}
- private void onValidationRequested() {
- try {
- if (mNmProvNotificationRequested
- && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
- mNmCallbacks.hideProvisioningNotification();
- mNmProvNotificationRequested = false;
- }
+ private void onValidationRequested() throws Exception {
+ if (mNmProvNotificationRequested
+ && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
+ mNmCallbacks.hideProvisioningNotification();
+ mNmProvNotificationRequested = false;
+ }
- mNmCallbacks.notifyNetworkTested(
- mNmValidationResult, mNmValidationRedirectUrl);
+ mNmCallbacks.notifyNetworkTested(
+ mNmValidationResult, mNmValidationRedirectUrl);
- if (mNmValidationRedirectUrl != null) {
- mNmCallbacks.showProvisioningNotification(
- "test_provisioning_notif_action", "com.android.test.package");
- mNmProvNotificationRequested = true;
- }
- } catch (RemoteException e) {
- fail(e.getMessage());
+ if (mNmValidationRedirectUrl != null) {
+ mNmCallbacks.showProvisioningNotification(
+ "test_provisioning_notif_action", "com.android.test.package");
+ mNmProvNotificationRequested = true;
}
}
@@ -664,8 +652,8 @@
return mScore;
}
- public void explicitlySelected(boolean acceptUnvalidated) {
- mNetworkAgent.explicitlySelected(acceptUnvalidated);
+ public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
+ mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
}
public void addCapability(int capability) {
@@ -768,6 +756,11 @@
connect(false);
}
+ public void connectWithPartialValidConnectivity() {
+ setNetworkPartialValid();
+ connect(false);
+ }
+
public void suspend() {
mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -1249,18 +1242,13 @@
waitForIdle(TIMEOUT_MS);
}
- public void setUidRulesChanged(int uidRules) {
- try {
- mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
- } catch (RemoteException ignored) {
- }
+ public void setUidRulesChanged(int uidRules) throws RemoteException {
+ mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
}
- public void setRestrictBackgroundChanged(boolean restrictBackground) {
- try {
- mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
- } catch (RemoteException ignored) {
- }
+ public void setRestrictBackgroundChanged(boolean restrictBackground)
+ throws RemoteException {
+ mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
}
}
@@ -1815,12 +1803,9 @@
return mLastAvailableNetwork;
}
- CallbackInfo nextCallback(int timeoutMs) {
+ CallbackInfo nextCallback(int timeoutMs) throws InterruptedException {
CallbackInfo cb = null;
- try {
- cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- }
+ cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
if (cb == null) {
// LinkedBlockingQueue.poll() returns null if it timeouts.
fail("Did not receive callback after " + timeoutMs + "ms");
@@ -1828,7 +1813,8 @@
return cb;
}
- CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
+ CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)
+ throws Exception {
final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
CallbackInfo actual = nextCallback(timeoutMs);
@@ -1845,15 +1831,16 @@
return actual;
}
- CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
+ CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) throws Exception {
return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
}
- CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
+ CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) throws Exception {
return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
}
- CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
+ CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)
+ throws Exception {
int timeLeft = timeoutMs;
while (timeLeft > 0) {
long start = SystemClock.elapsedRealtime();
@@ -1879,7 +1866,7 @@
// onCapabilitiesChanged callback.
// @param timeoutMs how long to wait for the callbacks.
void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
- boolean expectValidated, boolean expectBlocked, int timeoutMs) {
+ boolean expectValidated, boolean expectBlocked, int timeoutMs) throws Exception {
expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
if (expectSuspended) {
expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
@@ -1894,23 +1881,26 @@
}
// Expects the available callbacks (validated), plus onSuspended.
- void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
+ void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)
+ throws Exception {
expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
}
- void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
+ void expectAvailableCallbacksValidated(MockNetworkAgent agent)
+ throws Exception {
expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
}
- void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
+ void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) throws Exception {
expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
}
- void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
+ void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) throws Exception {
expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
}
- void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
+ void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent)
+ throws Exception {
expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
}
@@ -1918,7 +1908,7 @@
// VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
// one we just sent.
// TODO: this is likely a bug. Fix it and remove this method.
- void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
+ void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) throws Exception {
expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
@@ -1932,48 +1922,53 @@
// Expects the available callbacks where the onCapabilitiesChanged must not have validated,
// then expects another onCapabilitiesChanged that has the validated bit set. This is used
// when a network connects and satisfies a callback, and then immediately validates.
- void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
+ void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) throws Exception {
expectAvailableCallbacksUnvalidated(agent);
expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
}
- NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
+ NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent)
+ throws Exception {
return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
}
NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
- int timeoutMs) {
+ int timeoutMs) throws Exception {
CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
assertTrue(nc.hasCapability(capability));
return nc;
}
- NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
+ NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent)
+ throws Exception {
return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
}
NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
- int timeoutMs) {
+ int timeoutMs) throws Exception {
CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
assertFalse(nc.hasCapability(capability));
return nc;
}
- void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
+ void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)
+ throws Exception {
CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
assertTrue("Received capabilities don't match expectations : " + cbi.arg,
fn.test((NetworkCapabilities) cbi.arg));
}
- void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
+ void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent)
+ throws Exception {
CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
fn.test((LinkProperties) cbi.arg));
}
- void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
+ void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent)
+ throws Exception {
CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
boolean actualBlocked = (boolean) cbi.arg;
assertEquals(expectBlocked, actualBlocked);
@@ -2085,7 +2080,7 @@
}
@Test
- public void testMultipleLingering() {
+ public void testMultipleLingering() throws Exception {
// This test would be flaky with the default 120ms timer: that is short enough that
// lingered networks are torn down before assertions can be run. We don't want to mock the
// lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
@@ -2340,7 +2335,7 @@
}
@Test
- public void testNetworkGoesIntoBackgroundAfterLinger() {
+ public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
setAlwaysOnNetworks(true);
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities()
@@ -2385,7 +2380,7 @@
}
@Test
- public void testExplicitlySelected() {
+ public void testExplicitlySelected() throws Exception {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
.build();
@@ -2399,7 +2394,7 @@
// Bring up unvalidated wifi with explicitlySelected=true.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2422,7 +2417,7 @@
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2433,7 +2428,7 @@
// Reconnect, again with explicitlySelected=true, but this time validate.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(false);
+ mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
@@ -2448,14 +2443,36 @@
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
+ // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
+ // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
+ // wifi immediately.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(true, true);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mEthernetNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ mEthernetNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+
+ // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
+ // Check that the network is not scored specially and that the device prefers cell data.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false, true);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
// Clean up.
mWiFiNetworkAgent.disconnect();
mCellNetworkAgent.disconnect();
- mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
}
private int[] makeIntArray(final int size, final int value) {
@@ -2666,7 +2683,7 @@
}
@Test
- public void testPartialConnectivity() {
+ public void testPartialConnectivity() throws Exception {
// Register network callback.
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
@@ -2699,11 +2716,8 @@
// If user accepts partial connectivity network,
// NetworkMonitor#setAcceptPartialConnectivity() should be called too.
waitForIdle();
- try {
- verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
+ verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
@@ -2734,62 +2748,72 @@
// NET_CAPABILITY_PARTIAL_CONNECTIVITY.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
// acceptUnvalidated is also used as setting for accepting partial networks.
- mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
+ mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+ true /* acceptUnvalidated */);
mWiFiNetworkAgent.connect(true);
+
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
// ConnectivityService#updateNetworkInfo().
waitForIdle();
- try {
- verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
+ verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+
// Wifi should be the default network.
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- // If user accepted partial connectivity before, and now the device reconnects to the
- // partial connectivity network. The network should be valid and contain
- // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
+ // The user accepted partial connectivity and selected "don't ask again". Now the user
+ // reconnects to the partial connectivity network. Switch to wifi as soon as partial
+ // connectivity is detected.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
- // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
- // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
- // to ConnectivityService first then send VALID. Once NetworkMonitor support
- // multi-testResult, this test case also need to be changed to meet the new design.
+ mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+ true /* acceptUnvalidated */);
mWiFiNetworkAgent.connectWithPartialConnectivity();
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
// ConnectivityService#updateNetworkInfo().
waitForIdle();
- try {
- verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
+ verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
- // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
- // NetworkMonitor detects partial connectivity
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
mWiFiNetworkAgent.setNetworkValid();
+
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // If the user accepted partial connectivity, and the device auto-reconnects to the partial
+ // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
+ true /* acceptUnvalidated */);
+
+ // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
+ // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
+ // notifyNetworkConnected.
+ mWiFiNetworkAgent.connectWithPartialValidConnectivity();
+ waitForIdle();
+ verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCapabilitiesWith(
+ NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
}
@Test
- public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
+ public void testCaptivePortalOnPartialConnectivity() throws Exception {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2838,7 +2862,7 @@
}
@Test
- public void testCaptivePortal() {
+ public void testCaptivePortal() throws Exception {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2890,7 +2914,7 @@
}
@Test
- public void testCaptivePortalApp() throws RemoteException {
+ public void testCaptivePortalApp() throws Exception {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2948,7 +2972,7 @@
}
@Test
- public void testAvoidOrIgnoreCaptivePortals() {
+ public void testAvoidOrIgnoreCaptivePortals() throws Exception {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2988,7 +3012,7 @@
* does work.
*/
@Test
- public void testNetworkSpecifier() {
+ public void testNetworkSpecifier() throws Exception {
// A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
Parcelable {
@@ -3177,7 +3201,7 @@
}
@Test
- public void testNetworkSpecifierUidSpoofSecurityException() {
+ public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
@Override
public boolean satisfiedBy(NetworkSpecifier other) {
@@ -3790,7 +3814,7 @@
* time-out period expires.
*/
@Test
- public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
+ public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3810,7 +3834,7 @@
* not trigger onUnavailable() once the time-out period expires.
*/
@Test
- public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
+ public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3833,7 +3857,7 @@
* (somehow) satisfied - the callback isn't called later.
*/
@Test
- public void testTimedoutNetworkRequest() {
+ public void testTimedoutNetworkRequest() throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3854,7 +3878,7 @@
* trigger the callback.
*/
@Test
- public void testNoCallbackAfterUnregisteredNetworkRequest() {
+ public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3946,7 +3970,7 @@
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
- public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
+ public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
private class CallbackValue {
public CallbackType callbackType;
@@ -3994,25 +4018,19 @@
mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
}
- private void expectCallback(CallbackValue callbackValue) {
- try {
- assertEquals(
- callbackValue,
- mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
- }
+ private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
+ assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
- public void expectStarted() {
+ public void expectStarted() throws Exception {
expectCallback(new CallbackValue(CallbackType.ON_STARTED));
}
- public void expectStopped() {
+ public void expectStopped() throws Exception {
expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
}
- public void expectError(int error) {
+ public void expectError(int error) throws Exception {
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
}
}
@@ -4073,25 +4091,20 @@
mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
}
- private void expectCallback(CallbackValue callbackValue) {
- try {
- assertEquals(
- callbackValue,
- mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
- }
+ private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
+ assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
}
- public void expectStarted() {
+ public void expectStarted() throws InterruptedException {
expectCallback(new CallbackValue(CallbackType.ON_STARTED));
}
- public void expectStopped() {
+ public void expectStopped() throws InterruptedException {
expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
}
- public void expectError(int error) {
+ public void expectError(int error) throws InterruptedException {
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
}
@@ -4102,7 +4115,7 @@
}
}
- private Network connectKeepaliveNetwork(LinkProperties lp) {
+ private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
// Ensure the network is disconnected before we do anything.
if (mWiFiNetworkAgent != null) {
assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
@@ -4236,7 +4249,8 @@
}
// Helper method to prepare the executor and run test
- private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
+ private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
+ throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
final Executor executorInline = (Runnable r) -> r.run();
functor.accept(executorSingleThread);
@@ -4554,7 +4568,7 @@
private static boolean isUdpPortInUse(int port) {
try (DatagramSocket ignored = new DatagramSocket(port)) {
return false;
- } catch (IOException ignored) {
+ } catch (IOException alreadyInUse) {
return true;
}
}
@@ -4566,23 +4580,19 @@
}
private static class TestNetworkPinner extends NetworkPinner {
- public static boolean awaitPin(int timeoutMs) {
+ public static boolean awaitPin(int timeoutMs) throws InterruptedException {
synchronized(sLock) {
if (sNetwork == null) {
- try {
- sLock.wait(timeoutMs);
- } catch (InterruptedException e) {}
+ sLock.wait(timeoutMs);
}
return sNetwork != null;
}
}
- public static boolean awaitUnpin(int timeoutMs) {
+ public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
synchronized(sLock) {
if (sNetwork != null) {
- try {
- sLock.wait(timeoutMs);
- } catch (InterruptedException e) {}
+ sLock.wait(timeoutMs);
}
return sNetwork == null;
}
@@ -4605,7 +4615,7 @@
}
@Test
- public void testNetworkPinner() {
+ public void testNetworkPinner() throws Exception {
NetworkRequest wifiRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
.build();
@@ -4757,7 +4767,7 @@
}
@Test
- public void testNetworkInfoOfTypeNone() {
+ public void testNetworkInfoOfTypeNone() throws Exception {
ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
verifyNoNetwork();
@@ -4818,7 +4828,7 @@
}
@Test
- public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
+ public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
final NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -5226,7 +5236,7 @@
}
@Test
- public void testVpnNetworkActive() {
+ public void testVpnNetworkActive() throws Exception {
final int uid = Process.myUid();
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
@@ -5338,7 +5348,7 @@
}
@Test
- public void testVpnWithoutInternet() {
+ public void testVpnWithoutInternet() throws Exception {
final int uid = Process.myUid();
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
@@ -5368,7 +5378,7 @@
}
@Test
- public void testVpnWithInternet() {
+ public void testVpnWithInternet() throws Exception {
final int uid = Process.myUid();
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
@@ -5451,7 +5461,7 @@
}
@Test
- public void testVpnSetUnderlyingNetworks() {
+ public void testVpnSetUnderlyingNetworks() throws Exception {
final int uid = Process.myUid();
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
@@ -5549,7 +5559,7 @@
}
@Test
- public void testNullUnderlyingNetworks() {
+ public void testNullUnderlyingNetworks() throws Exception {
final int uid = Process.myUid();
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
@@ -5613,7 +5623,7 @@
}
@Test
- public void testIsActiveNetworkMeteredOverWifi() {
+ public void testIsActiveNetworkMeteredOverWifi() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -5625,7 +5635,7 @@
}
@Test
- public void testIsActiveNetworkMeteredOverCell() {
+ public void testIsActiveNetworkMeteredOverCell() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5637,7 +5647,7 @@
}
@Test
- public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
+ public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5691,7 +5701,7 @@
}
@Test
- public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
+ public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5762,7 +5772,7 @@
}
@Test
- public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
+ public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -5809,7 +5819,7 @@
}
@Test
- public void testNetworkBlockedStatus() {
+ public void testNetworkBlockedStatus() throws Exception {
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
final NetworkRequest cellRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
@@ -5860,7 +5870,7 @@
}
@Test
- public void testNetworkBlockedStatusBeforeAndAfterConnect() {
+ public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
@@ -5929,7 +5939,7 @@
}
@Test
- public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
+ public void testStackedLinkProperties() throws Exception {
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
final String kNat64PrefixString = "2001:db8:64:64:64:64::";
@@ -6092,7 +6102,7 @@
}
@Test
- public void testDataActivityTracking() throws RemoteException {
+ public void testDataActivityTracking() throws Exception {
final TestNetworkCallback networkCallback = new TestNetworkCallback();
final NetworkRequest networkRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
@@ -6167,21 +6177,17 @@
mCm.unregisterNetworkCallback(networkCallback);
}
- private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
+ private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
String[] values = tcpBufferSizes.split(",");
String rmemValues = String.join(" ", values[0], values[1], values[2]);
String wmemValues = String.join(" ", values[3], values[4], values[5]);
waitForIdle();
- try {
- verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
- } catch (RemoteException e) {
- fail("mMockNetd should never throw RemoteException");
- }
+ verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
reset(mMockNetd);
}
@Test
- public void testTcpBufferReset() {
+ public void testTcpBufferReset() throws Exception {
final String testTcpBufferSizes = "1,2,3,4,5,6";
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -6198,7 +6204,7 @@
}
@Test
- public void testGetGlobalProxyForNetwork() {
+ public void testGetGlobalProxyForNetwork() throws Exception {
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
@@ -6207,7 +6213,7 @@
}
@Test
- public void testGetProxyForActiveNetwork() {
+ public void testGetProxyForActiveNetwork() throws Exception {
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
@@ -6224,7 +6230,7 @@
}
@Test
- public void testGetProxyForVPN() {
+ public void testGetProxyForVPN() throws Exception {
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
// Set up a WiFi network with no proxy
@@ -6410,7 +6416,7 @@
private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
- Set<UidRange> vpnRange) {
+ Set<UidRange> vpnRange) throws Exception {
final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
mMockVpn.setNetworkAgent(vpnNetworkAgent);
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index b13731f..1be4ea8 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -56,7 +56,7 @@
"libziparchive",
"libpng",
"libbase",
- "libprotobuf-cpp-lite",
+ "libprotobuf-cpp-full",
"libz",
"libbuildversion",
],
diff --git a/tools/aapt2/Configuration.proto b/tools/aapt2/Configuration.proto
index fc636a4..8a4644c 100644
--- a/tools/aapt2/Configuration.proto
+++ b/tools/aapt2/Configuration.proto
@@ -19,7 +19,6 @@
package aapt.pb;
option java_package = "com.android.aapt";
-option optimize_for = LITE_RUNTIME;
// A description of the requirements a device must have in order for a
// resource to be matched and selected.
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 65f4652..7498e13 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -21,7 +21,6 @@
package aapt.pb;
option java_package = "com.android.aapt";
-option optimize_for = LITE_RUNTIME;
// A string pool that wraps the binary form of the C++ class android::ResStringPool.
message StringPool {
diff --git a/tools/aapt2/ResourcesInternal.proto b/tools/aapt2/ResourcesInternal.proto
index 520b242..b0ed3da3 100644
--- a/tools/aapt2/ResourcesInternal.proto
+++ b/tools/aapt2/ResourcesInternal.proto
@@ -22,7 +22,6 @@
package aapt.pb.internal;
option java_package = "android.aapt.pb.internal";
-option optimize_for = LITE_RUNTIME;
// The top level message representing an external resource file (layout XML, PNG, etc).
// This is used to represent a compiled file before it is linked. Only useful to aapt2.
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
index ce6d9352..bb925c9 100644
--- a/tools/aapt2/io/Util.cpp
+++ b/tools/aapt2/io/Util.cpp
@@ -58,7 +58,7 @@
return CopyFileToArchive(context, file, out_path, compression_flags, writer);
}
-bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
const std::string& out_path, uint32_t compression_flags,
IArchiveWriter* writer) {
TRACE_CALL();
diff --git a/tools/aapt2/io/Util.h b/tools/aapt2/io/Util.h
index 5f978a8..5cb8206 100644
--- a/tools/aapt2/io/Util.h
+++ b/tools/aapt2/io/Util.h
@@ -19,7 +19,7 @@
#include <string>
-#include "google/protobuf/message_lite.h"
+#include "google/protobuf/message.h"
#include "google/protobuf/io/coded_stream.h"
#include "format/Archive.h"
@@ -39,7 +39,7 @@
bool CopyFileToArchivePreserveCompression(IAaptContext* context, IFile* file,
const std::string& out_path, IArchiveWriter* writer);
-bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
const std::string& out_path, uint32_t compression_flags,
IArchiveWriter* writer);
@@ -127,13 +127,13 @@
public:
explicit ProtoInputStreamReader(io::InputStream* in) : in_(in) { }
- /** Deserializes a MessageLite proto from the current position in the input stream.*/
- template <typename T> bool ReadMessage(T *message_lite) {
+ /** Deserializes a Message proto from the current position in the input stream.*/
+ template <typename T> bool ReadMessage(T *message) {
ZeroCopyInputAdaptor adapter(in_);
google::protobuf::io::CodedInputStream coded_stream(&adapter);
coded_stream.SetTotalBytesLimit(std::numeric_limits<int32_t>::max(),
coded_stream.BytesUntilTotalBytesLimit());
- return message_lite->ParseFromCodedStream(&coded_stream);
+ return message->ParseFromCodedStream(&coded_stream);
}
private:
diff --git a/tools/dump-coverage/Android.bp b/tools/dump-coverage/Android.bp
new file mode 100644
index 0000000..4519ce3
--- /dev/null
+++ b/tools/dump-coverage/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Build variants {target,host} x {32,64}
+cc_library {
+ name: "libdumpcoverage",
+ srcs: ["dump_coverage.cc"],
+ header_libs: [
+ "libopenjdkjvmti_headers",
+ ],
+
+ host_supported: true,
+ shared_libs: [
+ "libbase",
+ ],
+}
diff --git a/tools/dump-coverage/README.md b/tools/dump-coverage/README.md
new file mode 100644
index 0000000..2bab4bc
--- /dev/null
+++ b/tools/dump-coverage/README.md
@@ -0,0 +1,50 @@
+# dumpcoverage
+
+libdumpcoverage.so is a JVMTI agent designed to dump coverage information for a process, where the binaries have been instrumented by JaCoCo. JaCoCo automatically starts recording data on process start, and we need a way to trigger the resetting or dumping of this data.
+
+The JVMTI agent is used to make the calls to JaCoCo in its process.
+
+# Usage
+
+Note that these examples assume you have an instrumented build (userdebug_coverage). Here is, for example, how to dump coverage information regarding the default clock app. First some setup is necessary:
+
+```
+adb root # necessary to copy files in/out of the /data/data/{package} folder
+adb shell 'mkdir /data/data/com.android.deskclock/folder-to-use'
+```
+
+Then we can run the command to dump the data:
+
+```
+adb shell 'am attach-agent com.android.deskclock /system/lib/libdumpcoverage.so=dump:/data/data/com.android.deskclock/folder-to-use'
+```
+
+We can also reset the coverage information with
+
+```
+adb shell 'am attach-agent com.android.deskclock /system/lib/libdumpcoverage.so=reset'
+```
+
+then perform more actions, then dump the data again. To get the files, we can get
+
+```
+adb pull /data/data/com.android.deskclock/folder-to-use ~/path-on-your-computer
+```
+
+And you should have timestamped `.exec` files on your machine under the folder `~/path-on-your-computer`
+
+# Details
+
+In dump mode, the agent makes JNI calls equivalent to
+
+```
+Agent.getInstance().getExecutionData(/*reset = */ false);
+```
+
+and then saves the result to a file specified by the passed in directory
+
+In reset mode, it makes a JNI call equivalent to
+
+```
+Agent.getInstance().reset();
+```
diff --git a/tools/dump-coverage/dump_coverage.cc b/tools/dump-coverage/dump_coverage.cc
new file mode 100644
index 0000000..3de1865
--- /dev/null
+++ b/tools/dump-coverage/dump_coverage.cc
@@ -0,0 +1,239 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <android-base/logging.h>
+#include <jni.h>
+#include <jvmti.h>
+#include <string.h>
+
+#include <atomic>
+#include <ctime>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using std::get;
+using std::tuple;
+using std::chrono::system_clock;
+
+namespace dump_coverage {
+
+#define CHECK_JVMTI(x) CHECK_EQ((x), JVMTI_ERROR_NONE)
+#define CHECK_NOTNULL(x) CHECK((x) != nullptr)
+#define CHECK_NO_EXCEPTION(env) CHECK(!(env)->ExceptionCheck());
+
+static JavaVM* java_vm = nullptr;
+
+// Get the current JNI environment.
+static JNIEnv* GetJNIEnv() {
+ JNIEnv* env = nullptr;
+ CHECK_EQ(java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6),
+ JNI_OK);
+ return env;
+}
+
+// Get the JaCoCo Agent class and an instance of the class, given a JNI
+// environment.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static tuple<jclass, jobject> GetJavaAgent(JNIEnv* env) {
+ jclass java_agent_class =
+ env->FindClass("org/jacoco/agent/rt/internal/Agent");
+ CHECK_NOTNULL(java_agent_class);
+
+ jmethodID java_agent_get_instance =
+ env->GetStaticMethodID(java_agent_class, "getInstance",
+ "()Lorg/jacoco/agent/rt/internal/Agent;");
+ CHECK_NOTNULL(java_agent_get_instance);
+
+ jobject java_agent_instance =
+ env->CallStaticObjectMethod(java_agent_class, java_agent_get_instance);
+ CHECK_NO_EXCEPTION(env);
+ CHECK_NOTNULL(java_agent_instance);
+
+ return tuple(java_agent_class, java_agent_instance);
+}
+
+// Runs equivalent of Agent.getInstance().getExecutionData(false) and returns
+// the result.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jbyteArray GetExecutionData(JNIEnv* env) {
+ auto java_agent = GetJavaAgent(env);
+ jmethodID java_agent_get_execution_data =
+ env->GetMethodID(get<0>(java_agent), "getExecutionData", "(Z)[B");
+ CHECK_NO_EXCEPTION(env);
+ CHECK_NOTNULL(java_agent_get_execution_data);
+
+ jbyteArray java_result_array = (jbyteArray)env->CallObjectMethod(
+ get<1>(java_agent), java_agent_get_execution_data, false);
+ CHECK_NO_EXCEPTION(env);
+
+ return java_result_array;
+}
+
+// Gets the filename to write execution data to
+// dirname: the directory in which to place the file
+// outputs <dirname>/YYYY-MM-DD-HH-MM-SS.SSS.exec
+static std::string GetFilename(const std::string& dirname) {
+ system_clock::time_point time_point = system_clock::now();
+ auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(time_point);
+ auto fractional_time = time_point - seconds;
+ auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(fractional_time);
+
+ std::time_t time = system_clock::to_time_t(time_point);
+ auto tm = *std::gmtime(&time);
+
+ std::ostringstream oss;
+ oss
+ << dirname
+ << "/"
+ << std::put_time(&tm, "%Y-%m-%d-%H-%M-%S.")
+ << std::setfill('0') << std::setw(3) << millis.count()
+ << ".ec";
+ return oss.str();
+}
+
+// Writes the execution data to a file
+// data, length: represent the data, as a sequence of bytes
+// dirname: directory name to contain the file
+// returns JNI_ERR if there is an error in writing the file, otherwise JNI_OK.
+static jint WriteFile(const char* data, int length, const std::string& dirname) {
+ auto filename = GetFilename(dirname);
+
+ LOG(INFO) << "Writing file of length " << length << " to '" << filename
+ << "'";
+ std::ofstream file(filename, std::ios::binary);
+
+ if (!file.is_open()) {
+ LOG(ERROR) << "Could not open file: '" << filename << "'";
+ return JNI_ERR;
+ }
+ file.write(data, length);
+ file.close();
+
+ if (!file) {
+ LOG(ERROR) << "I/O error in reading file";
+ return JNI_ERR;
+ }
+
+ LOG(INFO) << "Done writing file";
+ return JNI_OK;
+}
+
+// Grabs execution data and writes it to a file
+// dirname: directory name to contain the file
+// returns JNI_ERR if there is an error writing the file.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jint Dump(const std::string& dirname) {
+ LOG(INFO) << "Dumping file";
+
+ JNIEnv* env = GetJNIEnv();
+ jbyteArray java_result_array = GetExecutionData(env);
+ CHECK_NOTNULL(java_result_array);
+
+ jbyte* result_ptr = env->GetByteArrayElements(java_result_array, 0);
+ CHECK_NOTNULL(result_ptr);
+
+ int result_len = env->GetArrayLength(java_result_array);
+
+ return WriteFile((const char*) result_ptr, result_len, dirname);
+}
+
+// Resets execution data, performing the equivalent of
+// Agent.getInstance().reset();
+// args: should be empty
+// returns JNI_ERR if the arguments are invalid.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jint Reset(const std::string& args) {
+ if (args != "") {
+ LOG(ERROR) << "reset takes no arguments, but received '" << args << "'";
+ return JNI_ERR;
+ }
+
+ JNIEnv* env = GetJNIEnv();
+ auto java_agent = GetJavaAgent(env);
+
+ jmethodID java_agent_reset =
+ env->GetMethodID(get<0>(java_agent), "reset", "()V");
+ CHECK_NOTNULL(java_agent_reset);
+
+ env->CallVoidMethod(get<1>(java_agent), java_agent_reset);
+ CHECK_NO_EXCEPTION(env);
+ return JNI_OK;
+}
+
+// Given a string of the form "<a>:<b>" returns (<a>, <b>).
+// Given a string <a> that doesn't contain a colon, returns (<a>, "").
+static tuple<std::string, std::string> SplitOnColon(const std::string& options) {
+ size_t loc_delim = options.find(':');
+ std::string command, args;
+
+ if (loc_delim == std::string::npos) {
+ command = options;
+ } else {
+ command = options.substr(0, loc_delim);
+ args = options.substr(loc_delim + 1, options.length());
+ }
+ return tuple(command, args);
+}
+
+// Parses and executes a command specified by options of the form
+// "<command>:<args>" where <command> is either "dump" or "reset".
+static jint ParseOptionsAndExecuteCommand(const std::string& options) {
+ auto split = SplitOnColon(options);
+ auto command = get<0>(split), args = get<1>(split);
+
+ LOG(INFO) << "command: '" << command << "' args: '" << args << "'";
+
+ if (command == "dump") {
+ return Dump(args);
+ }
+
+ if (command == "reset") {
+ return Reset(args);
+ }
+
+ LOG(ERROR) << "Invalid command: expected 'dump' or 'reset' but was '"
+ << command << "'";
+ return JNI_ERR;
+}
+
+static jint AgentStart(JavaVM* vm, char* options) {
+ android::base::InitLogging(/* argv= */ nullptr);
+ java_vm = vm;
+
+ return ParseOptionsAndExecuteCommand(options);
+}
+
+// Late attachment (e.g. 'am attach-agent').
+extern "C" JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved ATTRIBUTE_UNUSED) {
+ return AgentStart(vm, options);
+}
+
+// Early attachment.
+extern "C" JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM* jvm ATTRIBUTE_UNUSED, char* options ATTRIBUTE_UNUSED, void* reserved ATTRIBUTE_UNUSED) {
+ LOG(ERROR)
+ << "The dumpcoverage agent will not work on load,"
+ << " as it does not have access to the runtime.";
+ return JNI_ERR;
+}
+
+} // namespace dump_coverage