Merge "Prevent usage of freed memory by using getLights and getSensors" into sc-dev
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index dc29c5e..a741f96 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -265,7 +265,7 @@
// Return an empty cursor for all columns.
return new MatrixCursor(cursor.getColumnNames(), 0);
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "query");
+ traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -285,7 +285,7 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
+ traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
try {
return mInterface.getType(uri);
} catch (RemoteException e) {
@@ -323,7 +323,7 @@
setCallingAttributionSource(original);
}
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
+ traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -345,7 +345,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
+ traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -391,7 +391,7 @@
}
}
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
+ traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -423,7 +423,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
+ traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -445,7 +445,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "update");
+ traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -465,7 +465,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
+ traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -486,7 +486,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
+ traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -505,7 +505,7 @@
String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
- Trace.traceBegin(TRACE_TAG_DATABASE, "call");
+ traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -523,7 +523,7 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "getStreamTypes");
+ traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
try {
return mInterface.getStreamTypes(uri, mimeTypeFilter);
} catch (RemoteException e) {
@@ -541,7 +541,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, "r");
- Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
+ traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -569,7 +569,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
+ traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -605,7 +605,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
+ traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -641,7 +641,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return false;
}
- Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
+ traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -658,7 +658,7 @@
int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
+ traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -2683,4 +2683,10 @@
}
return uri;
}
+
+ private static void traceBegin(long traceTag, String methodName, String subInfo) {
+ if (Trace.isTagEnabled(traceTag)) {
+ Trace.traceBegin(traceTag, methodName + subInfo);
+ }
+ }
}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 6a2b723..61f524f 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -154,4 +154,13 @@
* app.
*/
void detachNavigationBarFromApp(boolean moveHomeToTop);
+
+ /**
+ * Used for animating the navigation bar during app launch from recents in live tile mode.
+ *
+ * First fade out the navigation bar at the bottom of the display and then fade in to the app.
+ *
+ * @param duration the duration of the app launch animation
+ */
+ void animateNavigationBarToApp(long duration);
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index a64129e..756425e 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -293,4 +293,7 @@
be able to connect to the internet when such a proxy is in use, since
all outgoing connections originate from this app. -->
<allow-in-power-save-except-idle package="com.android.proxyhandler" />
+
+ <!-- Allow IMS service entitlement app to schedule jobs to run when app in background. -->
+ <allow-in-power-save-except-idle package="com.android.imsserviceentitlement" />
</permissions>
diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java
index a1a7aa8..cc1ec1b 100644
--- a/keystore/java/android/security/GenerateRkpKey.java
+++ b/keystore/java/android/security/GenerateRkpKey.java
@@ -22,6 +22,10 @@
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner
@@ -41,14 +45,25 @@
* @hide
*/
public class GenerateRkpKey {
+ private static final String TAG = "GenerateRkpKey";
+
+ private static final int NOTIFY_EMPTY = 0;
+ private static final int NOTIFY_KEY_GENERATED = 1;
+ private static final int TIMEOUT_MS = 1000;
private IGenerateRkpKeyService mBinder;
private Context mContext;
+ private CountDownLatch mCountDownLatch;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
mBinder = IGenerateRkpKeyService.Stub.asInterface(service);
+ mCountDownLatch.countDown();
+ }
+
+ @Override public void onBindingDied(ComponentName className) {
+ mCountDownLatch.countDown();
}
@Override
@@ -64,36 +79,51 @@
mContext = context;
}
- /**
- * Fulfills the use case of (2) described in the class documentation. Blocks until the
- * RemoteProvisioner application can get new attestation keys signed by the server.
- */
- public void notifyEmpty(int securityLevel) throws RemoteException {
+ private void bindAndSendCommand(int command, int securityLevel) throws RemoteException {
Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ if (comp == null) {
+ throw new RemoteException("Could not resolve GenerateRkpKeyService.");
+ }
intent.setComponent(comp);
- if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
- throw new RemoteException("Failed to bind to GenerateKeyService");
+ mCountDownLatch = new CountDownLatch(1);
+ if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
+ throw new RemoteException("Failed to bind to GenerateRkpKeyService");
+ }
+ try {
+ mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted: ", e);
}
if (mBinder != null) {
- mBinder.generateKey(securityLevel);
+ switch (command) {
+ case NOTIFY_EMPTY:
+ mBinder.generateKey(securityLevel);
+ break;
+ case NOTIFY_KEY_GENERATED:
+ mBinder.notifyKeyGenerated(securityLevel);
+ break;
+ default:
+ Log.e(TAG, "Invalid case for command");
+ }
+ } else {
+ Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService.");
}
mContext.unbindService(mConnection);
}
/**
- * FUlfills the use case of (1) described in the class documentation. Non blocking call.
+ * Fulfills the use case of (2) described in the class documentation. Blocks until the
+ * RemoteProvisioner application can get new attestation keys signed by the server.
+ */
+ public void notifyEmpty(int securityLevel) throws RemoteException {
+ bindAndSendCommand(NOTIFY_EMPTY, securityLevel);
+ }
+
+ /**
+ * Fulfills the use case of (1) described in the class documentation. Non blocking call.
*/
public void notifyKeyGenerated(int securityLevel) throws RemoteException {
- Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
- throw new RemoteException("Failed to bind to GenerateKeyService");
- }
- if (mBinder != null) {
- mBinder.notifyKeyGenerated(securityLevel);
- }
- mContext.unbindService(mConnection);
+ bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel);
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index dc7f3dd..c048f3b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -580,7 +580,7 @@
} catch (RemoteException e) {
// This is not really an error state, and necessarily does not apply to non RKP
// systems or hybrid systems where RKP is not currently turned on.
- Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.");
+ Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
}
success = true;
return new KeyPair(publicKey, publicKey.getPrivateKey());
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 10df726..8881be7 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -19,7 +19,7 @@
package="com.android.wm.shell">
<!-- System permission required by WM Shell Task Organizer. -->
<uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT" />
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
</manifest>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index a88be31..f7fb63d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -46,6 +46,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
import com.android.wm.shell.startingsurface.StartingWindowController;
@@ -55,6 +56,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Unified task organizer for all components in the shell.
@@ -342,6 +344,19 @@
notifySizeCompatUI(info.getTaskInfo(), listener);
}
+ /**
+ * Take a screenshot of a task.
+ */
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ final TaskAppearedInfo info = mTasks.get(taskInfo.taskId);
+ if (info == null) {
+ return;
+ }
+ ScreenshotUtils.captureLayer(info.getLeash(), crop, consumer);
+ }
+
+
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
synchronized (mLock) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 2fc696c..35a4f33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -231,7 +231,8 @@
* Fade animation for consecutive flyouts.
*/
void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, PointF stackPos,
- boolean hideDot) {
+ boolean hideDot, Runnable onHide) {
+ mOnHide = onHide;
final Runnable afterFadeOut = () -> {
updateFlyoutMessage(flyoutMessage, parentWidth);
// Wait for TextViews to layout with updated height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index d821c6f..8613dcb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1492,22 +1492,22 @@
mStackAnimationController.setStackPosition(mPositioner.getDefaultStartPosition());
}
- if (getBubbleCount() == 0) {
- mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
- }
-
if (bubble.getIconView() == null) {
return;
}
+ mBubbleContainer.addView(bubble.getIconView(), 0,
+ new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
+ mPositioner.getBubbleSize()));
+
+ if (getBubbleCount() == 0) {
+ mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
+ }
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
bubble.getIconView().setDotBadgeOnLeft(!mStackOnLeftOrWillBe /* onLeft */);
bubble.getIconView().setOnClickListener(mBubbleClickListener);
bubble.getIconView().setOnTouchListener(mBubbleTouchListener);
- mBubbleContainer.addView(bubble.getIconView(), 0,
- new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
- mPositioner.getBubbleSize()));
updateBubbleShadows(false /* showForAllBubbles */);
animateInFlyoutForBubble(bubble);
requestUpdate();
@@ -2400,7 +2400,8 @@
if (mFlyout.getVisibility() == View.VISIBLE) {
mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(),
- mStackAnimationController.getStackPosition(), !bubble.showDot());
+ mStackAnimationController.getStackPosition(), !bubble.showDot(),
+ mAfterFlyoutHidden /* onHide */);
} else {
mFlyout.setVisibility(INVISIBLE);
mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(),
@@ -2408,7 +2409,7 @@
mStackAnimationController.isStackOnLeftSide(),
bubble.getIconView().getDotColor() /* dotColor */,
expandFlyoutAfterDelay /* onLayoutComplete */,
- mAfterFlyoutHidden,
+ mAfterFlyoutHidden /* onHide */,
bubble.getIconView().getDotCenter(),
!bubble.showDot(),
mPositioner);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 8043d2b..12d55b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -124,9 +124,6 @@
*/
private Rect mAnimatingToBounds = new Rect();
- /** Initial starting location for the stack. */
- @Nullable private BubbleStackView.RelativeStackPosition mStackStartPosition;
-
/** Whether or not the stack's start position has been set. */
private boolean mStackMovedToStartPosition = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
index 32575fa..eea6e3c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
@@ -21,6 +21,8 @@
import android.graphics.Rect;
import android.view.SurfaceControl;
+import java.util.function.Consumer;
+
/**
* Helpers for working with screenshots.
*/
@@ -29,6 +31,60 @@
/**
* Take a screenshot of the specified SurfaceControl.
*
+ * @param sc the SurfaceControl to take a screenshot of
+ * @param crop the crop to use when capturing the screenshot
+ * @param consumer Consumer for the captured buffer
+ */
+ public static void captureLayer(SurfaceControl sc, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ consumer.accept(SurfaceControl.captureLayers(
+ new SurfaceControl.LayerCaptureArgs.Builder(sc)
+ .setSourceCrop(crop)
+ .setCaptureSecureLayers(true)
+ .setAllowProtected(true)
+ .build()));
+ }
+
+ private static class BufferConsumer implements
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> {
+ SurfaceControl mScreenshot = null;
+ SurfaceControl.Transaction mTransaction;
+ SurfaceControl mSurfaceControl;
+ int mLayer;
+
+ BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, int layer) {
+ mTransaction = t;
+ mSurfaceControl = sc;
+ mLayer = layer;
+ }
+
+ @Override
+ public void accept(SurfaceControl.ScreenshotHardwareBuffer buffer) {
+ if (buffer == null || buffer.getHardwareBuffer() == null) {
+ return;
+ }
+ final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
+ buffer.getHardwareBuffer());
+ mScreenshot = new SurfaceControl.Builder()
+ .setName("ScreenshotUtils screenshot")
+ .setFormat(PixelFormat.TRANSLUCENT)
+ .setSecure(buffer.containsSecureLayers())
+ .setCallsite("ScreenshotUtils.takeScreenshot")
+ .setBLASTLayer()
+ .build();
+
+ mTransaction.setBuffer(mScreenshot, graphicBuffer);
+ mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
+ mTransaction.reparent(mScreenshot, mSurfaceControl);
+ mTransaction.setLayer(mScreenshot, mLayer);
+ mTransaction.show(mScreenshot);
+ mTransaction.apply();
+ }
+ }
+
+ /**
+ * Take a screenshot of the specified SurfaceControl.
+ *
* @param t the transaction used to set changes on the resulting screenshot.
* @param sc the SurfaceControl to take a screenshot of
* @param crop the crop to use when capturing the screenshot
@@ -38,32 +94,8 @@
*/
public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
Rect crop, int layer) {
- final SurfaceControl.ScreenshotHardwareBuffer buffer = SurfaceControl.captureLayers(
- new SurfaceControl.LayerCaptureArgs.Builder(sc)
- .setSourceCrop(crop)
- .setCaptureSecureLayers(true)
- .setAllowProtected(true)
- .build()
- );
- if (buffer == null || buffer.getHardwareBuffer() == null) {
- return null;
- }
- final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- buffer.getHardwareBuffer());
- final SurfaceControl screenshot = new SurfaceControl.Builder()
- .setName("ScreenshotUtils screenshot")
- .setFormat(PixelFormat.TRANSLUCENT)
- .setSecure(buffer.containsSecureLayers())
- .setCallsite("ScreenshotUtils.takeScreenshot")
- .setBLASTLayer()
- .build();
-
- t.setBuffer(screenshot, graphicBuffer);
- t.setColorSpace(screenshot, buffer.getColorSpace());
- t.reparent(screenshot, sc);
- t.setLayer(screenshot, layer);
- t.show(screenshot);
- t.apply();
- return screenshot;
+ BufferConsumer consumer = new BufferConsumer(t, sc, layer);
+ captureLayer(sc, crop, consumer);
+ return consumer.mScreenshot;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 7d032ad..afd7d26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -628,8 +628,10 @@
final Rect destinationBounds = mPipBoundsState.getBounds();
final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay;
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
- mSurfaceTransactionHelper.resetScale(tx, mLeash, destinationBounds);
- mSurfaceTransactionHelper.crop(tx, mLeash, destinationBounds);
+ mSurfaceTransactionHelper
+ .resetScale(tx, mLeash, destinationBounds)
+ .crop(tx, mLeash, destinationBounds)
+ .round(tx, mLeash, isInPip());
// The animation is finished in the Launcher and here we directly apply the final touch.
applyEnterPipSyncTransaction(destinationBounds, () -> {
// Ensure menu's settled in its final bounds first.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
index fbbd09f..ad9dda6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
@@ -16,6 +16,13 @@
package com.android.wm.shell.tasksurfacehelper;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Rect;
+import android.view.SurfaceControl;
+
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
/**
* Interface to communicate with a Task's SurfaceControl.
*/
@@ -23,4 +30,8 @@
/** Sets the METADATA_GAME_MODE for the layer corresponding to the task **/
default void setGameModeForTask(int taskId, int gameMode) {}
+
+ /** Takes a screenshot for a task **/
+ default void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
index b459b9f..064d9d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
@@ -16,11 +16,16 @@
package com.android.wm.shell.tasksurfacehelper;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Rect;
import android.view.SurfaceControl;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
/**
* Intermediary controller that communicates with {@link ShellTaskOrganizer} to send commands
* to SurfaceControl.
@@ -49,6 +54,14 @@
mTaskOrganizer.setSurfaceMetadata(taskId, SurfaceControl.METADATA_GAME_MODE, gameMode);
}
+ /**
+ * Take screenshot of the specified task.
+ */
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ mTaskOrganizer.screenshotTask(taskInfo, crop, consumer);
+ }
+
private class TaskSurfaceHelperImpl implements TaskSurfaceHelper {
@Override
public void setGameModeForTask(int taskId, int gameMode) {
@@ -56,5 +69,14 @@
TaskSurfaceHelperController.this.setGameModeForTask(taskId, gameMode);
});
}
+
+ @Override
+ public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
+ Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
+ mMainExecutor.execute(() -> {
+ TaskSurfaceHelperController.this.screenshotTask(taskInfo, crop,
+ (t) -> executor.execute(() -> consumer.accept(t)));
+ });
+ }
}
}
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 01a2ec5..fe9a30a 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -429,7 +429,9 @@
kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr);
if (bufferInfo->skSurface.get() == nullptr) {
ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
- mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer,
+ mNativeBuffers[idx].dequeue_fence.release());
+ mNativeBuffers[idx].dequeued = false;
return nullptr;
}
}
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index cb56ee5..a3842a1 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -178,6 +178,7 @@
public static final int POWER_HIGH = 203;
private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1;
+ private static final double IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR = 1D / 6D;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
+ "LocationManager} methods to provide the provider explicitly.")
@@ -552,7 +553,7 @@
*/
public @IntRange(from = 0) long getMinUpdateIntervalMillis() {
if (mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
- return mInterval;
+ return (long) (mInterval * IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR);
} else {
// the min is only necessary in case someone use a deprecated function to mess with the
// interval or min update interval
@@ -1018,7 +1019,9 @@
* Sets an explicit minimum update interval. If location updates are available faster than
* the request interval then an update will only occur if the minimum update interval has
* expired since the last location update. Defaults to no explicit minimum update interval
- * set, which means the minimum update interval is the same as the interval.
+ * set, which means some sensible default between 0 and the interval will be chosen. The
+ * exact value is not specified at the moment. If an exact known value is required, clients
+ * should set an explicit value themselves.
*
* <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
* minimum update interval, so you need not worry about updates blocked simply because they
@@ -1037,7 +1040,8 @@
/**
* Clears an explicitly set minimum update interval and reverts to an implicit minimum
- * update interval (ie, the minimum update interval is the same value as the interval).
+ * update interval (ie, the minimum update interval is some sensible default between 0 and
+ * the interval).
*/
public @NonNull Builder clearMinUpdateIntervalMillis() {
mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml
index 338bff8..7e2db63 100644
--- a/packages/SystemUI/res/drawable/people_space_activity_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_activity_card.xml
@@ -14,5 +14,5 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorBackgroundFloating" />
+ <solid android:color="@color/people_tile_background" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml
index 30519ae..9704871 100644
--- a/packages/SystemUI/res/drawable/people_space_content_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_content_background.xml
@@ -15,6 +15,6 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_image_radius" />
</shape>
diff --git a/packages/SystemUI/res/drawable/people_space_new_story_outline.xml b/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
index a1737f9..4d6249d 100644
--- a/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
+++ b/packages/SystemUI/res/drawable/people_space_new_story_outline.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<stroke android:width="2dp" android:color="?android:attr/colorAccent" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_rounded_border.xml b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
index 9956bc2..50560df 100644
--- a/packages/SystemUI/res/drawable/people_space_rounded_border.xml
+++ b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
@@ -15,5 +15,5 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
index 8fd4388..6e1e5de 100644
--- a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
@@ -14,6 +14,6 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_widget_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_tile_empty_background.xml b/packages/SystemUI/res/drawable/people_tile_empty_background.xml
index 2dac740..7dbea73 100644
--- a/packages/SystemUI/res/drawable/people_tile_empty_background.xml
+++ b/packages/SystemUI/res/drawable/people_tile_empty_background.xml
@@ -14,8 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <solid android:color="?androidprv:attr/colorSurface" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/people_tile_background" />
<corners android:radius="@dimen/people_space_widget_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index c473229..8e6293a 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -97,4 +97,6 @@
<!-- Accessibility floating menu -->
<color name="accessibility_floating_menu_background">#B3000000</color> <!-- 70% -->
+
+ <color name="people_tile_background">@android:color/system_accent2_800</color>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f64299d..2cf3058 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -281,4 +281,6 @@
<!-- Wallet screen -->
<color name="wallet_card_border">#33FFFFFF</color>
+
+ <color name="people_tile_background">@android:color/system_accent2_50</color>
</resources>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index c388b1e..027f162 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -33,15 +33,11 @@
<!-- People Tile flag -->
<bool name="flag_conversations">false</bool>
- <bool name="flag_wallet">false</bool>
-
<!-- The new animations to/from lockscreen and AOD! -->
<bool name="flag_lockscreen_animations">false</bool>
<bool name="flag_pm_lite">true</bool>
- <bool name="flag_alarm_tile">false</bool>
-
<bool name="flag_charging_ripple">false</bool>
<bool name="flag_ongoing_call_status_bar_chip">true</bool>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
index 74aa138..fb9aa4a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
@@ -46,12 +46,13 @@
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
mTmpDestinationRectF.left, mTmpDestinationRectF.top,
- mTmpFloat9, 0 /* rotation */, mCornerRadius, sourceBounds);
+ mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scale(
@@ -62,11 +63,12 @@
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
mTmpTransform.postRotate(degree, 0, 0);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- positionX, positionY, mTmpFloat9, degree, mCornerRadius, sourceBounds);
+ positionX, positionY, mTmpFloat9, degree, cornerRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scaleAndCrop(
@@ -83,12 +85,15 @@
final float left = destinationBounds.left - insets.left * scale;
final float top = destinationBounds.top - insets.top * scale;
mTmpTransform.setScale(scale, scale);
+ final Rect cornerRadiusRect = new Rect(destinationBounds);
+ cornerRadiusRect.inset(insets);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, cornerRadiusRect);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, left, top)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- left, top, mTmpFloat9, 0 /* rotation */, mCornerRadius, mTmpDestinationRect);
+ left, top, mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
}
public PictureInPictureSurfaceTransaction scaleAndRotate(
@@ -105,12 +110,22 @@
: (float) destinationBounds.height() / sourceBounds.height();
mTmpTransform.setRotate(degree, 0, 0);
mTmpTransform.postScale(scale, scale);
+ final Rect cornerRadiusRect = new Rect(destinationBounds);
+ cornerRadiusRect.inset(insets);
+ final float cornerRadius = getScaledCornerRadius(sourceBounds, cornerRadiusRect);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, mCornerRadius);
+ .setCornerRadius(leash, cornerRadius);
return new PictureInPictureSurfaceTransaction(
- positionX, positionY, mTmpFloat9, degree, mCornerRadius, mTmpDestinationRect);
+ positionX, positionY, mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
+ }
+
+ /** @return the round corner radius scaled by given from and to bounds */
+ private float getScaledCornerRadius(Rect fromBounds, Rect toBounds) {
+ final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+ / Math.hypot(toBounds.width(), toBounds.height()));
+ return mCornerRadius * scale;
}
/** @return {@link SurfaceControl.Transaction} instance with vsync-id */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 700ec49..8e65560 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -152,4 +152,15 @@
Log.e(TAG, "Failed to detach the navigation bar from app", e);
}
}
+
+ /**
+ * @see IRecentsAnimationController#animateNavigationBarToApp(long)
+ */
+ public void animateNavigationBarToApp(long duration) {
+ try {
+ mAnimationController.animateNavigationBarToApp(duration);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to animate the navigation bar to app", e);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 619bf1b..92ffb42 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -64,9 +64,10 @@
private float mDarkAmount;
/**
- * Boolean value indicating if notifications are visible on lock screen.
+ * Boolean value indicating if notifications are visible on lock screen. Use null to signify
+ * it is uninitialized.
*/
- private boolean mHasVisibleNotifications = true;
+ private Boolean mHasVisibleNotifications = null;
private AnimatorSet mClockInAnim = null;
private AnimatorSet mClockOutAnim = null;
@@ -263,7 +264,8 @@
* the smaller version.
*/
boolean willSwitchToLargeClock(boolean hasVisibleNotifications) {
- if (hasVisibleNotifications == mHasVisibleNotifications) {
+ if (mHasVisibleNotifications != null
+ && hasVisibleNotifications == mHasVisibleNotifications) {
return false;
}
boolean useLargeClock = !hasVisibleNotifications;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index fcb090a..717c715 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -66,6 +66,7 @@
import java.io.PrintWriter;
import java.text.NumberFormat;
+import java.util.Collections;
import java.util.Locale;
/**
@@ -178,7 +179,13 @@
// Initialize listeners.
mMirrorViewRunnable = () -> {
if (mMirrorView != null) {
+ final Rect oldViewBounds = new Rect(mMirrorViewBounds);
mMirrorView.getBoundsOnScreen(mMirrorViewBounds);
+ if (oldViewBounds.width() != mMirrorViewBounds.width()
+ || oldViewBounds.height() != mMirrorViewBounds.height()) {
+ mMirrorView.setSystemGestureExclusionRects(Collections.singletonList(
+ new Rect(0, 0, mMirrorViewBounds.width(), mMirrorViewBounds.height())));
+ }
updateSystemUIStateIfNeeded();
mWindowMagnifierCallback.onWindowMagnifierBoundsChanged(
mDisplayId, mMirrorViewBounds);
@@ -269,6 +276,7 @@
if (mMirrorWindowControl != null) {
mMirrorWindowControl.destroyControl();
}
+ mMirrorViewBounds.setEmpty();
updateSystemUIStateIfNeeded();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
index ca59393..76fb49a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
@@ -130,19 +130,29 @@
@Override
public void onAuthenticationFailed(
@Modality int modality, @Nullable String failureReason) {
- if (modality == TYPE_FACE && mActiveSensorType == TYPE_FACE) {
- // switching from face -> fingerprint mode, suppress soft error messages
- failureReason = mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
+ super.onAuthenticationFailed(modality, checkErrorForFallback(failureReason));
+ }
+
+ @Override
+ public void onError(int modality, String error) {
+ super.onError(modality, checkErrorForFallback(error));
+ }
+
+ private String checkErrorForFallback(String message) {
+ if (mActiveSensorType == TYPE_FACE) {
+ Log.d(TAG, "Falling back to fingerprint: " + message);
+
+ // switching from face -> fingerprint mode, suppress root error messages
+ mCallback.onAction(Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR);
+ return mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
}
- super.onAuthenticationFailed(modality, failureReason);
+ return message;
}
@Override
@BiometricState
protected int getStateForAfterError() {
if (mActiveSensorType == TYPE_FACE) {
- mHandler.post(() -> mCallback.onAction(
- Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
return STATE_AUTHENTICATING;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
index c2a6255..69d49d4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
@@ -24,7 +24,6 @@
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.policy.NextAlarmController
import java.util.Locale
import javax.inject.Inject
@@ -38,7 +37,6 @@
statusBarStateController: StatusBarStateController,
activityStarter: ActivityStarter,
qsLogger: QSLogger,
- private val featureFlags: FeatureFlags,
private val userTracker: UserTracker,
nextAlarmController: NextAlarmController
) : QSTileImpl<QSTile.State>(
@@ -65,10 +63,6 @@
nextAlarmController.observe(this, callback)
}
- override fun isAvailable(): Boolean {
- return featureFlags.isAlarmTileAvailable
- }
-
override fun newTileState(): QSTile.State {
return QSTile.State().apply {
handlesLongClick = false
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index 7fab0f5..0e4434b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -49,7 +49,6 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
@@ -71,7 +70,6 @@
private final PackageManager mPackageManager;
private final SecureSettings mSecureSettings;
private final QuickAccessWalletController mController;
- private final FeatureFlags mFeatureFlags;
private WalletCard mSelectedCard;
@VisibleForTesting Drawable mCardViewDrawable;
@@ -89,15 +87,13 @@
KeyguardStateController keyguardStateController,
PackageManager packageManager,
SecureSettings secureSettings,
- QuickAccessWalletController quickAccessWalletController,
- FeatureFlags featureFlags) {
+ QuickAccessWalletController quickAccessWalletController) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = quickAccessWalletController;
mKeyguardStateController = keyguardStateController;
mPackageManager = packageManager;
mSecureSettings = secureSettings;
- mFeatureFlags = featureFlags;
}
@@ -192,8 +188,7 @@
@Override
public boolean isAvailable() {
- return mFeatureFlags.isQuickAccessWalletEnabled()
- && mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
+ return mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
&& !mPackageManager.hasSystemFeature(FEATURE_CHROME_OS)
&& mSecureSettings.getString(NFC_PAYMENT_DEFAULT_COMPONENT) != null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index c7b6e67..7e67619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -65,18 +65,10 @@
return mFlagReader.isEnabled(R.bool.flag_monet);
}
- public boolean isQuickAccessWalletEnabled() {
- return mFlagReader.isEnabled(R.bool.flag_wallet);
- }
-
public boolean isPMLiteEnabled() {
return mFlagReader.isEnabled(R.bool.flag_pm_lite);
}
- public boolean isAlarmTileAvailable() {
- return mFlagReader.isEnabled(R.bool.flag_alarm_tile);
- }
-
public boolean isChargingRippleEnabled() {
return mFlagReader.isEnabled(R.bool.flag_charging_ripple);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index f7b3a35..085a076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -26,6 +26,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
@@ -53,6 +55,11 @@
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
+ // More extreme version of SLOW_OUT_LINEAR_IN which keeps the icon nearly invisible until after
+ // the next icon has translated out of the way, to avoid overlapping.
+ private static final Interpolator ICON_ALPHA_INTERPOLATOR =
+ new PathInterpolator(0.6f, 0f, 0.6f, 0f);
+
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
private boolean mHideBackground;
@@ -659,7 +666,7 @@
if (iconState == null) {
return;
}
- iconState.alpha = transitionAmount;
+ iconState.alpha = ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount);
boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf();
iconState.hidden = isAppearing
|| (view instanceof ExpandableNotificationRow
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 5ebcd61..fda24c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1126,10 +1126,7 @@
mKeyguardBottomArea.setStatusBar(mStatusBar);
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
mKeyguardBottomArea.setFalsingManager(mFalsingManager);
-
- if (mFeatureFlags.isQuickAccessWalletEnabled()) {
- mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
- }
+ mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
}
private void updateMaxDisplayedNotifications(boolean recompute) {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index d61848c..e0ff88b 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -75,6 +75,10 @@
static final String COLOR_SOURCE_PRESET = "preset";
+ static final String COLOR_SOURCE_HOME = "home_wallpaper";
+
+ static final String COLOR_SOURCE_LOCK = "lock_wallpaper";
+
static final String TIMESTAMP_FIELD = "_applied_timestamp";
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index c23e0b4..428921e 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -16,6 +16,8 @@
package com.android.systemui.theme;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_HOME;
+import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_LOCK;
import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_PRESET;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ACCENT_COLOR;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
@@ -200,36 +202,37 @@
String overlayPackageJson = mSecureSettings.getStringForUser(
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
currentUser);
- boolean isDestinationBoth = mWallpaperManager.getWallpaperId(
- WallpaperManager.FLAG_LOCK) < 0;
- if (!TextUtils.isEmpty(overlayPackageJson)) {
- try {
- JSONObject jsonObject = new JSONObject(overlayPackageJson);
- if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
- && ((flags & latestWallpaperType) != 0)) {
- mSkipSettingChange = true;
- if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
- OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
- jsonObject.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
- jsonObject.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
- jsonObject.remove(OVERLAY_COLOR_SOURCE);
- jsonObject.remove(OVERLAY_COLOR_INDEX);
- }
- // Keep color_both value because users can change either or both home and
- // lock screen wallpapers.
- jsonObject.put(OVERLAY_COLOR_BOTH, isDestinationBoth ? "1" : "0");
-
- jsonObject.put(TIMESTAMP_FIELD, System.currentTimeMillis());
- if (DEBUG) {
- Log.d(TAG, "Updating theme setting from "
- + overlayPackageJson + " to " + jsonObject.toString());
- }
- mSecureSettings.putString(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
- jsonObject.toString());
+ boolean isDestinationBoth = (flags == (WallpaperManager.FLAG_SYSTEM
+ | WallpaperManager.FLAG_LOCK));
+ try {
+ JSONObject jsonObject = (overlayPackageJson == null) ? new JSONObject()
+ : new JSONObject(overlayPackageJson);
+ if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
+ && ((flags & latestWallpaperType) != 0)) {
+ mSkipSettingChange = true;
+ if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
+ OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
+ jsonObject.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
+ jsonObject.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+ jsonObject.remove(OVERLAY_COLOR_INDEX);
}
- } catch (JSONException e) {
- Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
+ // Keep color_both value because users can change either or both home and
+ // lock screen wallpapers.
+ jsonObject.put(OVERLAY_COLOR_BOTH, isDestinationBoth ? "1" : "0");
+
+ jsonObject.put(OVERLAY_COLOR_SOURCE,
+ (flags == WallpaperManager.FLAG_LOCK) ? COLOR_SOURCE_LOCK
+ : COLOR_SOURCE_HOME);
+ jsonObject.put(TIMESTAMP_FIELD, System.currentTimeMillis());
+ if (DEBUG) {
+ Log.d(TAG, "Updating theme setting from "
+ + overlayPackageJson + " to " + jsonObject.toString());
+ }
+ mSecureSettings.putString(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
+ jsonObject.toString());
}
+ } catch (JSONException e) {
+ Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
}
reevaluateSystemTheme(false /* forceReload */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index ad99e4d..f62069d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -77,6 +77,8 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
@LargeTest
@RunWith(AndroidTestingRunner.class)
public class WindowMagnificationControllerTest extends SysuiTestCase {
@@ -152,6 +154,19 @@
}
@Test
+ public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN);
+ });
+ // Wait for Rects updated.
+ waitForIdleSync();
+
+ List<Rect> rects = mWindowManager.getAttachedView().getSystemGestureExclusionRects();
+ assertFalse(rects.isEmpty());
+ }
+
+ @Test
public void deleteWindowMagnification_destroyControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
index aed0da6..82bf041 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
@@ -22,6 +22,8 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -124,16 +126,50 @@
}
@Test
- public void testModeUpdated_whenSwitchToFingerprint() {
+ public void testModeUpdated_onSoftError_whenSwitchToFingerprint() {
mFaceToFpView.onDialogAnimatedIn();
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
waitForIdleSync();
verify(mIndicatorView).setText(
eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
+ verify(mCallback).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
}
+ @Test
+ public void testModeUpdated_onHardError_whenSwitchToFingerprint() {
+ mFaceToFpView.onDialogAnimatedIn();
+ mFaceToFpView.onError(TYPE_FACE, "oh no!");
+ waitForIdleSync();
+
+ verify(mIndicatorView).setText(
+ eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
+ verify(mCallback).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
+ assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
+ }
+
+ @Test
+ public void testFingerprintOnlyStartsOnFirstError() {
+ mFaceToFpView.onDialogAnimatedIn();
+ verify(mFaceToFpView.mIconController)
+ .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
+
+ mFaceToFpView.onDialogAnimatedIn();
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_ERROR);
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);
+
+ reset(mCallback);
+
+ mFaceToFpView.onError(TYPE_FACE, "oh no!");
+ mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
+
+ verify(mCallback, never()).onAction(
+ eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
+ }
+
public class TestableView extends AuthBiometricFaceToFingerprintView {
public TestableView(Context context) {
super(context, null, new MockInjector());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index a435768..32b1f43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -16,7 +16,6 @@
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.policy.NextAlarmController
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -47,8 +46,6 @@
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
private lateinit var userTracker: UserTracker
@Mock
private lateinit var nextAlarmController: NextAlarmController
@@ -79,7 +76,6 @@
statusBarStateController,
activityStarter,
qsLogger,
- featureFlags,
userTracker,
nextAlarmController
)
@@ -90,14 +86,7 @@
}
@Test
- fun testNotAvailableFeatureFlag() {
- `when`(featureFlags.isAlarmTileAvailable).thenReturn(false)
- assertThat(tile.isAvailable).isFalse()
- }
-
- @Test
- fun testAvailableFeatureFlag() {
- `when`(featureFlags.isAlarmTileAvailable).thenReturn(true)
+ fun testAvailable() {
assertThat(tile.isAvailable).isTrue()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 09b0427..e4a9aac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -69,7 +69,6 @@
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
@@ -118,8 +117,6 @@
private SecureSettings mSecureSettings;
@Mock
private QuickAccessWalletController mController;
- @Mock
- private FeatureFlags mFeatureFlags;
@Captor
ArgumentCaptor<Intent> mIntentCaptor;
@Captor
@@ -139,7 +136,6 @@
doNothing().when(mSpiedContext).startActivity(any(Intent.class));
when(mHost.getContext()).thenReturn(mSpiedContext);
when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger);
- when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(true);
when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
@@ -158,8 +154,7 @@
mKeyguardStateController,
mPackageManager,
mSecureSettings,
- mController,
- mFeatureFlags);
+ mController);
}
@Test
@@ -168,12 +163,6 @@
}
@Test
- public void testIsAvailable_featureFlagIsOff() {
- when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(false);
- assertFalse(mTile.isAvailable());
- }
-
- @Test
public void testWalletServiceUnavailable_recreateWalletClient() {
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 3d2a0f1..3cf9212 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -232,9 +232,9 @@
verify(mSecureSettings).putString(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
- assertThat(updatedSetting.getValue().contains("android.theme.customization.system_palette"))
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.accent_color"))
.isFalse();
- assertThat(updatedSetting.getValue().contains("android.theme.customization.color_source"))
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.system_palette"))
.isFalse();
assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
.isFalse();
@@ -289,7 +289,8 @@
.thenReturn(jsonString);
when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(-1);
- mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+ mColorsListener.getValue().onColorsChanged(mainColors,
+ WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
verify(mSecureSettings).putString(
@@ -303,6 +304,60 @@
}
@Test
+ public void onWallpaperColorsChanged_changeLockWallpaper() {
+ // Should ask for a new theme when wallpaper colors change
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+ String jsonString =
+ "{\"android.theme.customization.system_palette\":\"override.package.name\","
+ + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.color_index\":\"2\"}";
+ when(mSecureSettings.getStringForUser(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+ .thenReturn(jsonString);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(1);
+
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_LOCK);
+
+ ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+ verify(mSecureSettings).putString(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+ assertThat(updatedSetting.getValue().contains(
+ "android.theme.customization.color_source\":\"lock_wallpaper")).isTrue();
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
+ .isFalse();
+ verify(mThemeOverlayApplier)
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
+ public void onWallpaperColorsChanged_changeHomeWallpaper() {
+ // Should ask for a new theme when wallpaper colors change
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+ String jsonString =
+ "{\"android.theme.customization.system_palette\":\"override.package.name\","
+ + "\"android.theme.customization.color_source\":\"lock_wallpaper\","
+ + "\"android.theme.customization.color_index\":\"2\"}";
+ when(mSecureSettings.getStringForUser(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+ .thenReturn(jsonString);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(-1);
+
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+ ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+ verify(mSecureSettings).putString(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+ assertThat(updatedSetting.getValue().contains(
+ "android.theme.customization.color_source\":\"home_wallpaper")).isTrue();
+ assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index"))
+ .isFalse();
+ verify(mThemeOverlayApplier)
+ .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
public void onWallpaperColorsChanged_ResetThemeWhenFromLatestWallpaper() {
// Should ask for a new theme when the colors of the last applied wallpaper change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c994d7c..c841fa3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5996,13 +5996,23 @@
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String callingPackage, String name, int userId,
boolean stable) {
- return mCpHelper.getContentProvider(caller, callingPackage, name, userId, stable);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "getContentProvider: ", name);
+ try {
+ return mCpHelper.getContentProvider(caller, callingPackage, name, userId, stable);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public ContentProviderHolder getContentProviderExternal(
String name, int userId, IBinder token, String tag) {
- return mCpHelper.getContentProviderExternal(name, userId, token, tag);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "getContentProviderExternal: ", name);
+ try {
+ return mCpHelper.getContentProviderExternal(name, userId, token, tag);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
/**
@@ -6017,18 +6027,57 @@
@Deprecated
@Override
public void removeContentProviderExternal(String name, IBinder token) {
- removeContentProviderExternalAsUser(name, token, UserHandle.getCallingUserId());
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "removeContentProviderExternal: ", name);
+ try {
+ removeContentProviderExternalAsUser(name, token, UserHandle.getCallingUserId());
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public void removeContentProviderExternalAsUser(String name, IBinder token, int userId) {
- mCpHelper.removeContentProviderExternalAsUser(name, token, userId);
+ traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "removeContentProviderExternalAsUser: ", name);
+ try {
+ mCpHelper.removeContentProviderExternalAsUser(name, token, userId);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
public final void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) {
- mCpHelper.publishContentProviders(caller, providers);
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ final int maxLength = 256;
+ final StringBuilder sb = new StringBuilder(maxLength);
+ sb.append("publishContentProviders: ");
+ if (providers != null) {
+ boolean first = true;
+ for (int i = 0, size = providers.size(); i < size; i++) {
+ final ContentProviderHolder holder = providers.get(i);
+ if (holder != null && holder.info != null && holder.info.authority != null) {
+ final int len = holder.info.authority.length();
+ if (sb.length() + len > maxLength) {
+ sb.append("[[TRUNCATED]]");
+ break;
+ }
+ if (!first) {
+ sb.append(';');
+ } else {
+ first = false;
+ }
+ sb.append(holder.info.authority);
+ }
+ }
+ }
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, sb.toString());
+ }
+ try {
+ mCpHelper.publishContentProviders(caller, providers);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@Override
@@ -17108,4 +17157,10 @@
SystemClock.sleep(durationMs);
}
}
+
+ static void traceBegin(long traceTag, String methodName, String subInfo) {
+ if (Trace.isTagEnabled(traceTag)) {
+ Trace.traceBegin(traceTag, methodName + subInfo);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index ab1da80..1611395 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -58,6 +58,7 @@
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -707,20 +708,28 @@
mService.enforceNotIsolatedCaller("removeContentProvider");
final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mService) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection) connection;
- } catch (ClassCastException e) {
- String msg = "removeContentProvider: " + connection
- + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection) connection;
+ } catch (ClassCastException e) {
+ String msg = "removeContentProvider: " + connection
+ + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "removeContentProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ synchronized (mService) {
+ decProviderCountLocked(conn, null, null, stable, true, true);
}
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
- decProviderCountLocked(conn, null, null, stable, true, true);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -781,8 +790,15 @@
throw new NullPointerException("connection is null");
}
- conn.adjustCounts(stable, unstable);
- return !conn.dead;
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "refContentProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ conn.adjustCounts(stable, unstable);
+ return !conn.dead;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
void unstableProviderDied(IBinder connection) {
@@ -798,50 +814,60 @@
throw new NullPointerException("connection is null");
}
- // Safely retrieve the content provider associated with the connection.
- IContentProvider provider;
- synchronized (mService) {
- provider = conn.provider.provider;
- }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "unstableProviderDied: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
- if (provider == null) {
- // Um, yeah, we're way ahead of you.
- return;
- }
-
- // Make sure the caller is being honest with us.
- if (provider.asBinder().pingBinder()) {
- // Er, no, still looks good to us.
+ try {
+ // Safely retrieve the content provider associated with the connection.
+ IContentProvider provider;
synchronized (mService) {
- Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
- + " says " + conn + " died, but we don't agree");
- return;
+ provider = conn.provider.provider;
}
- }
- // Well look at that! It's dead!
- synchronized (mService) {
- if (conn.provider.provider != provider) {
- // But something changed... good enough.
+ if (provider == null) {
+ // Um, yeah, we're way ahead of you.
return;
}
- ProcessRecord proc = conn.provider.proc;
- if (proc == null || proc.getThread() == null) {
- // Seems like the process is already cleaned up.
- return;
+ // Make sure the caller is being honest with us.
+ if (provider.asBinder().pingBinder()) {
+ // Er, no, still looks good to us.
+ synchronized (mService) {
+ Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
+ + " says " + conn + " died, but we don't agree");
+ return;
+ }
}
- // As far as we're concerned, this is just like receiving a
- // death notification... just a bit prematurely.
- mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
- + " (pid " + proc.getPid() + ") early provider death", proc.info.uid);
- final long token = Binder.clearCallingIdentity();
- try {
- mService.appDiedLocked(proc, "unstable content provider");
- } finally {
- Binder.restoreCallingIdentity(token);
+ // Well look at that! It's dead!
+ synchronized (mService) {
+ if (conn.provider.provider != provider) {
+ // But something changed... good enough.
+ return;
+ }
+
+ ProcessRecord proc = conn.provider.proc;
+ if (proc == null || proc.getThread() == null) {
+ // Seems like the process is already cleaned up.
+ return;
+ }
+
+ // As far as we're concerned, this is just like receiving a
+ // death notification... just a bit prematurely.
+ mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
+ + " (pid " + proc.getPid() + ") early provider death",
+ proc.info.uid);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mService.appDiedLocked(proc, "unstable content provider");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
@@ -855,13 +881,21 @@
return;
}
- final ProcessRecord host = conn.provider.proc;
- if (host == null) {
- Slog.w(TAG, "Failed to find hosting ProcessRecord");
- return;
- }
+ ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "appNotRespondingViaProvider: ",
+ (conn.provider != null && conn.provider.info != null
+ ? conn.provider.info.authority : ""));
+ try {
+ final ProcessRecord host = conn.provider.proc;
+ if (host == null) {
+ Slog.w(TAG, "Failed to find hosting ProcessRecord");
+ return;
+ }
- mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
+ mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
/**
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 36dc5cd..ef02a47 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -355,10 +355,6 @@
}
}
- private void cancelAllFingerprintSensors() {
- cancelAllSensors(sensor -> sensor.modality == TYPE_FINGERPRINT);
- }
-
private void cancelAllSensors() {
cancelAllSensors(sensor -> true);
}
@@ -387,6 +383,9 @@
*/
boolean onErrorReceived(int sensorId, int cookie, @BiometricConstants.Errors int error,
int vendorCode) throws RemoteException {
+ if (DEBUG) {
+ Slog.v(TAG, "onErrorReceived sensor: " + sensorId + " error: " + error);
+ }
if (!containsCookie(cookie)) {
Slog.e(TAG, "Unknown/expired cookie: " + cookie);
@@ -454,12 +453,14 @@
// a round trip to SystemUI.
mClientReceiver.onError(modality, error, vendorCode);
return true;
- } else if (shouldErrorTriggerMultiSensorTransition()) {
- // wait for the UI to signal when modality should switch
- mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
- Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
} else {
mState = STATE_ERROR_PENDING_SYSUI;
+ if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT
+ && mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING) {
+ // wait for the UI to signal when modality should switch
+ Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
+ mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
+ }
mStatusBarService.onBiometricError(modality, error, vendorCode);
}
break;
@@ -627,7 +628,7 @@
void onDeviceCredentialPressed() {
// Cancel authentication. Skip the token/package check since we are cancelling
// from system server. The interface is permission protected so this is fine.
- cancelBiometricOnly();
+ cancelAllSensors();
mState = STATE_SHOWING_DEVICE_CREDENTIAL;
}
@@ -733,12 +734,10 @@
}
mClientReceiver.onAuthenticationSucceeded(
Utils.getAuthenticationTypeForResult(reason));
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
mClientReceiver.onDialogDismissed(reason);
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
@@ -747,7 +746,6 @@
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
0 /* vendorCode */
);
- cancelBiometricOnly();
break;
case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
@@ -765,6 +763,9 @@
}
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
+ } finally {
+ // ensure everything is cleaned up when dismissed
+ cancelAllSensors();
}
}
@@ -780,8 +781,8 @@
|| mState == STATE_AUTH_STARTED
|| mState == STATE_AUTH_STARTED_UI_SHOWING;
+ cancelAllSensors();
if (authStarted && !force) {
- cancelAllSensors();
// Wait for ERROR_CANCELED to be returned from the sensors
return false;
} else {
@@ -804,22 +805,6 @@
return false;
}
- /**
- * Cancels biometric authentication only. AuthSession may either be going into
- * {@link #STATE_SHOWING_DEVICE_CREDENTIAL} or dismissed.
- */
- private void cancelBiometricOnly() {
- if (mState == STATE_AUTH_STARTED || mState == STATE_AUTH_STARTED_UI_SHOWING) {
- cancelAllSensors();
- } else if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
- cancelAllFingerprintSensors();
- } else {
- if (DEBUG) {
- Slog.v(TAG, "nothing to cancel - wrong state: " + mState);
- }
- }
- }
-
boolean isCrypto() {
return mOperationId != 0;
}
@@ -896,13 +881,6 @@
}
}
- private boolean shouldErrorTriggerMultiSensorTransition() {
- if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
- return mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING;
- }
- return false;
- }
-
@BiometricMultiSensorMode
private static int getMultiSensorModeForNewSession(Collection<BiometricSensor> sensors) {
boolean hasFace = false;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index b0f8ee1..92b6a08 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -5495,7 +5495,8 @@
final int result = checkPermission(mContext, permission, attributionSource, message,
forDataDelivery, startDataDelivery, fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
- if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
+ if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
+ && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
if (attributedOp == AppOpsManager.OP_NONE) {
finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
attributionSource.asState(), fromDatasource);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 2b40b75..5362771 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -156,6 +156,7 @@
@VisibleForTesting
boolean mShouldAttachNavBarToAppDuringTransition;
private boolean mNavigationBarAttachedToApp;
+ private ActivityRecord mNavBarAttachedApp;
/**
* Animates the screenshot of task that used to be controlled by RecentsAnimation.
@@ -392,6 +393,18 @@
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public void animateNavigationBarToApp(long duration) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ animateNavigationBarForAppLaunch(duration);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
};
/**
@@ -613,7 +626,6 @@
|| mDisplayContent.getFadeRotationAnimationController() != null) {
return;
}
- ActivityRecord topActivity = null;
boolean shouldTranslateNavBar = false;
final boolean isDisplayLandscape =
mDisplayContent.getConfiguration().orientation == ORIENTATION_LANDSCAPE;
@@ -630,12 +642,12 @@
continue;
}
shouldTranslateNavBar = isSplitScreenSecondary;
- topActivity = task.getTopVisibleActivity();
+ mNavBarAttachedApp = task.getTopVisibleActivity();
break;
}
final WindowState navWindow = getNavigationBarWindow();
- if (topActivity == null || navWindow == null || navWindow.mToken == null) {
+ if (mNavBarAttachedApp == null || navWindow == null || navWindow.mToken == null) {
return;
}
mNavigationBarAttachedToApp = true;
@@ -643,9 +655,9 @@
final SurfaceControl.Transaction t = navWindow.mToken.getPendingTransaction();
final SurfaceControl navSurfaceControl = navWindow.mToken.getSurfaceControl();
if (shouldTranslateNavBar) {
- navWindow.setSurfaceTranslationY(-topActivity.getBounds().top);
+ navWindow.setSurfaceTranslationY(-mNavBarAttachedApp.getBounds().top);
}
- t.reparent(navSurfaceControl, topActivity.getSurfaceControl());
+ t.reparent(navSurfaceControl, mNavBarAttachedApp.getSurfaceControl());
t.show(navSurfaceControl);
final WindowContainer imeContainer = mDisplayContent.getImeContainer();
@@ -695,9 +707,25 @@
}
}
+ void animateNavigationBarForAppLaunch(long duration) {
+ if (!mShouldAttachNavBarToAppDuringTransition
+ // Skip the case where the nav bar is controlled by fade rotation.
+ || mDisplayContent.getFadeRotationAnimationController() != null
+ || mNavigationBarAttachedToApp
+ || mNavBarAttachedApp == null) {
+ return;
+ }
+
+ final NavBarFadeAnimationController controller =
+ new NavBarFadeAnimationController(mDisplayContent);
+ controller.fadeOutAndInSequentially(duration, null /* fadeOutParent */,
+ mNavBarAttachedApp.getSurfaceControl());
+ }
+
void addTaskToTargets(Task task, OnAnimationFinishedCallback finishedCallback) {
if (mRunner != null) {
mIsAddingTaskToTargets = task != null;
+ mNavBarAttachedApp = task == null ? null : task.getTopVisibleActivity();
// No need to send task appeared when the task target already exists, or when the
// task is being managed as a multi-window mode outside of recents (e.g. bubbles).
if (isAnimatingTask(task) || skipAnimation(task)) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 4afb7dd..2892bf5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -18,6 +18,7 @@
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
import static com.android.server.biometrics.BiometricServiceStateProto.*;
@@ -38,7 +39,6 @@
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.Context;
-import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricAuthenticator;
@@ -67,6 +67,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import java.util.function.Consumer;
@Presubmit
@SmallTest
@@ -245,9 +246,6 @@
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
assertEquals(BiometricSensor.STATE_COOKIE_RETURNED,
session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
- session.onErrorReceived(fingerprintSensorId,
- session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getCookie(),
- BiometricConstants.BIOMETRIC_ERROR_VENDOR, 0 /* vendorCode */);
session.onStartFingerprint();
}
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
@@ -258,6 +256,21 @@
@Test
public void testCancelAuthentication_whenStateAuthCalled_invokesCancel()
throws RemoteException {
+ testInvokesCancel(session -> session.onCancelAuthSession(false /* force */));
+ }
+
+ @Test
+ public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()
+ throws RemoteException {
+ testInvokesCancel(session -> session.onCancelAuthSession(true /* force */));
+ }
+
+ @Test
+ public void testCancelAuthentication_whenDialogDismissed() throws RemoteException {
+ testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null));
+ }
+
+ private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException {
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
@@ -269,7 +282,8 @@
session.goToInitialState();
assertEquals(STATE_AUTH_CALLED, session.getState());
- session.onCancelAuthSession(false /* force */);
+
+ sessionConsumer.accept(session);
verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE));
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index ae836ce..7c7afb7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -1036,7 +1036,7 @@
}
@Test
- public void testDismissedReasonNegative_whilePaused_doesntInvokeHalCancel() throws Exception {
+ public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception {
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */, null /* authenticators */);
@@ -1050,14 +1050,12 @@
BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */);
waitForIdle();
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
}
@Test
- public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws
+ public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws
Exception {
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
@@ -1072,10 +1070,8 @@
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
waitForIdle();
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
}
@Test
@@ -1091,11 +1087,8 @@
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
waitForIdle();
- // doesn't send cancel to HAL
- verify(mBiometricService.mSensors.get(0).impl,
- never()).cancelAuthenticationFromService(
- any(),
- any());
+ verify(mBiometricService.mSensors.get(0).impl)
+ .cancelAuthenticationFromService(any(), any());
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_FACE),
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 4d5b6ac..88efe1f 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1069,6 +1069,13 @@
*/
public static final int NO_DEFAULT_DATA = 0x10008;
+ /**
+ * Data service is temporarily unavailable.
+ *
+ * @hide
+ */
+ public static final int SERVICE_TEMPORARILY_UNAVAILABLE = 0x10009;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
@@ -1500,6 +1507,7 @@
sFailCauseMap.put(HANDOVER_FAILED, "HANDOVER_FAILED");
sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID");
sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA");
+ sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
}
private DataFailCause() {
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 363e47a..d082715 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -63,6 +63,11 @@
public static final int RESULT_ERROR_BUSY = 3;
/** Request sent in illegal state */
public static final int RESULT_ERROR_ILLEGAL_STATE = 4;
+ /**
+ * Service is temporarily unavailable. Frameworks should retry the request again.
+ * @hide
+ */
+ public static final int RESULT_ERROR_TEMPORARILY_UNAVAILABLE = 5;
private final IDataServiceCallback mCallback;