summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt3
-rw-r--r--core/api/removed.txt5
-rw-r--r--core/java/android/app/Notification.java46
-rw-r--r--core/java/android/companion/virtual/VirtualDevice.java26
-rw-r--r--core/java/android/companion/virtual/flags.aconfig7
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java52
-rw-r--r--core/java/android/view/TextureView.java16
-rw-r--r--core/java/android/view/View.java9
-rw-r--r--core/java/android/window/StartingWindowInfo.java4
-rw-r--r--core/jni/Android.bp1
-rw-r--r--core/jni/android_graphics_SurfaceTexture.cpp151
-rw-r--r--core/tests/coretests/src/android/app/NotificationTest.java46
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java90
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java25
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt15
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp3
-rw-r--r--packages/SettingsLib/tests/integ/AndroidManifest.xml2
-rw-r--r--packages/SettingsLib/tests/integ/AndroidTest.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java3
-rw-r--r--services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java11
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java25
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerException.java3
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java63
-rw-r--r--services/core/java/com/android/server/wm/StartingSurfaceController.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java54
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java4
31 files changed, 532 insertions, 166 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index f640ea25a22b..c9f06397abbf 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6749,7 +6749,6 @@ package android.app {
method public android.app.Notification.WearableExtender clone();
method public android.app.Notification.Builder extend(android.app.Notification.Builder);
method public java.util.List<android.app.Notification.Action> getActions();
- method @Deprecated public android.graphics.Bitmap getBackground();
method public String getBridgeTag();
method public int getContentAction();
method @Deprecated public int getContentIcon();
@@ -6768,7 +6767,6 @@ package android.app {
method @Deprecated public boolean getHintShowBackgroundOnly();
method @Deprecated public java.util.List<android.app.Notification> getPages();
method public boolean getStartScrollBottom();
- method @Deprecated public android.app.Notification.WearableExtender setBackground(android.graphics.Bitmap);
method public android.app.Notification.WearableExtender setBridgeTag(String);
method public android.app.Notification.WearableExtender setContentAction(int);
method @Deprecated public android.app.Notification.WearableExtender setContentIcon(int);
@@ -9682,6 +9680,7 @@ package android.companion.virtual {
method public int describeContents();
method public int getDeviceId();
method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @NonNull public int[] getDisplayIds();
+ method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @Nullable public CharSequence getDisplayName();
method @Nullable public String getName();
method @Nullable public String getPersistentDeviceId();
method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") public boolean hasCustomSensorSupport();
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 8b3696a1e6d9..57e2e73854c1 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -23,6 +23,11 @@ package android.app {
method @Deprecated public android.app.Notification.Builder setTimeout(long);
}
+ public static final class Notification.WearableExtender implements android.app.Notification.Extender {
+ method @Deprecated public android.graphics.Bitmap getBackground();
+ method @Deprecated public android.app.Notification.WearableExtender setBackground(android.graphics.Bitmap);
+ }
+
}
package android.app.slice {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c42df3c8819..93c2b5ad4d86 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -44,6 +44,9 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.admin.DevicePolicyManager;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -296,6 +299,15 @@ public class Notification implements Parcelable
public static final String EXTRA_REMOTE_INPUT_DRAFT = "android.remoteInputDraft";
/**
+ * The call to WearableExtender#setBackground(Bitmap) will have no effect and the passed
+ * Bitmap will not be retained in memory.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @VisibleForTesting
+ static final long WEARABLE_EXTENDER_BACKGROUND_BLOCKED = 270551184L;
+
+ /**
* A timestamp related to this notification, in milliseconds since the epoch.
*
* Default value: {@link System#currentTimeMillis() Now}.
@@ -11148,9 +11160,20 @@ public class Notification implements Parcelable
wearableBundle.putParcelableArray(KEY_PAGES, mPages.toArray(
new Notification[mPages.size()]));
}
+
if (mBackground != null) {
- wearableBundle.putParcelable(KEY_BACKGROUND, mBackground);
+ // Keeping WearableExtender backgrounds in memory despite them being deprecated has
+ // added noticeable increase in system server and system ui memory usage. After
+ // target VERSION_CODE#VANILLA_ICE_CREAM the background will not be populated
+ // anymore.
+ if (CompatChanges.isChangeEnabled(WEARABLE_EXTENDER_BACKGROUND_BLOCKED)) {
+ Log.d(TAG, "Use of background in WearableExtenders has been deprecated and "
+ + "will not be populated anymore.");
+ } else {
+ wearableBundle.putParcelable(KEY_BACKGROUND, mBackground);
+ }
}
+
if (mContentIcon != 0) {
wearableBundle.putInt(KEY_CONTENT_ICON, mContentIcon);
}
@@ -11369,12 +11392,21 @@ public class Notification implements Parcelable
*
* @param background the background bitmap
* @return this object for method chaining
- * @see android.app.Notification.WearableExtender#getBackground
- * @deprecated Background images are no longer supported.
+ * @removed Not functional since {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}.
+ * The wearable background is not used by wearables anymore and uses up
+ * unnecessary memory.
*/
@Deprecated
public WearableExtender setBackground(Bitmap background) {
- mBackground = background;
+ // Keeping WearableExtender backgrounds in memory despite them being deprecated has
+ // added noticeable increase in system server and system ui memory usage. After
+ // target VERSION_CODE#VANILLA_ICE_CREAM the background will not be populated anymore.
+ if (CompatChanges.isChangeEnabled(WEARABLE_EXTENDER_BACKGROUND_BLOCKED)) {
+ Log.d(TAG, "Use of background in WearableExtenders has been deprecated and "
+ + "will not be populated anymore.");
+ } else {
+ mBackground = background;
+ }
return this;
}
@@ -11384,11 +11416,13 @@ public class Notification implements Parcelable
* will work with any notification style.
*
* @return the background image
- * @see android.app.Notification.WearableExtender#setBackground
- * @deprecated Background images are no longer supported.
+ * @removed Not functional since {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. The
+ * wearable background is not used by wearables anymore and uses up
+ * unnecessary memory.
*/
@Deprecated
public Bitmap getBackground() {
+ Log.w(TAG, "Use of background in WearableExtender has been removed, returning null.");
return mBackground;
}
diff --git a/core/java/android/companion/virtual/VirtualDevice.java b/core/java/android/companion/virtual/VirtualDevice.java
index 4692f921beb2..ce883cddc952 100644
--- a/core/java/android/companion/virtual/VirtualDevice.java
+++ b/core/java/android/companion/virtual/VirtualDevice.java
@@ -44,6 +44,7 @@ public final class VirtualDevice implements Parcelable {
private final int mId;
private final @Nullable String mPersistentId;
private final @Nullable String mName;
+ private final @Nullable CharSequence mDisplayName;
/**
* Creates a new instance of {@link VirtualDevice}.
@@ -53,6 +54,18 @@ public final class VirtualDevice implements Parcelable {
*/
public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id,
@Nullable String persistentId, @Nullable String name) {
+ this(virtualDevice, id, persistentId, name, null);
+ }
+
+ /**
+ * Creates a new instance of {@link VirtualDevice}. Only to be used by the
+ * VirtualDeviceManagerService.
+ *
+ * @hide
+ */
+ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id,
+ @Nullable String persistentId, @Nullable String name,
+ @Nullable CharSequence displayName) {
if (id <= Context.DEVICE_ID_DEFAULT) {
throw new IllegalArgumentException("VirtualDevice ID must be greater than "
+ Context.DEVICE_ID_DEFAULT);
@@ -61,6 +74,7 @@ public final class VirtualDevice implements Parcelable {
mId = id;
mPersistentId = persistentId;
mName = name;
+ mDisplayName = displayName;
}
private VirtualDevice(@NonNull Parcel parcel) {
@@ -68,6 +82,7 @@ public final class VirtualDevice implements Parcelable {
mId = parcel.readInt();
mPersistentId = parcel.readString8();
mName = parcel.readString8();
+ mDisplayName = parcel.readCharSequence();
}
/**
@@ -112,6 +127,15 @@ public final class VirtualDevice implements Parcelable {
}
/**
+ * Returns the human-readable name of the virtual device, if defined, which is suitable to be
+ * shown in UI.
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public @Nullable CharSequence getDisplayName() {
+ return mDisplayName;
+ }
+
+ /**
* Returns the IDs of all virtual displays that belong to this device, if any.
*
* <p>The actual {@link android.view.Display} objects can be obtained by passing the returned
@@ -156,6 +180,7 @@ public final class VirtualDevice implements Parcelable {
dest.writeInt(mId);
dest.writeString8(mPersistentId);
dest.writeString8(mName);
+ dest.writeCharSequence(mDisplayName);
}
@Override
@@ -165,6 +190,7 @@ public final class VirtualDevice implements Parcelable {
+ " mId=" + mId
+ " mPersistentId=" + mPersistentId
+ " mName=" + mName
+ + " mDisplayName=" + mDisplayName
+ ")";
}
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 3e96c96d8d17..d0e13cd977ef 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -34,3 +34,10 @@ flag {
description: "Enable Virtual Camera"
bug: "270352264"
}
+
+flag {
+ name: "stream_permissions"
+ namespace: "virtual_devices"
+ description: "Enable streaming permission dialogs to Virtual Devices"
+ bug: "291737919"
+}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 94d851603064..6a82f6da67b3 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -959,8 +959,8 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
mKeyphraseMetadata = new KeyphraseMetadata(1, mText, fakeSupportedLocales,
AlwaysOnHotwordDetector.RECOGNITION_MODE_VOICE_TRIGGER);
}
- notifyStateChangedLocked();
}
+ notifyStateChanged(availability);
}
/**
@@ -1370,8 +1370,8 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
mAvailability = STATE_INVALID;
mIsAvailabilityOverriddenByTestApi = false;
- notifyStateChangedLocked();
}
+ notifyStateChanged(STATE_INVALID);
super.destroy();
}
@@ -1401,6 +1401,8 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
*/
// TODO(b/281608561): remove the enrollment flow from AlwaysOnHotwordDetector
void onSoundModelsChanged() {
+ boolean notifyError = false;
+
synchronized (mLock) {
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE
@@ -1441,6 +1443,9 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
// calling stopRecognition where there is no started session.
Log.w(TAG, "Failed to stop recognition after enrollment update: code="
+ result);
+
+ // Execute a refresh availability task - which should then notify of a change.
+ new RefreshAvailabilityTask().execute();
} catch (Exception e) {
Slog.w(TAG, "Failed to stop recognition after enrollment update", e);
if (CompatChanges.isChangeEnabled(SEND_ON_FAILURE_FOR_ASYNC_EXCEPTIONS)) {
@@ -1449,14 +1454,14 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
+ Log.getStackTraceString(e),
FailureSuggestedAction.RECREATE_DETECTOR));
} else {
- updateAndNotifyStateChangedLocked(STATE_ERROR);
+ notifyError = true;
}
- return;
}
}
+ }
- // Execute a refresh availability task - which should then notify of a change.
- new RefreshAvailabilityTask().execute();
+ if (notifyError) {
+ updateAndNotifyStateChanged(STATE_ERROR);
}
}
@@ -1572,10 +1577,11 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
}
}
- @GuardedBy("mLock")
- private void updateAndNotifyStateChangedLocked(int availability) {
- updateAvailabilityLocked(availability);
- notifyStateChangedLocked();
+ private void updateAndNotifyStateChanged(int availability) {
+ synchronized (mLock) {
+ updateAvailabilityLocked(availability);
+ }
+ notifyStateChanged(availability);
}
@GuardedBy("mLock")
@@ -1589,17 +1595,17 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
}
}
- @GuardedBy("mLock")
- private void notifyStateChangedLocked() {
+ private void notifyStateChanged(int newAvailability) {
Message message = Message.obtain(mHandler, MSG_AVAILABILITY_CHANGED);
- message.arg1 = mAvailability;
+ message.arg1 = newAvailability;
message.sendToTarget();
}
- @GuardedBy("mLock")
private void sendUnknownFailure(String failureMessage) {
- // update but do not call onAvailabilityChanged callback for STATE_ERROR
- updateAvailabilityLocked(STATE_ERROR);
+ synchronized (mLock) {
+ // update but do not call onAvailabilityChanged callback for STATE_ERROR
+ updateAvailabilityLocked(STATE_ERROR);
+ }
Message.obtain(mHandler, MSG_DETECTION_UNKNOWN_FAILURE, failureMessage).sendToTarget();
}
@@ -1802,19 +1808,17 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
availability = STATE_KEYPHRASE_UNENROLLED;
}
}
- updateAndNotifyStateChangedLocked(availability);
}
+ updateAndNotifyStateChanged(availability);
} catch (Exception e) {
// Any exception here not caught will crash the process because AsyncTask does not
// bubble up the exceptions to the client app, so we must propagate it to the app.
Slog.w(TAG, "Failed to refresh availability", e);
- synchronized (mLock) {
- if (CompatChanges.isChangeEnabled(SEND_ON_FAILURE_FOR_ASYNC_EXCEPTIONS)) {
- sendUnknownFailure(
- "Failed to refresh availability: " + Log.getStackTraceString(e));
- } else {
- updateAndNotifyStateChangedLocked(STATE_ERROR);
- }
+ if (CompatChanges.isChangeEnabled(SEND_ON_FAILURE_FOR_ASYNC_EXCEPTIONS)) {
+ sendUnknownFailure(
+ "Failed to refresh availability: " + Log.getStackTraceString(e));
+ } else {
+ updateAndNotifyStateChanged(STATE_ERROR);
}
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index bdd0a9cf653a..969b6a5125d0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -30,8 +31,10 @@ import android.graphics.SurfaceTexture;
import android.graphics.TextureLayer;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.flags.Flags;
/**
* <p>A TextureView can be used to display a content stream, such as that
@@ -194,6 +197,9 @@ public class TextureView extends View {
private Canvas mCanvas;
private int mSaveCount;
+ @FloatRange(from = 0.0) float mFrameRate;
+ @Surface.FrameRateCompatibility int mFrameRateCompatibility;
+
private final Object[] mNativeWindowLock = new Object[0];
// Set by native code, do not write!
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -465,6 +471,16 @@ public class TextureView extends View {
mLayer.setSurfaceTexture(mSurface);
mSurface.setDefaultBufferSize(getWidth(), getHeight());
mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
+ if (Flags.toolkitSetFrameRate()) {
+ mSurface.setOnSetFrameRateListener(
+ (surfaceTexture, frameRate, compatibility, strategy) -> {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.instant(Trace.TRACE_TAG_VIEW, "setFrameRate: " + frameRate);
+ }
+ mFrameRate = frameRate;
+ mFrameRateCompatibility = compatibility;
+ }, mAttachInfo.mHandler);
+ }
if (mListener != null && createNewSurface) {
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 55374b994cd4..5eaded218a0b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8562,6 +8562,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* announcements every time a View is updated.
*
* <p>
+ * For notifying users about errors, such as in a login screen with text that displays an
+ * "incorrect password" notification, that view should send an AccessibilityEvent of type
+ * {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR} and set
+ * {@link AccessibilityNodeInfo#setError(CharSequence)} instead. Custom widgets should expose
+ * error-setting methods that support accessibility automatically. For example, instead of
+ * explicitly sending this event when using a TextView, use
+ * {@link android.widget.TextView#setError(CharSequence)}.
+ *
+ * <p>
* Use {@link #setStateDescription(CharSequence)} to convey state changes to views within the
* user interface. While a live region may send different types of events generated by the view,
* state description will send {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events of
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index a88e394c0985..451acbe84a60 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -122,7 +122,7 @@ public final class StartingWindowInfo implements Parcelable {
TYPE_PARAMETER_PROCESS_RUNNING,
TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
TYPE_PARAMETER_ACTIVITY_CREATED,
- TYPE_PARAMETER_ALLOW_ICON,
+ TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN,
TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN,
TYPE_PARAMETER_WINDOWLESS,
TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
@@ -143,7 +143,7 @@ public final class StartingWindowInfo implements Parcelable {
/** @hide */
public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
/** @hide */
- public static final int TYPE_PARAMETER_ALLOW_ICON = 0x00000020;
+ public static final int TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN = 0x00000020;
/**
* The parameter which indicates if the activity has finished drawing.
* @hide
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 9ed41553a4b4..3795fc8594ae 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -102,6 +102,7 @@ cc_library_shared_for_libandroid_runtime {
static_libs: [
"libnativehelper_lazy",
"libziparchive_for_incfs",
+ "libguiflags",
],
export_include_dirs: [
diff --git a/core/jni/android_graphics_SurfaceTexture.cpp b/core/jni/android_graphics_SurfaceTexture.cpp
index 21487abadbae..50832a5c256a 100644
--- a/core/jni/android_graphics_SurfaceTexture.cpp
+++ b/core/jni/android_graphics_SurfaceTexture.cpp
@@ -17,27 +17,24 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceTexture"
-#include <stdio.h>
-
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
-
+#include <com_android_graphics_libgui_flags.h>
+#include <cutils/atomic.h>
#include <gui/BufferQueue.h>
#include <gui/Surface.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <stdio.h>
#include <surfacetexture/SurfaceTexture.h>
#include <surfacetexture/surface_texture_platform.h>
-
-#include "core_jni_helpers.h"
-
-#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/misc.h>
+#include "core_jni_helpers.h"
#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
// ----------------------------------------------------------------------------
@@ -55,6 +52,7 @@ struct fields_t {
jfieldID producer;
jfieldID frameAvailableListener;
jmethodID postEvent;
+ jmethodID postOnSetFrameRateEvent;
};
static fields_t fields;
@@ -139,61 +137,81 @@ bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) {
// ----------------------------------------------------------------------------
-class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener
-{
+class JNISurfaceTextureContextCommon {
public:
- JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
- virtual ~JNISurfaceTextureContext();
- virtual void onFrameAvailable(const BufferItem& item);
+ JNISurfaceTextureContextCommon(JNIEnv* env, jobject weakThiz, jclass clazz)
+ : mWeakThiz(env->NewGlobalRef(weakThiz)), mClazz((jclass)env->NewGlobalRef(clazz)) {}
+
+ virtual ~JNISurfaceTextureContextCommon() {
+ JNIEnv* env = getJNIEnv();
+ if (env != NULL) {
+ env->DeleteGlobalRef(mWeakThiz);
+ env->DeleteGlobalRef(mClazz);
+ } else {
+ ALOGW("leaking JNI object references");
+ }
+ }
-private:
- static JNIEnv* getJNIEnv();
+ void onFrameAvailable(const BufferItem& item) {
+ JNIEnv* env = getJNIEnv();
+ if (env != NULL) {
+ env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+ } else {
+ ALOGW("onFrameAvailable event will not posted");
+ }
+ }
+
+protected:
+ static JNIEnv* getJNIEnv() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL};
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->AttachCurrentThreadAsDaemon(&env, (void*)&args);
+ if (result != JNI_OK) {
+ ALOGE("thread attach failed: %#x", result);
+ return NULL;
+ }
+ }
+ return env;
+ }
jobject mWeakThiz;
jclass mClazz;
};
-JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
- jobject weakThiz, jclass clazz) :
- mWeakThiz(env->NewGlobalRef(weakThiz)),
- mClazz((jclass)env->NewGlobalRef(clazz))
-{}
-
-JNIEnv* JNISurfaceTextureContext::getJNIEnv() {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- JavaVMAttachArgs args = {
- JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL };
- JavaVM* vm = AndroidRuntime::getJavaVM();
- int result = vm->AttachCurrentThreadAsDaemon(&env, (void*)&args);
- if (result != JNI_OK) {
- ALOGE("thread attach failed: %#x", result);
- return NULL;
- }
+class JNISurfaceTextureContextFrameAvailableListener
+ : public JNISurfaceTextureContextCommon,
+ public SurfaceTexture::FrameAvailableListener {
+public:
+ JNISurfaceTextureContextFrameAvailableListener(JNIEnv* env, jobject weakThiz, jclass clazz)
+ : JNISurfaceTextureContextCommon(env, weakThiz, clazz) {}
+ void onFrameAvailable(const BufferItem& item) override {
+ JNISurfaceTextureContextCommon::onFrameAvailable(item);
}
- return env;
-}
+};
-JNISurfaceTextureContext::~JNISurfaceTextureContext()
-{
- JNIEnv* env = getJNIEnv();
- if (env != NULL) {
- env->DeleteGlobalRef(mWeakThiz);
- env->DeleteGlobalRef(mClazz);
- } else {
- ALOGW("leaking JNI object references");
+class JNISurfaceTextureContextListener : public JNISurfaceTextureContextCommon,
+ public SurfaceTexture::SurfaceTextureListener {
+public:
+ JNISurfaceTextureContextListener(JNIEnv* env, jobject weakThiz, jclass clazz)
+ : JNISurfaceTextureContextCommon(env, weakThiz, clazz) {}
+
+ void onFrameAvailable(const BufferItem& item) override {
+ JNISurfaceTextureContextCommon::onFrameAvailable(item);
}
-}
-void JNISurfaceTextureContext::onFrameAvailable(const BufferItem& /* item */)
-{
- JNIEnv* env = getJNIEnv();
- if (env != NULL) {
- env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
- } else {
- ALOGW("onFrameAvailable event will not posted");
+ void onSetFrameRate(float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) override {
+ JNIEnv* env = getJNIEnv();
+ if (env != NULL) {
+ env->CallStaticVoidMethod(mClazz, fields.postOnSetFrameRateEvent, mWeakThiz, frameRate,
+ compatibility, changeFrameRateStrategy);
+ } else {
+ ALOGW("onSetFrameRate event will not posted");
+ }
}
-}
+};
// ----------------------------------------------------------------------------
@@ -229,6 +247,13 @@ static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
if (fields.postEvent == NULL) {
ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
}
+
+ fields.postOnSetFrameRateEvent =
+ env->GetStaticMethodID(clazz, "postOnSetFrameRateEventFromNative",
+ "(Ljava/lang/ref/WeakReference;FII)V");
+ if (fields.postOnSetFrameRateEvent == NULL) {
+ ALOGE("can't find android/graphics/SurfaceTexture.postOnSetFrameRateEventFromNative");
+ }
}
static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
@@ -274,17 +299,27 @@ static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
return;
}
- sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
- clazz));
- surfaceTexture->setFrameAvailableListener(ctx);
- SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
+ if (com::android::graphics::libgui::flags::bq_setframerate()) {
+ sp<JNISurfaceTextureContextListener> ctx(
+ new JNISurfaceTextureContextListener(env, weakThiz, clazz));
+ surfaceTexture->setSurfaceTextureListener(ctx);
+ } else {
+ sp<JNISurfaceTextureContextFrameAvailableListener> ctx(
+ new JNISurfaceTextureContextFrameAvailableListener(env, weakThiz, clazz));
+ surfaceTexture->setFrameAvailableListener(ctx);
+ SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
+ }
}
static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
{
sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
- surfaceTexture->setFrameAvailableListener(0);
- SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
+ if (com::android::graphics::libgui::flags::bq_setframerate()) {
+ surfaceTexture->setSurfaceTextureListener(0);
+ } else {
+ surfaceTexture->setFrameAvailableListener(0);
+ SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
+ }
SurfaceTexture_setSurfaceTexture(env, thiz, 0);
SurfaceTexture_setProducer(env, thiz, 0);
}
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 48dc167438da..7f3e01432dd9 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -69,6 +69,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
@@ -95,16 +96,20 @@ import android.util.Pair;
import android.widget.RemoteViews;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.util.ContrastColorUtil;
import junit.framework.Assert;
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.List;
@@ -116,6 +121,9 @@ public class NotificationTest {
private Context mContext;
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
@@ -1777,6 +1785,42 @@ public class NotificationTest {
assertThat(recoveredExtender.getColor()).isEqualTo(1234);
}
+ @Test
+ @CoreCompatChangeRule.EnableCompatChanges({Notification.WEARABLE_EXTENDER_BACKGROUND_BLOCKED})
+ public void wearableBackgroundBlockEnabled_wearableBackgroundSet_valueRemainsNull() {
+ Notification.WearableExtender extender = new Notification.WearableExtender();
+ Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
+ extender.setBackground(bitmap);
+ Notification notif =
+ new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test_title")
+ .extend(extender)
+ .build();
+
+ Notification.WearableExtender result = new Notification.WearableExtender(notif);
+ Assert.assertNull(result.getBackground());
+ }
+
+ @Test
+ @CoreCompatChangeRule.DisableCompatChanges({Notification.WEARABLE_EXTENDER_BACKGROUND_BLOCKED})
+ public void wearableBackgroundBlockDisabled_wearableBackgroundSet_valueKeepsBitmap() {
+ Notification.WearableExtender extender = new Notification.WearableExtender();
+ Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
+ extender.setBackground(bitmap);
+ Notification notif =
+ new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test_title")
+ .extend(extender)
+ .build();
+
+ Notification.WearableExtender result = new Notification.WearableExtender(notif);
+ Bitmap resultBitmap = result.getBackground();
+ assertNotNull(resultBitmap);
+ Assert.assertEquals(bitmap, resultBitmap);
+ }
+
private void assertValid(Notification.Colors c) {
// Assert that all colors are populated
assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID);
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index dfe5012a2b4d..dd82fed03087 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -16,6 +16,7 @@
package android.graphics;
+import android.annotation.FloatRange;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
@@ -24,8 +25,10 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Trace;
import android.view.Surface;
import android.view.TextureView;
+import android.view.flags.Flags;
import java.lang.ref.WeakReference;
@@ -79,6 +82,7 @@ public class SurfaceTexture {
private final Looper mCreatorLooper;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private Handler mOnFrameAvailableHandler;
+ private Handler mOnSetFrameRateHandler;
/**
* These fields are used by native code, do not access or modify.
@@ -100,6 +104,21 @@ public class SurfaceTexture {
}
/**
+ * Callback interface for being notified that a producer set a frame rate
+ * @hide
+ */
+ public interface OnSetFrameRateListener {
+ /**
+ * Called when the producer sets a frame rate
+ * @hide
+ */
+ void onSetFrameRate(SurfaceTexture surfaceTexture,
+ @FloatRange(from = 0.0) float frameRate,
+ @Surface.FrameRateCompatibility int compatibility,
+ @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy);
+ }
+
+ /**
* Exception thrown when a SurfaceTexture couldn't be created or resized.
*
* @deprecated No longer thrown. {@link android.view.Surface.OutOfResourcesException}
@@ -224,6 +243,48 @@ public class SurfaceTexture {
}
}
+ private static class SetFrameRateArgs {
+ SetFrameRateArgs(@FloatRange(from = 0.0) float frameRate,
+ @Surface.FrameRateCompatibility int compatibility,
+ @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy) {
+ this.mFrameRate = frameRate;
+ this.mCompatibility = compatibility;
+ this.mChangeFrameRateStrategy = changeFrameRateStrategy;
+ }
+ final float mFrameRate;
+ final int mCompatibility;
+ final int mChangeFrameRateStrategy;
+ }
+
+ /**
+ * Register a callback to be invoked when the producer sets a frame rate using
+ * Surface.setFrameRate.
+ * @hide
+ */
+ public void setOnSetFrameRateListener(@Nullable final OnSetFrameRateListener listener,
+ @Nullable Handler handler) {
+ if (listener != null) {
+ Looper looper = handler != null ? handler.getLooper() :
+ mCreatorLooper != null ? mCreatorLooper : Looper.getMainLooper();
+ mOnSetFrameRateHandler = new Handler(looper, null, true /*async*/) {
+ @Override
+ public void handleMessage(Message msg) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSetFrameRateHandler");
+ try {
+ SetFrameRateArgs args = (SetFrameRateArgs) msg.obj;
+ listener.onSetFrameRate(SurfaceTexture.this,
+ args.mFrameRate, args.mCompatibility,
+ args.mChangeFrameRateStrategy);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+ };
+ } else {
+ mOnSetFrameRateHandler = null;
+ }
+ }
+
/**
* Set the default size of the image buffers. The image producer may override the buffer size,
* in which case the producer-set buffer size will be used, not the default size set by this
@@ -418,6 +479,35 @@ public class SurfaceTexture {
}
/**
+ * This method is invoked from native code only.
+ * @hide
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ private static void postOnSetFrameRateEventFromNative(WeakReference<SurfaceTexture> weakSelf,
+ @FloatRange(from = 0.0) float frameRate,
+ @Surface.FrameRateCompatibility int compatibility,
+ @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "postOnSetFrameRateEventFromNative");
+ try {
+ if (Flags.toolkitSetFrameRate()) {
+ SurfaceTexture st = weakSelf.get();
+ if (st != null) {
+ Handler handler = st.mOnSetFrameRateHandler;
+ if (handler != null) {
+ Message msg = new Message();
+ msg.obj = new SetFrameRateArgs(frameRate, compatibility,
+ changeFrameRateStrategy);
+ handler.sendMessage(msg);
+ }
+ }
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+
+ }
+
+ /**
* Returns {@code true} if the SurfaceTexture is single-buffered.
* @hide
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index 6ea6516a96f5..72fc8686f648 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -30,7 +30,7 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCR
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_ICON;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS;
import android.window.StartingWindowInfo;
@@ -52,7 +52,8 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
- final boolean allowIcon = (parameter & TYPE_PARAMETER_ALLOW_ICON) != 0;
+ final boolean isSolidColorSplashScreen =
+ (parameter & TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN) != 0;
final boolean legacySplashScreen =
((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
final boolean activityDrawn = (parameter & TYPE_PARAMETER_ACTIVITY_DRAWN) != 0;
@@ -66,13 +67,13 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
+ "processRunning=%b, "
+ "allowTaskSnapshot=%b, "
+ "activityCreated=%b, "
- + "allowIcon=%b, "
+ + "isSolidColorSplashScreen=%b, "
+ "legacySplashScreen=%b, "
+ "activityDrawn=%b, "
+ "windowless=%b, "
+ "topIsHome=%b",
newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated,
- allowIcon, legacySplashScreen, activityDrawn, windowlessSurface,
+ isSolidColorSplashScreen, legacySplashScreen, activityDrawn, windowlessSurface,
topIsHome);
if (windowlessSurface) {
@@ -80,7 +81,7 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
}
if (!topIsHome) {
if (!processRunning || newTask || (taskSwitch && !activityCreated)) {
- return getSplashscreenType(allowIcon, legacySplashScreen);
+ return getSplashscreenType(isSolidColorSplashScreen, legacySplashScreen);
}
}
@@ -94,18 +95,18 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
}
}
if (!activityDrawn && !topIsHome) {
- return getSplashscreenType(allowIcon, legacySplashScreen);
+ return getSplashscreenType(isSolidColorSplashScreen, legacySplashScreen);
}
}
return STARTING_WINDOW_TYPE_NONE;
}
- private static int getSplashscreenType(boolean allowIcon, boolean legacySplashScreen) {
- if (allowIcon) {
- return legacySplashScreen ? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ private static int getSplashscreenType(boolean solidColorSplashScreen,
+ boolean legacySplashScreen) {
+ return solidColorSplashScreen
+ ? STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN
+ : legacySplashScreen
+ ? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
: STARTING_WINDOW_TYPE_SPLASH_SCREEN;
- } else {
- return STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
- }
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 664fbb22b13b..f2c29f4a623e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -180,7 +180,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
+ val wct =
+ getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -198,7 +199,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
+ val wct =
+ getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -216,7 +218,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
+ val wct =
+ getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
@@ -230,7 +233,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
+ val wct =
+ getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(1)
wct.assertReorderAt(index = 0, homeTask)
}
@@ -246,7 +250,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
- val wct = getLatestWct(type = TRANSIT_OPEN, handlerClass = OneShotRemoteHandler::class.java)
+ val wct =
+ getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
assertThat(wct.hierarchyOps).hasSize(2)
// Expect order to be from bottom: home, task
wct.assertReorderAt(index = 0, homeTaskDefaultDisplay)
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 94ed06c806e5..f76ea063842f 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,6 +17,7 @@
#include "RenderThread.h"
#include <GrContextOptions.h>
+#include <include/gpu/ganesh/gl/GrGLDirectContext.h>
#include <android-base/properties.h>
#include <dlfcn.h>
#include <gl/GrGLInterface.h>
@@ -286,7 +287,7 @@ void RenderThread::requireGlContext() {
auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
auto size = glesVersion ? strlen(glesVersion) : -1;
cacheManager().configureContext(&options, glesVersion, size);
- sk_sp<GrDirectContext> grContext(GrDirectContext::MakeGL(std::move(glInterface), options));
+ sk_sp<GrDirectContext> grContext(GrDirectContexts::MakeGL(std::move(glInterface), options));
LOG_ALWAYS_FATAL_IF(!grContext.get());
setGrContext(grContext);
}
diff --git a/packages/SettingsLib/tests/integ/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml
index a95da3033eae..32048ca6344c 100644
--- a/packages/SettingsLib/tests/integ/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidManifest.xml
@@ -41,7 +41,7 @@
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.settingslib"
+ android:targetPackage="com.android.settingslib.tests.integ"
android:label="Tests for SettingsLib">
</instrumentation>
</manifest>
diff --git a/packages/SettingsLib/tests/integ/AndroidTest.xml b/packages/SettingsLib/tests/integ/AndroidTest.xml
index b5d09475269e..d0aee8822a72 100644
--- a/packages/SettingsLib/tests/integ/AndroidTest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidTest.xml
@@ -21,7 +21,7 @@
<option name="test-suite-tag" value="apct" />
<option name="test-tag" value="SettingsLibTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.settingslib" />
+ <option name="package" value="com.android.settingslib.tests.integ" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 625c1de0134d..b2287d876a48 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -163,7 +163,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
mCurrentUser = KeyguardUpdateMonitor.getCurrentUser();
showPrimarySecurityScreen(false);
- reinflateViewFlipper((l) -> {});
+ if (mCurrentSecurityMode != SecurityMode.SimPin
+ && mCurrentSecurityMode != SecurityMode.SimPuk) {
+ reinflateViewFlipper((l) -> {});
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 954129ef78c8..22bd20767e14 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -18,8 +18,8 @@ package com.android.systemui;
import static androidx.dynamicanimation.animation.DynamicAnimation.TRANSLATION_X;
import static androidx.dynamicanimation.animation.FloatPropertyCompat.createFloatPropertyCompat;
-
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
+import static com.android.systemui.flags.Flags.SWIPE_UNCLEARED_TRANSIENT_VIEW_FIX;
import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
import android.animation.Animator;
@@ -482,7 +482,14 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
boolean wasRemoved = false;
if (animView instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
- wasRemoved = row.isRemoved();
+ if (mFeatureFlags.isEnabled(SWIPE_UNCLEARED_TRANSIENT_VIEW_FIX)) {
+ // If the view is already removed from its parent and added as Transient,
+ // we need to clean the transient view upon animation end
+ wasRemoved = row.getTransientContainer() != null
+ || row.getParent() == null || row.isRemoved();
+ } else {
+ wasRemoved = row.isRemoved();
+ }
}
if (!mCancelled || wasRemoved) {
mCallback.onChildDismissed(animView);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index e8be40eaf3fe..9b74ac4afed4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -791,7 +791,8 @@ public class QuickSettingsController implements Dumpable {
/** update Qs height state */
public void setExpansionHeight(float height) {
// TODO(b/277909752): remove below log when bug is fixed
- if (mSplitShadeEnabled && mShadeExpandedFraction == 1.0f && height == 0) {
+ if (mSplitShadeEnabled && mShadeExpandedFraction == 1.0f && height == 0
+ && mBarState == SHADE) {
Log.wtf(TAG,
"setting QS height to 0 in split shade while shade is open(ing). "
+ "Value of mExpandImmediate = " + mExpandImmediate);
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index a3ccb168aa4e..b56b47f9c727 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -113,6 +113,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
private final boolean mCrossTaskNavigationAllowedByDefault;
@NonNull
private final ArraySet<ComponentName> mCrossTaskNavigationExemptions;
+ @Nullable
+ private final ComponentName mPermissionDialogComponent;
private final Object mGenericWindowPolicyControllerLock = new Object();
@Nullable private final ActivityBlockedCallback mActivityBlockedCallback;
private int mDisplayId = Display.INVALID_DISPLAY;
@@ -171,6 +173,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@NonNull Set<ComponentName> activityPolicyExemptions,
boolean crossTaskNavigationAllowedByDefault,
@NonNull Set<ComponentName> crossTaskNavigationExemptions,
+ @Nullable ComponentName permissionDialogComponent,
@Nullable ActivityListener activityListener,
@Nullable PipBlockedCallback pipBlockedCallback,
@Nullable ActivityBlockedCallback activityBlockedCallback,
@@ -185,6 +188,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mActivityPolicyExemptions = activityPolicyExemptions;
mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
mCrossTaskNavigationExemptions = new ArraySet<>(crossTaskNavigationExemptions);
+ mPermissionDialogComponent = permissionDialogComponent;
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -309,6 +313,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
return false;
}
+ // mPermissionDialogComponent being null means we don't want to block permission Dialogs
+ // based on FLAG_STREAM_PERMISSIONS
+ if (mPermissionDialogComponent != null
+ && mPermissionDialogComponent.equals(activityComponent)) {
+ return false;
+ }
+
return true;
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 203a152ccc73..a2e4d2cc6929 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -24,6 +24,7 @@ import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAUL
import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
+import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -204,6 +205,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@GuardedBy("mVirtualDeviceLock")
@NonNull
private final Set<ComponentName> mActivityPolicyExemptions;
+ private final ComponentName mPermissionDialogComponent;
private ActivityListener createListenerAdapter() {
return new ActivityListener() {
@@ -317,6 +319,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mParams.getVirtualSensorCallback(), mParams.getVirtualSensorConfigs());
mCameraAccessController = cameraAccessController;
mCameraAccessController.startObservingIfNeeded();
+ if (!Flags.streamPermissions()) {
+ mPermissionDialogComponent = getPermissionDialogComponent();
+ } else {
+ mPermissionDialogComponent = null;
+ }
try {
token.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -324,8 +331,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
mVirtualDeviceLog.logCreated(deviceId, mOwnerUid);
- mPublicVirtualDeviceObject = new VirtualDevice(
- this, getDeviceId(), getPersistentDeviceId(), mParams.getName());
+ if (Flags.vdmPublicApis()) {
+ mPublicVirtualDeviceObject = new VirtualDevice(
+ this, getDeviceId(), getPersistentDeviceId(), mParams.getName(),
+ getDisplayName());
+ } else {
+ mPublicVirtualDeviceObject = new VirtualDevice(
+ this, getDeviceId(), getPersistentDeviceId(), mParams.getName());
+ }
if (Flags.dynamicPolicy()) {
mActivityPolicyExemptions = new ArraySet<>(
@@ -951,6 +964,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
/*crossTaskNavigationExemptions=*/crossTaskNavigationAllowedByDefault
? mParams.getBlockedCrossTaskNavigations()
: mParams.getAllowedCrossTaskNavigations(),
+ mPermissionDialogComponent,
createListenerAdapter(),
this::onEnteringPipBlocked,
this::onActivityBlocked,
@@ -963,6 +977,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
return gwpc;
}
+ private ComponentName getPermissionDialogComponent() {
+ Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
+ PackageManager packageManager = mContext.getPackageManager();
+ intent.setPackage(packageManager.getPermissionControllerPackageName());
+ return intent.resolveActivity(packageManager);
+ }
+
int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
@NonNull IVirtualDisplayCallback callback, String packageName) {
GenericWindowPolicyController gwpc;
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index 881cbe806c66..d69737aef98f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -102,7 +102,8 @@ public class PackageManagerException extends Exception {
INTERNAL_ERROR_STATIC_SHARED_LIB_PROTECTED_BROADCAST,
INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS,
INTERNAL_ERROR_APEX_NOT_DIRECTORY,
- INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE
+ INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE,
+ INTERNAL_ERROR_MISSING_USER
})
@Retention(RetentionPolicy.SOURCE)
public @interface InternalErrorCode {}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 3d61f3eea393..b055a3ffd688 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -402,7 +402,7 @@ final class RemovePackageHelper {
mBroadcastHelper.sendPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
}
} else if (!deletedPs.isSystem() && outInfo != null && !outInfo.mIsUpdate
- && outInfo.mRemovedUsers != null) {
+ && outInfo.mRemovedUsers != null && !outInfo.mIsExternal) {
// For non-system uninstalls with DELETE_KEEP_DATA, set the installed state to false
// for affected users. This does not apply to app updates where the old apk is replaced
// but the old data remains.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a0c78702fec5..16847243b6e1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -580,7 +580,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
IBinder mRequestedLaunchingTaskFragmentToken;
// Tracking splash screen status from previous activity
- boolean mAllowIconSplashScreen = true;
+ boolean mSplashScreenStyleSolidColor = false;
boolean mPauseSchedulePendingForPip = false;
@@ -2408,7 +2408,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@VisibleForTesting
boolean addStartingWindow(String pkg, int resolvedTheme, ActivityRecord from, boolean newTask,
boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot,
- boolean activityCreated, boolean allowIcon, boolean activityAllDrawn) {
+ boolean activityCreated, boolean isSimple,
+ boolean activityAllDrawn) {
// If the display is frozen, we won't do anything until the actual window is
// displayed so there is no reason to put in the starting window.
if (!okToDisplay()) {
@@ -2443,8 +2444,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int typeParameter = StartingSurfaceController
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
- allowTaskSnapshot, activityCreated, allowIcon, useLegacy,
- activityAllDrawn, type, packageName, mUserId);
+ allowTaskSnapshot, activityCreated, isSimple, useLegacy, activityAllDrawn,
+ type, packageName, mUserId);
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
if (isActivityTypeHome()) {
@@ -6746,7 +6747,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void onFirstWindowDrawn(WindowState win) {
firstWindowDrawn = true;
// stop tracking
- mAllowIconSplashScreen = false;
+ mSplashScreenStyleSolidColor = true;
if (mStartingWindow != null) {
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
@@ -6795,7 +6796,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void onStartingWindowDrawn() {
boolean wasTaskVisible = false;
if (task != null) {
- mAllowIconSplashScreen = false;
+ mSplashScreenStyleSolidColor = true;
wasTaskVisible = !setTaskHasBeenVisible();
}
@@ -7320,32 +7321,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
- * Checks whether an icon splash screen can be used in the starting window based on the
- * preference in the {@code options} and this activity's theme, giving higher priority to the
- * {@code options}'s preference.
- *
- * When no preference is specified, a default behaviour is defined:
- * - if the activity is started from the home or shell app, an icon can be used
- * - if the activity is started from SystemUI, an icon should not be used
- * - if there is a launching activity, use its preference
- * - if none of the above is met, only use an icon when the activity is started for the first
- * time from a System app
- *
- * The returned value is sent to WmShell, which will make the final decision on what splash
- * screen type will be used.
- *
- * @return true if an icon can be used in the splash screen
- * false when an icon should not be used in the splash screen
+ * @return true if a solid color splash screen must be used
+ * false when an icon splash screen can be used, but the final decision for whether to
+ * use an icon or solid color splash screen will be made by WmShell.
*/
- private boolean canUseIconSplashScreen(ActivityRecord sourceRecord,
+ private boolean shouldUseSolidColorSplashScreen(ActivityRecord sourceRecord,
boolean startActivity, ActivityOptions options, int resolvedTheme) {
if (sourceRecord == null && !startActivity) {
- // Shouldn't use an icon if this activity is not top activity. This could happen when
- // adding a splash screen window to the warm start activity which is re-create because
- // top is finishing.
+ // Use simple style if this activity is not top activity. This could happen when adding
+ // a splash screen window to the warm start activity which is re-create because top is
+ // finishing.
final ActivityRecord above = task.getActivityAbove(this);
if (above != null) {
- return false;
+ return true;
}
}
@@ -7353,33 +7341,32 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int optionsStyle = options != null ? options.getSplashScreenStyle() :
SplashScreen.SPLASH_SCREEN_STYLE_UNDEFINED;
if (optionsStyle == SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR) {
- return false;
+ return true;
} else if (optionsStyle == SplashScreen.SPLASH_SCREEN_STYLE_ICON
|| isIconStylePreferred(resolvedTheme)) {
- return true;
+ return false;
}
// Choose the default behavior when neither the ActivityRecord nor the activity theme have
// specified a splash screen style.
if (mLaunchSourceType == LAUNCH_SOURCE_TYPE_HOME || launchedFromUid == Process.SHELL_UID) {
- return true;
- } else if (mLaunchSourceType == LAUNCH_SOURCE_TYPE_SYSTEMUI) {
return false;
+ } else if (mLaunchSourceType == LAUNCH_SOURCE_TYPE_SYSTEMUI) {
+ return true;
} else {
- // Need to check sourceRecord in case this activity is launched from a service or a
- // trampoline activity.
+ // Need to check sourceRecord in case this activity is launched from a service.
if (sourceRecord == null) {
sourceRecord = searchCandidateLaunchingActivity();
}
if (sourceRecord != null) {
- return sourceRecord.mAllowIconSplashScreen;
+ return sourceRecord.mSplashScreenStyleSolidColor;
}
// Use an icon if the activity was launched from System for the first start.
- // Otherwise, can't use an icon splash screen.
- return mLaunchSourceType == LAUNCH_SOURCE_TYPE_SYSTEM && startActivity;
+ // Otherwise, must use solid color splash screen.
+ return mLaunchSourceType != LAUNCH_SOURCE_TYPE_SYSTEM || !startActivity;
}
}
@@ -7443,7 +7430,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int resolvedTheme = evaluateStartingWindowTheme(prev, packageName, theme,
splashScreenTheme);
- mAllowIconSplashScreen = canUseIconSplashScreen(sourceRecord, startActivity,
+ mSplashScreenStyleSolidColor = shouldUseSolidColorSplashScreen(sourceRecord, startActivity,
startOptions, resolvedTheme);
final boolean activityCreated =
@@ -7455,7 +7442,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final boolean scheduled = addStartingWindow(packageName, resolvedTheme,
prev, newTask || newSingleActivity, taskSwitch, processRunning,
- allowTaskSnapshot(), activityCreated, mAllowIconSplashScreen, allDrawn);
+ allowTaskSnapshot(), activityCreated, mSplashScreenStyleSolidColor, allDrawn);
if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) {
Slog.d(TAG, "Scheduled starting window for " + this);
}
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index a0517bebca6d..a55c232990cf 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -19,12 +19,12 @@ package com.android.server.wm;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_ICON;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SNAPSHOT;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
@@ -102,7 +102,7 @@ public class StartingSurfaceController {
static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
- boolean allowIcon, boolean useLegacy, boolean activityDrawn, int startingWindowType,
+ boolean isSolidColor, boolean useLegacy, boolean activityDrawn, int startingWindowType,
String packageName, int userId) {
int parameter = 0;
if (newTask) {
@@ -120,8 +120,8 @@ public class StartingSurfaceController {
if (activityCreated || startingWindowType == STARTING_WINDOW_TYPE_SNAPSHOT) {
parameter |= TYPE_PARAMETER_ACTIVITY_CREATED;
}
- if (allowIcon) {
- parameter |= TYPE_PARAMETER_ALLOW_ICON;
+ if (isSolidColor) {
+ parameter |= TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;
}
if (useLegacy) {
parameter |= TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 41af9e31dbdd..1e6306cb4071 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -57,6 +57,7 @@ import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
+import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.IVirtualSensorCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensorCallback;
@@ -100,6 +101,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.WorkSource;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
@@ -211,6 +213,9 @@ public class VirtualDeviceManagerServiceTest {
private static final String TEST_SITE = "http://test";
@Rule
+ public SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Rule
public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
Manifest.permission.CREATE_VIRTUAL_DEVICE);
@@ -328,6 +333,11 @@ public class VirtualDeviceManagerServiceTest {
LocalServices.removeServiceForTest(DisplayManagerInternal.class);
LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+ mSetFlagsRule.disableFlags(Flags.FLAG_VDM_PUBLIC_APIS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_DYNAMIC_POLICY);
+ mSetFlagsRule.disableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_VDM_CUSTOM_HOME);
+
doReturn(true).when(mInputManagerInternalMock).setVirtualMousePointerDisplayId(anyInt());
doNothing().when(mInputManagerInternalMock).setPointerAcceleration(anyFloat(), anyInt());
doNothing().when(mInputManagerInternalMock).setPointerIconVisible(anyBoolean(), anyInt());
@@ -1450,6 +1460,50 @@ public class VirtualDeviceManagerServiceTest {
}
@Test
+ public void openPermissionControllerOnVirtualDisplay_displayOnRemoteDevices_startsWhenFlagIsEnabled() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
+ DISPLAY_ID_1);
+ doNothing().when(mContext).startActivityAsUser(any(), any(), any());
+
+ ActivityInfo activityInfo = getActivityInfo(
+ PERMISSION_CONTROLLER_PACKAGE_NAME,
+ PERMISSION_CONTROLLER_PACKAGE_NAME,
+ /* displayOnRemoveDevices */ true,
+ /* targetDisplayCategory */ null);
+ Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+
+ verify(mContext, never()).startActivityAsUser(argThat(intent ->
+ intent.filterEquals(blockedAppIntent)), any(), any());
+ }
+
+ @Test
+ public void openPermissionControllerOnVirtualDisplay_dontDisplayOnRemoteDevices_startsWhenFlagIsEnabled() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
+ DISPLAY_ID_1);
+ doNothing().when(mContext).startActivityAsUser(any(), any(), any());
+
+ ActivityInfo activityInfo = getActivityInfo(
+ PERMISSION_CONTROLLER_PACKAGE_NAME,
+ PERMISSION_CONTROLLER_PACKAGE_NAME,
+ /* displayOnRemoveDevices */ false,
+ /* targetDisplayCategory */ null);
+ Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
+
+ verify(mContext).startActivityAsUser(argThat(intent ->
+ intent.filterEquals(blockedAppIntent)), any(), any());
+ }
+
+ @Test
public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index c65452aa2fa1..90d9452fb9c3 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -49,6 +49,7 @@ public class VirtualDeviceTest {
private static final int VIRTUAL_DEVICE_ID = 42;
private static final String PERSISTENT_ID = "persistentId";
private static final String DEVICE_NAME = "VirtualDeviceName";
+ private static final String DISPLAY_NAME = "DisplayName";
@Mock
private IVirtualDevice mVirtualDevice;
@@ -87,7 +88,8 @@ public class VirtualDeviceTest {
@Test
public void parcelable_shouldRecreateSuccessfully() {
VirtualDevice originalDevice =
- new VirtualDevice(mVirtualDevice, VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME);
+ new VirtualDevice(mVirtualDevice, VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME,
+ DISPLAY_NAME);
Parcel parcel = Parcel.obtain();
originalDevice.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
@@ -96,6 +98,7 @@ public class VirtualDeviceTest {
assertThat(device.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
assertThat(device.getPersistentDeviceId()).isEqualTo(PERSISTENT_ID);
assertThat(device.getName()).isEqualTo(DEVICE_NAME);
+ assertThat(device.getDisplayName().toString()).isEqualTo(DISPLAY_NAME);
}
@RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 1c48b8aa79f9..ef5270e8f003 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -82,6 +82,7 @@ public class VirtualAudioControllerTest {
/* activityPolicyExemptions= */ new ArraySet<>(),
/* crossTaskNavigationAllowedByDefault= */ true,
/* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent */ null,
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index f65cb93258bc..40ac7b1ccdca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2855,14 +2855,14 @@ public class ActivityRecordTests extends WindowTestsBase {
.setTask(sourceRecord.getTask()).build();
secondRecord.showStartingWindow(null /* prev */, true /* newTask */, false,
true /* startActivity */, sourceRecord);
- assertTrue(secondRecord.mAllowIconSplashScreen);
+ assertFalse(secondRecord.mSplashScreenStyleSolidColor);
secondRecord.onStartingWindowDrawn();
final ActivityRecord finalRecord = new ActivityBuilder(mAtm)
.setTask(sourceRecord.getTask()).build();
finalRecord.showStartingWindow(null /* prev */, true /* newTask */, false,
true /* startActivity */, secondRecord);
- assertFalse(finalRecord.mAllowIconSplashScreen);
+ assertTrue(finalRecord.mSplashScreenStyleSolidColor);
}
@Test