Merge "Remove duplicated screenshot capture." into main
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index 3534624..f80ccf7 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -7,6 +7,18 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+aconfig_declarations {
+ name: "bootanimation_flags",
+ package: "com.android.graphics.bootanimation.flags",
+ container: "system",
+ srcs: ["bootanimation_flags.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "libbootanimationflags",
+ aconfig_declarations: "bootanimation_flags",
+}
+
cc_defaults {
name: "bootanimation_defaults",
@@ -28,6 +40,10 @@
"liblog",
"libutils",
],
+
+ static_libs: [
+ "libbootanimationflags",
+ ],
}
// bootanimation executable
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 87c9fa4..14e2387 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_NDEBUG 0
+
#define LOG_TAG "BootAnimation"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -61,6 +62,8 @@
#include "BootAnimation.h"
+#include <com_android_graphics_bootanimation_flags.h>
+
#define ANIM_PATH_MAX 255
#define STR(x) #x
#define STRTO(x) STR(x)
@@ -448,19 +451,21 @@
auto token = SurfaceComposerClient::getPhysicalDisplayToken(
event.header.displayId);
- if (token != mBootAnimation->mDisplayToken) {
+ auto firstDisplay = mBootAnimation->mDisplays.front();
+ if (token != firstDisplay.displayToken) {
// ignore hotplug of a secondary display
continue;
}
DisplayMode displayMode;
const status_t error = SurfaceComposerClient::getActiveDisplayMode(
- mBootAnimation->mDisplayToken, &displayMode);
+ firstDisplay.displayToken, &displayMode);
if (error != NO_ERROR) {
SLOGE("Can't get active display mode.");
}
mBootAnimation->resizeSurface(displayMode.resolution.getWidth(),
- displayMode.resolution.getHeight());
+ displayMode.resolution.getHeight(),
+ firstDisplay);
}
}
} while (numEvents > 0);
@@ -506,91 +511,106 @@
status_t BootAnimation::readyToRun() {
ATRACE_CALL();
mAssets.addDefaultAssets();
+ return initDisplaysAndSurfaces();
+}
- const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
- if (ids.empty()) {
- SLOGE("Failed to get ID for any displays\n");
+status_t BootAnimation::initDisplaysAndSurfaces() {
+ std::vector<PhysicalDisplayId> displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
+ if (displayIds.empty()) {
+ SLOGE("Failed to get ID for any displays");
return NAME_NOT_FOUND;
}
- mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
- if (mDisplayToken == nullptr) {
- return NAME_NOT_FOUND;
+ // If Multi-Display isn't explicitly enabled, ignore all displays after the first one
+ if (!com::android::graphics::bootanimation::flags::multidisplay()) {
+ displayIds.erase(displayIds.begin() + 1, displayIds.end());
}
- DisplayMode displayMode;
- const status_t error =
- SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &displayMode);
- if (error != NO_ERROR) {
- return error;
+ for (const auto id : displayIds) {
+ if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) {
+ mDisplays.push_back({.displayToken = token});
+ } else {
+ SLOGE("Failed to get display token for a display");
+ SLOGE("Failed to get display token for display %" PRIu64, id.value);
+ return NAME_NOT_FOUND;
+ }
}
+ // Initialize EGL
+ mEgl = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(mEgl, nullptr, nullptr);
+ EGLConfig config = getEglConfig(mEgl);
+ EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ mEglContext = eglCreateContext(mEgl, config, nullptr, contextAttributes);
+
mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0);
mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0);
- ui::Size resolution = displayMode.resolution;
- resolution = limitSurfaceSize(resolution.width, resolution.height);
- // create the native surface
- sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
- resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565,
- ISurfaceComposerClient::eOpaque);
- SurfaceComposerClient::Transaction t;
- t.setDisplayLayerStack(mDisplayToken, ui::DEFAULT_LAYER_STACK);
- t.setLayerStack(control, ui::DEFAULT_LAYER_STACK);
+ for (size_t displayIdx = 0; displayIdx < mDisplays.size(); displayIdx++) {
+ auto& display = mDisplays[displayIdx];
+ DisplayMode displayMode;
+ const status_t error =
+ SurfaceComposerClient::getActiveDisplayMode(display.displayToken, &displayMode);
+ if (error != NO_ERROR) {
+ return error;
+ }
+ ui::Size resolution = displayMode.resolution;
+ // Clamp each surface to max size
+ resolution = limitSurfaceSize(resolution.width, resolution.height);
+ // Create the native surface
+ display.surfaceControl =
+ session()->createSurface(String8("BootAnimation"), resolution.width,
+ resolution.height, PIXEL_FORMAT_RGB_565,
+ ISurfaceComposerClient::eOpaque);
+ // Attach surface to layerstack, and associate layerstack with physical display
+ configureDisplayAndLayerStack(display, ui::LayerStack::fromValue(displayIdx));
+ display.surface = display.surfaceControl->getSurface();
+ display.eglSurface = eglCreateWindowSurface(mEgl, config, display.surface.get(), nullptr);
- t.setLayer(control, 0x40000000)
- .apply();
+ EGLint w, h;
+ eglQuerySurface(mEgl, display.eglSurface, EGL_WIDTH, &w);
+ eglQuerySurface(mEgl, display.eglSurface, EGL_HEIGHT, &h);
+ if (eglMakeCurrent(mEgl, display.eglSurface, display.eglSurface,
+ mEglContext) == EGL_FALSE) {
+ return NO_INIT;
+ }
+ display.initWidth = display.width = w;
+ display.initHeight = display.height = h;
+ mTargetInset = -1;
- sp<Surface> s = control->getSurface();
+ // Rotate the boot animation according to the value specified in the sysprop
+ // ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0,
+ // ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270.
+ // If the value isn't specified or is ORIENTATION_0, nothing will be changed.
+ // This is needed to support boot animation in orientations different from the natural
+ // device orientation. For example, on tablets that may want to keep natural orientation
+ // portrait for applications compatibility and to have the boot animation in landscape.
+ rotateAwayFromNaturalOrientationIfNeeded(display);
- // initialize opengl and egl
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(display, nullptr, nullptr);
- EGLConfig config = getEglConfig(display);
- EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
- // Initialize egl context with client version number 2.0.
- EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
- EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes);
- EGLint w, h;
- eglQuerySurface(display, surface, EGL_WIDTH, &w);
- eglQuerySurface(display, surface, EGL_HEIGHT, &h);
-
- if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
- return NO_INIT;
- }
-
- mDisplay = display;
- mContext = context;
- mSurface = surface;
- mInitWidth = mWidth = w;
- mInitHeight = mHeight = h;
- mFlingerSurfaceControl = control;
- mFlingerSurface = s;
- mTargetInset = -1;
-
- // Rotate the boot animation according to the value specified in the sysprop
- // ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0,
- // ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270.
- // If the value isn't specified or is ORIENTATION_0, nothing will be changed.
- // This is needed to support having boot animation in orientations different from the natural
- // device orientation. For example, on tablets that may want to keep natural orientation
- // portrait for applications compatibility and to have the boot animation in landscape.
- rotateAwayFromNaturalOrientationIfNeeded();
-
- projectSceneToWindow();
+ projectSceneToWindow(display);
+ } // end iteration over all display tokens
// Register a display event receiver
mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>();
status_t status = mDisplayEventReceiver->initCheck();
SLOGE_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver failed with status: %d",
- status);
+ status);
mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
- new DisplayEventCallback(this), nullptr);
+ new DisplayEventCallback(this), nullptr);
return NO_ERROR;
}
-void BootAnimation::rotateAwayFromNaturalOrientationIfNeeded() {
+void BootAnimation::configureDisplayAndLayerStack(const Display& display,
+ ui::LayerStack layerStack) {
+ SurfaceComposerClient::Transaction t;
+ t.setDisplayLayerStack(display.displayToken, layerStack);
+ t.setLayerStack(display.surfaceControl, layerStack)
+ .setLayer(display.surfaceControl, 0x40000000)
+ .apply();
+}
+
+void BootAnimation::rotateAwayFromNaturalOrientationIfNeeded(Display& display) {
ATRACE_CALL();
const auto orientation = parseOrientationProperty();
@@ -600,16 +620,16 @@
}
if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
- std::swap(mWidth, mHeight);
- std::swap(mInitWidth, mInitHeight);
- mFlingerSurfaceControl->updateDefaultBufferSize(mWidth, mHeight);
+ std::swap(display.width, display.height);
+ std::swap(display.initWidth, display.initHeight);
+ display.surfaceControl->updateDefaultBufferSize(display.width, display.height);
}
- Rect displayRect(0, 0, mWidth, mHeight);
- Rect layerStackRect(0, 0, mWidth, mHeight);
+ Rect displayRect(0, 0, display.width, display.height);
+ Rect layerStackRect(0, 0, display.width, display.height);
SurfaceComposerClient::Transaction t;
- t.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect);
+ t.setDisplayProjection(display.displayToken, orientation, layerStackRect, displayRect);
t.apply();
}
@@ -640,38 +660,37 @@
return ui::ROTATION_0;
}
-void BootAnimation::projectSceneToWindow() {
+void BootAnimation::projectSceneToWindow(const Display& display) {
ATRACE_CALL();
- glViewport(0, 0, mWidth, mHeight);
- glScissor(0, 0, mWidth, mHeight);
+ glViewport(0, 0, display.width, display.height);
+ glScissor(0, 0, display.width, display.height);
}
-void BootAnimation::resizeSurface(int newWidth, int newHeight) {
+void BootAnimation::resizeSurface(int newWidth, int newHeight, Display& display) {
ATRACE_CALL();
// We assume this function is called on the animation thread.
- if (newWidth == mWidth && newHeight == mHeight) {
+ if (newWidth == display.width && newHeight == display.height) {
return;
}
- SLOGV("Resizing the boot animation surface to %d %d", newWidth, newHeight);
- eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(mDisplay, mSurface);
+ eglMakeCurrent(mEgl, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(mEgl, display.eglSurface);
const auto limitedSize = limitSurfaceSize(newWidth, newHeight);
- mWidth = limitedSize.width;
- mHeight = limitedSize.height;
+ display.width = limitedSize.width;
+ display.height = limitedSize.height;
- mFlingerSurfaceControl->updateDefaultBufferSize(mWidth, mHeight);
- EGLConfig config = getEglConfig(mDisplay);
- EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr);
- if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) {
- SLOGE("Can't make the new surface current. Error %d", eglGetError());
+ display.surfaceControl->updateDefaultBufferSize(display.width, display.height);
+ EGLConfig config = getEglConfig(mEgl);
+ EGLSurface eglSurface = eglCreateWindowSurface(mEgl, config, display.surface.get(), nullptr);
+ if (eglMakeCurrent(mEgl, eglSurface, eglSurface, mEglContext) == EGL_FALSE) {
+ SLOGE("Can't make the new eglSurface current. Error %d", eglGetError());
return;
}
- projectSceneToWindow();
+ projectSceneToWindow(display);
- mSurface = surface;
+ display.eglSurface = eglSurface;
}
bool BootAnimation::preloadAnimation() {
@@ -801,24 +820,26 @@
// animation.
if (mZipFileName.empty()) {
ALOGD("No animation file");
- result = android();
+ result = android(mDisplays.front());
} else {
result = movie();
}
mCallbacks->shutdown();
- eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(mDisplay, mContext);
- eglDestroySurface(mDisplay, mSurface);
- mFlingerSurface.clear();
- mFlingerSurfaceControl.clear();
- eglTerminate(mDisplay);
+ eglMakeCurrent(mEgl, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(mEgl, mEglContext);
+ for (auto& display : mDisplays) {
+ eglDestroySurface(mEgl, display.eglSurface);
+ display.surface.clear();
+ display.surfaceControl.clear();
+ }
+ eglTerminate(mEgl);
eglReleaseThread();
IPCThreadState::self()->stopProcess();
return result;
}
-bool BootAnimation::android() {
+bool BootAnimation::android(const Display& display) {
ATRACE_CALL();
glActiveTexture(GL_TEXTURE0);
@@ -836,7 +857,7 @@
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
- eglSwapBuffers(mDisplay, mSurface);
+ eglSwapBuffers(mEgl, display.eglSurface);
// Blend state
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -844,11 +865,11 @@
const nsecs_t startTime = systemTime();
do {
processDisplayEvents();
- const GLint xc = (mWidth - mAndroid[0].w) / 2;
- const GLint yc = (mHeight - mAndroid[0].h) / 2;
+ const GLint xc = (display.width - mAndroid[0].w) / 2;
+ const GLint yc = (display.height - mAndroid[0].h) / 2;
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
- glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
- updateRect.height());
+ glScissor(updateRect.left, display.height - updateRect.bottom, updateRect.width(),
+ updateRect.height());
nsecs_t now = systemTime();
double time = now - startTime;
@@ -862,14 +883,14 @@
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
- drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
- drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
+ drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h, display);
+ drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h, display);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
- drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
+ drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h, display);
- EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
+ EGLBoolean res = eglSwapBuffers(mEgl, display.eglSurface);
if (res == EGL_FALSE)
break;
@@ -888,7 +909,7 @@
void BootAnimation::checkExit() {
ATRACE_CALL();
- // Allow surface flinger to gracefully request shutdown
+ // Allow SurfaceFlinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
property_get(EXIT_PROP_NAME, value, "0");
int exitnow = atoi(value);
@@ -1034,7 +1055,8 @@
return status;
}
-void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
+void BootAnimation::drawText(const char* str, const Font& font, bool bold,
+ int* x, int* y, const Display& display) {
ATRACE_CALL();
glEnable(GL_BLEND); // Allow us to draw on top of the animation
glBindTexture(GL_TEXTURE_2D, font.texture.name);
@@ -1045,14 +1067,14 @@
const int strWidth = font.char_width * len;
if (*x == TEXT_CENTER_VALUE) {
- *x = (mWidth - strWidth) / 2;
+ *x = (display.width - strWidth) / 2;
} else if (*x < 0) {
- *x = mWidth + *x - strWidth;
+ *x = display.width + *x - strWidth;
}
if (*y == TEXT_CENTER_VALUE) {
- *y = (mHeight - font.char_height) / 2;
+ *y = (display.height - font.char_height) / 2;
} else if (*y < 0) {
- *y = mHeight + *y - font.char_height;
+ *y = display.height + *y - font.char_height;
}
for (int i = 0; i < len; i++) {
@@ -1072,7 +1094,7 @@
float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2;
float u1 = u0 + 1.0f / FONT_NUM_COLS;
glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1);
- drawTexturedQuad(*x, *y, font.char_width, font.char_height);
+ drawTexturedQuad(*x, *y, font.char_width, font.char_height, display);
*x += font.char_width;
}
@@ -1082,7 +1104,8 @@
}
// We render 12 or 24 hour time.
-void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) {
+void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos,
+ const Display& display) {
ATRACE_CALL();
static constexpr char TIME_FORMAT_12[] = "%l:%M";
static constexpr char TIME_FORMAT_24[] = "%H:%M";
@@ -1105,10 +1128,11 @@
char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0];
int x = xPos;
int y = yPos;
- drawText(out, font, false, &x, &y);
+ drawText(out, font, false, &x, &y, display);
}
-void BootAnimation::drawProgress(int percent, const Font& font, const int xPos, const int yPos) {
+void BootAnimation::drawProgress(int percent, const Font& font, const int xPos, const int yPos,
+ const Display& display) {
ATRACE_CALL();
static constexpr int PERCENT_LENGTH = 5;
@@ -1118,7 +1142,7 @@
sprintf(percentBuff, "%d;", percent);
int x = xPos;
int y = yPos;
- drawText(percentBuff, font, false, &x, &y);
+ drawText(percentBuff, font, false, &x, &y, display);
}
bool BootAnimation::parseAnimationDesc(Animation& animation) {
@@ -1247,8 +1271,7 @@
bool BootAnimation::preloadZip(Animation& animation) {
ATRACE_CALL();
- // read all the data structures
- const size_t pcount = animation.parts.size();
+ const size_t numParts = animation.parts.size();
void *cookie = nullptr;
ZipFileRO* zip = animation.zip;
if (!zip->startIteration(&cookie)) {
@@ -1284,8 +1307,8 @@
continue;
}
- for (size_t j = 0; j < pcount; j++) {
- if (path.string() == animation.parts[j].path.c_str()) {
+ for (size_t partIdx = 0; partIdx < numParts; partIdx++) {
+ if (path.string() == animation.parts[partIdx].path.c_str()) {
uint16_t method;
// supports only stored png files
if (zip->getEntryInfo(entry, &method, nullptr, nullptr, nullptr, nullptr,
@@ -1293,7 +1316,7 @@
if (method == ZipFileRO::kCompressStored) {
FileMap* map = zip->createEntryFileMap(entry);
if (map) {
- Animation::Part& part(animation.parts.editItemAt(j));
+ Animation::Part& part(animation.parts.editItemAt(partIdx));
if (leaf == "audio.wav") {
// a part may have at most one audio file
part.audioData = (uint8_t *)map->getDataPtr();
@@ -1324,7 +1347,8 @@
// If there is trimData present, override the positioning defaults.
for (Animation::Part& part : animation.parts) {
const char* trimDataStr = part.trimData.c_str();
- for (size_t frameIdx = 0; frameIdx < part.frames.size(); frameIdx++) {
+ const size_t numFramesInPart = part.frames.size();
+ for (size_t frameIdxInPart = 0; frameIdxInPart < numFramesInPart; frameIdxInPart++) {
const char* endl = strstr(trimDataStr, "\n");
// No more trimData for this part.
if (endl == nullptr) {
@@ -1335,7 +1359,7 @@
trimDataStr = ++endl;
int width = 0, height = 0, x = 0, y = 0;
if (sscanf(lineStr, "%dx%d+%d+%d", &width, &height, &x, &y) == 4) {
- Animation::Frame& frame(part.frames.editItemAt(frameIdx));
+ Animation::Frame& frame(part.frames.editItemAt(frameIdxInPart));
frame.trimWidth = width;
frame.trimHeight = height;
frame.trimX = x;
@@ -1458,13 +1482,15 @@
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
}
-void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) {
+void BootAnimation::drawTexturedQuad(float xStart, float yStart,
+ float width, float height,
+ const Display& display) {
ATRACE_CALL();
// Map coordinates from screen space to world space.
- float x0 = mapLinear(xStart, 0, mWidth, -1, 1);
- float y0 = mapLinear(yStart, 0, mHeight, -1, 1);
- float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1);
- float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1);
+ float x0 = mapLinear(xStart, 0, display.width, -1, 1);
+ float y0 = mapLinear(yStart, 0, display.height, -1, 1);
+ float x1 = mapLinear(xStart + width, 0, display.width, -1, 1);
+ float y1 = mapLinear(yStart + height, 0, display.height, -1, 1);
// Update quad vertex positions.
quadPositions[0] = x0;
quadPositions[1] = y0;
@@ -1511,7 +1537,7 @@
bool BootAnimation::playAnimation(const Animation& animation) {
ATRACE_CALL();
- const size_t pcount = animation.parts.size();
+ const size_t numParts = animation.parts.size();
nsecs_t frameDuration = s2ns(1) / animation.fps;
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
@@ -1521,9 +1547,9 @@
int lastDisplayedProgress = 0;
int colorTransitionStart = animation.colorTransitionStart;
int colorTransitionEnd = animation.colorTransitionEnd;
- for (size_t i=0 ; i<pcount ; i++) {
- const Animation::Part& part(animation.parts[i]);
- const size_t fcount = part.frames.size();
+ for (size_t partIdx = 0; partIdx < numParts; partIdx++) {
+ const Animation::Part& part(animation.parts[partIdx]);
+ const size_t numFramesInPart = part.frames.size();
glBindTexture(GL_TEXTURE_2D, 0);
// Handle animation package
@@ -1535,7 +1561,9 @@
}
// process the part not only while the count allows but also if already fading
- for (int r=0 ; !part.count || r<part.count || fadedFramesCount > 0 ; r++) {
+ for (int frameIdx = 0;
+ !part.count || frameIdx < part.count || fadedFramesCount > 0;
+ frameIdx++) {
if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;
// It's possible that the sysprops were not loaded yet at this boot phase.
@@ -1550,12 +1578,12 @@
const int transitionLength = colorTransitionEnd - colorTransitionStart;
if (part.postDynamicColoring) {
colorTransitionStart = 0;
- colorTransitionEnd = fmin(transitionLength, fcount - 1);
+ colorTransitionEnd = fmin(transitionLength, numFramesInPart - 1);
}
}
}
- mCallbacks->playPart(i, part, r);
+ mCallbacks->playPart(partIdx, part, frameIdx);
glClearColor(
part.backgroundColor[0],
@@ -1569,11 +1597,10 @@
// For the last animation, if we have progress indicator from
// the system, display it.
- int currentProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);
- bool displayProgress = animation.progressEnabled &&
- (i == (pcount -1)) && currentProgress != 0;
+ const bool displayProgress = animation.progressEnabled && (partIdx == (numParts - 1)) &&
+ android::base::GetIntProperty(PROGRESS_PROP_NAME, 0) != 0;
- for (size_t j=0 ; j<fcount ; j++) {
+ for (size_t frameIdxInPart = 0; frameIdxInPart < numFramesInPart; frameIdxInPart++) {
if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;
// Color progress is
@@ -1584,21 +1611,15 @@
// - 1 for parts that come after.
float colorProgress = part.useDynamicColoring
? fmin(fmax(
- ((float)j - colorTransitionStart) /
+ (static_cast<float>(frameIdxInPart) - colorTransitionStart) /
fmax(colorTransitionEnd - colorTransitionStart, 1.0f), 0.0f), 1.0f)
: (part.postDynamicColoring ? 1 : 0);
-
processDisplayEvents();
- const double ratio_w = static_cast<double>(mWidth) / mInitWidth;
- const double ratio_h = static_cast<double>(mHeight) / mInitHeight;
- const int animationX = (mWidth - animation.width * ratio_w) / 2;
- const int animationY = (mHeight - animation.height * ratio_h) / 2;
-
- const Animation::Frame& frame(part.frames[j]);
+ const Animation::Frame& frame(part.frames[frameIdxInPart]);
nsecs_t lastFrame = systemTime();
- if (r > 0) {
+ if (frameIdx > 0) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
if (part.count != 1) {
@@ -1611,17 +1632,6 @@
initTexture(frame.map, &w, &h, false /* don't premultiply alpha */);
}
- const int trimWidth = frame.trimWidth * ratio_w;
- const int trimHeight = frame.trimHeight * ratio_h;
- const int trimX = frame.trimX * ratio_w;
- const int trimY = frame.trimY * ratio_h;
- const int xc = animationX + trimX;
- const int yc = animationY + trimY;
- glClear(GL_COLOR_BUFFER_BIT);
- // specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
- // which is equivalent to mHeight - (yc + frame.trimHeight)
- const int frameDrawY = mHeight - (yc + trimHeight);
-
float fade = 0;
// if the part hasn't been stopped yet then continue fading if necessary
if (exitPending() && part.hasFadingPhase()) {
@@ -1630,40 +1640,66 @@
fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading
}
}
- glUseProgram(mImageShader);
- glUniform1i(mImageTextureLocation, 0);
- glUniform1f(mImageFadeLocation, fade);
- if (animation.dynamicColoringEnabled) {
- glUniform1f(mImageColorProgressLocation, colorProgress);
- }
- glEnable(GL_BLEND);
- drawTexturedQuad(xc, frameDrawY, trimWidth, trimHeight);
- glDisable(GL_BLEND);
- if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
- drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
- }
+ // Draw the current frame's texture on every physical display that is enabled.
+ for (const auto& display : mDisplays) {
+ eglMakeCurrent(mEgl, display.eglSurface, display.eglSurface, mEglContext);
- if (displayProgress) {
- int newProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);
- // In case the new progress jumped suddenly, still show an
- // increment of 1.
- if (lastDisplayedProgress != 100) {
- // Artificially sleep 1/10th a second to slow down the animation.
- usleep(100000);
- if (lastDisplayedProgress < newProgress) {
- lastDisplayedProgress++;
- }
+ const double ratioW =
+ static_cast<double>(display.width) / display.initWidth;
+ const double ratioH =
+ static_cast<double>(display.height) / display.initHeight;
+ const int animationX = (display.width - animation.width * ratioW) / 2;
+ const int animationY = (display.height - animation.height * ratioH) / 2;
+
+ const int trimWidth = frame.trimWidth * ratioW;
+ const int trimHeight = frame.trimHeight * ratioH;
+ const int trimX = frame.trimX * ratioW;
+ const int trimY = frame.trimY * ratioH;
+ const int xc = animationX + trimX;
+ const int yc = animationY + trimY;
+ projectSceneToWindow(display);
+ handleViewport(frameDuration, display);
+ glClear(GL_COLOR_BUFFER_BIT);
+ // specify the y center as ceiling((height - frame.trimHeight) / 2)
+ // which is equivalent to height - (yc + frame.trimHeight)
+ const int frameDrawY = display.height - (yc + trimHeight);
+
+ glUseProgram(mImageShader);
+ glUniform1i(mImageTextureLocation, 0);
+ glUniform1f(mImageFadeLocation, fade);
+ if (animation.dynamicColoringEnabled) {
+ glUniform1f(mImageColorProgressLocation, colorProgress);
}
- // Put the progress percentage right below the animation.
- int posY = animation.height / 3;
- int posX = TEXT_CENTER_VALUE;
- drawProgress(lastDisplayedProgress, animation.progressFont, posX, posY);
+ glEnable(GL_BLEND);
+ drawTexturedQuad(xc, frameDrawY, trimWidth, trimHeight, display);
+ glDisable(GL_BLEND);
+
+ if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
+ drawClock(animation.clockFont, part.clockPosX, part.clockPosY, display);
+ }
+
+ if (displayProgress) {
+ int newProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);
+ // In case the new progress jumped suddenly, still show an
+ // increment of 1.
+ if (lastDisplayedProgress != 100) {
+ // Artificially sleep 1/10th a second to slow down the animation.
+ usleep(100000);
+ if (lastDisplayedProgress < newProgress) {
+ lastDisplayedProgress++;
+ }
+ }
+ // Put the progress percentage right below the animation.
+ int posY = animation.height / 3;
+ int posX = TEXT_CENTER_VALUE;
+ drawProgress(lastDisplayedProgress,
+ animation.progressFont, posX, posY, display);
+ }
+
+ eglSwapBuffers(mEgl, display.eglSurface);
}
- handleViewport(frameDuration);
-
- eglSwapBuffers(mDisplay, mSurface);
nsecs_t now = systemTime();
nsecs_t delay = frameDuration - (now - lastFrame);
@@ -1709,9 +1745,7 @@
// Free textures created for looping parts now that the animation is done.
for (const Animation::Part& part : animation.parts) {
if (part.count != 1) {
- const size_t fcount = part.frames.size();
- for (size_t j = 0; j < fcount; j++) {
- const Animation::Frame& frame(part.frames[j]);
+ for (const auto& frame : part.frames) {
glDeleteTextures(1, &frame.tid);
}
}
@@ -1730,16 +1764,17 @@
mLooper->pollOnce(0);
}
-void BootAnimation::handleViewport(nsecs_t timestep) {
+void BootAnimation::handleViewport(nsecs_t timestep, const Display& display) {
ATRACE_CALL();
- if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) {
+ if (mShuttingDown || !display.surfaceControl || mTargetInset == 0) {
return;
}
if (mTargetInset < 0) {
// Poll the amount for the top display inset. This will return -1 until persistent properties
// have been loaded.
- mTargetInset = android::base::GetIntProperty("persist.sys.displayinset.top",
- -1 /* default */, -1 /* min */, mHeight / 2 /* max */);
+ mTargetInset =
+ android::base::GetIntProperty("persist.sys.displayinset.top", -1 /* default */,
+ -1 /* min */, display.height / 2 /* max */);
}
if (mTargetInset <= 0) {
return;
@@ -1751,19 +1786,27 @@
int interpolatedInset = (cosf((fraction + 1) * M_PI) / 2.0f + 0.5f) * mTargetInset;
SurfaceComposerClient::Transaction()
- .setCrop(mFlingerSurfaceControl, Rect(0, interpolatedInset, mWidth, mHeight))
+ .setCrop(display.surfaceControl,
+ Rect(0, interpolatedInset, display.width, display.height))
.apply();
} else {
// At the end of the animation, we switch to the viewport that DisplayManager will apply
// later. This changes the coordinate system, and means we must move the surface up by
// the inset amount.
- Rect layerStackRect(0, 0, mWidth, mHeight - mTargetInset);
- Rect displayRect(0, mTargetInset, mWidth, mHeight);
-
+ Rect layerStackRect(0, 0,
+ display.width,
+ display.height - mTargetInset);
+ Rect displayRect(0, mTargetInset,
+ display.width,
+ display.height);
SurfaceComposerClient::Transaction t;
- t.setPosition(mFlingerSurfaceControl, 0, -mTargetInset)
- .setCrop(mFlingerSurfaceControl, Rect(0, mTargetInset, mWidth, mHeight));
- t.setDisplayProjection(mDisplayToken, ui::ROTATION_0, layerStackRect, displayRect);
+ t.setPosition(display.surfaceControl, 0, -mTargetInset)
+ .setCrop(display.surfaceControl,
+ Rect(0, mTargetInset,
+ display.width,
+ display.height));
+ t.setDisplayProjection(display.displayToken,
+ ui::ROTATION_0, layerStackRect, displayRect);
t.apply();
mTargetInset = mCurrentInset = 0;
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 8683b71..0a05746 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -31,6 +31,7 @@
#include <binder/IBinder.h>
#include <ui/Rotation.h>
+#include <ui/LayerStack.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
@@ -119,6 +120,18 @@
float endColors[4][3]; // End colors of dynamic color transition.
};
+ // Collects all attributes that must be tracked per physical display.
+ struct Display {
+ int width;
+ int height;
+ int initWidth;
+ int initHeight;
+ EGLDisplay eglSurface;
+ sp<IBinder> displayToken;
+ sp<SurfaceControl> surfaceControl;
+ sp<Surface> surface;
+ };
+
// All callbacks will be called from this class's internal thread.
class Callbacks : public RefBase {
public:
@@ -181,14 +194,18 @@
bool premultiplyAlpha = true);
status_t initFont(Font* font, const char* fallback);
void initShaders();
- bool android();
+ bool android(const Display& display);
+ status_t initDisplaysAndSurfaces();
bool movie();
- void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
- void drawClock(const Font& font, const int xPos, const int yPos);
- void drawProgress(int percent, const Font& font, const int xPos, const int yPos);
+ void drawText(const char* str, const Font& font, bool bold,
+ int* x, int* y, const Display& display);
+ void drawClock(const Font& font, const int xPos, const int yPos, const Display& display);
+ void drawProgress(int percent, const Font& font,
+ const int xPos, const int yPos, const Display& display);
void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
const Animation::Part& part, int fadedFramesCount);
- void drawTexturedQuad(float xStart, float yStart, float width, float height);
+ void drawTexturedQuad(float xStart, float yStart,
+ float width, float height, const Display& display);
bool validClock(const Animation::Part& part);
Animation* loadAnimation(const String8&);
bool playAnimation(const Animation&);
@@ -200,36 +217,31 @@
bool preloadAnimation();
EGLConfig getEglConfig(const EGLDisplay&);
ui::Size limitSurfaceSize(int width, int height) const;
- void resizeSurface(int newWidth, int newHeight);
- void projectSceneToWindow();
- void rotateAwayFromNaturalOrientationIfNeeded();
+ void resizeSurface(int newWidth, int newHeight, Display& display);
+ void projectSceneToWindow(const Display& display);
+ void rotateAwayFromNaturalOrientationIfNeeded(Display& display);
ui::Rotation parseOrientationProperty();
+ void configureDisplayAndLayerStack(const Display& display, ui::LayerStack layerStack);
bool shouldStopPlayingPart(const Animation::Part& part, int fadedFramesCount,
int lastDisplayedProgress);
void checkExit();
- void handleViewport(nsecs_t timestep);
+ void handleViewport(nsecs_t timestep, const Display& display);
void initDynamicColors();
sp<SurfaceComposerClient> mSession;
AssetManager mAssets;
Texture mAndroid[2];
- int mWidth;
- int mHeight;
- int mInitWidth;
- int mInitHeight;
int mMaxWidth = 0;
int mMaxHeight = 0;
int mCurrentInset;
int mTargetInset;
bool mUseNpotTextures = false;
- EGLDisplay mDisplay;
- EGLDisplay mContext;
- EGLDisplay mSurface;
- sp<IBinder> mDisplayToken;
- sp<SurfaceControl> mFlingerSurfaceControl;
- sp<Surface> mFlingerSurface;
+ EGLDisplay mEgl;
+ EGLDisplay mEglContext;
+ // Per-Display Attributes (to support multi-display)
+ std::vector<Display> mDisplays;
bool mClockEnabled;
bool mTimeIsAccurate;
bool mTimeFormat12Hour;
diff --git a/cmds/bootanimation/bootanimation_flags.aconfig b/cmds/bootanimation/bootanimation_flags.aconfig
new file mode 100644
index 0000000..04837b9
--- /dev/null
+++ b/cmds/bootanimation/bootanimation_flags.aconfig
@@ -0,0 +1,12 @@
+package: "com.android.graphics.bootanimation.flags"
+container: "system"
+
+flag {
+ name: "multidisplay"
+ namespace: "bootanimation"
+ description: "Enable boot animation on multiple displays (e.g. foldables)"
+ bug: "335406617"
+ is_fixed_read_only: true
+}
+
+
diff --git a/core/api/current.txt b/core/api/current.txt
index 565254f..ec6a20c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -22601,6 +22601,7 @@
method public void sendEvent(int, int, @Nullable byte[]) throws android.media.MediaCasException;
method public void setEventListener(@Nullable android.media.MediaCas.EventListener, @Nullable android.os.Handler);
method public void setPrivateData(@NonNull byte[]) throws android.media.MediaCasException;
+ method @FlaggedApi("com.android.media.flags.update_client_profile_priority") public boolean updateResourcePriority(int, int);
field public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = 0; // 0x0
field public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = 1; // 0x1
field public static final int SCRAMBLING_MODE_AES128 = 9; // 0x9
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 8bb2857..5bc7de9 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -84,19 +84,25 @@
* @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes
* @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType
* @attr ref android.R.styleable#AccessibilityService_accessibilityFlags
+ * @attr ref android.R.styleable#AccessibilityService_animatedImageDrawable
+ * @attr ref android.R.styleable#AccessibilityService_canControlMagnification
+ * @attr ref android.R.styleable#AccessibilityService_canPerformGestures
* @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
+ * @attr ref android.R.styleable#AccessibilityService_canRequestFingerprintGestures
* @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
* @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent
- * @attr ref android.R.styleable#AccessibilityService_intro
+ * @attr ref android.R.styleable#AccessibilityService_canTakeScreenshot
* @attr ref android.R.styleable#AccessibilityService_description
- * @attr ref android.R.styleable#AccessibilityService_summary
+ * @attr ref android.R.styleable#AccessibilityService_htmlDescription
+ * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
+ * @attr ref android.R.styleable#AccessibilityService_intro
+ * @attr ref android.R.styleable#AccessibilityService_isAccessibilityTool
+ * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
* @attr ref android.R.styleable#AccessibilityService_notificationTimeout
* @attr ref android.R.styleable#AccessibilityService_packageNames
* @attr ref android.R.styleable#AccessibilityService_settingsActivity
+ * @attr ref android.R.styleable#AccessibilityService_summary
* @attr ref android.R.styleable#AccessibilityService_tileService
- * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
- * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
- * @attr ref android.R.styleable#AccessibilityService_canTakeScreenshot
* @see AccessibilityService
* @see android.view.accessibility.AccessibilityEvent
* @see android.view.accessibility.AccessibilityManager
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c1c96ea..014e4660 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -285,6 +285,14 @@
public static final String COMMAND_UNFREEZE = "android.wallpaper.unfreeze";
/**
+ * Command for {@link #sendWallpaperCommand}: in sendWallpaperCommand put extra to this command
+ * to give the bounds of space between the bottom of notifications and the top of shortcuts
+ * @hide
+ */
+ public static final String COMMAND_LOCKSCREEN_LAYOUT_CHANGED =
+ "android.wallpaper.lockscreen_layout_changed";
+
+ /**
* Extra passed back from setWallpaper() giving the new wallpaper's assigned ID.
* @hide
*/
diff --git a/core/java/android/app/wearable/flags.aconfig b/core/java/android/app/wearable/flags.aconfig
index b68bafe..534f461 100644
--- a/core/java/android/app/wearable/flags.aconfig
+++ b/core/java/android/app/wearable/flags.aconfig
@@ -38,4 +38,12 @@
namespace: "machine_learning"
description: "This flag enables the APIs related to hotword in WearableSensingManager and WearableSensingService."
bug: "310055381"
+}
+
+flag {
+ name: "enable_concurrent_wearable_connections"
+ is_exported: true
+ namespace: "machine_learning"
+ description: "This flag enables the APIs for providing multiple concurrent connections to the WearableSensingService."
+ bug: "358133158"
}
\ No newline at end of file
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index dfc591b..8ef62e3 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -62,7 +62,7 @@
* sleep (CPU off, display dark, device waiting for external input),
* but is not affected by clock scaling, idle, or other power saving
* mechanisms. This is the basis for most interval timing
- * such as {@link Thread#sleep(long) Thread.sleep(millls)},
+ * such as {@link Thread#sleep(long) Thread.sleep(millis)},
* {@link Object#wait(long) Object.wait(millis)}, and
* {@link System#nanoTime System.nanoTime()}. This clock is guaranteed
* to be monotonic, and is suitable for interval timing when the
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index bca5bcc..feeb339 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -206,17 +206,6 @@
}
flag {
- name: "apex_signature_permission_allowlist_enabled"
- is_fixed_read_only: true
- namespace: "permissions"
- description: "Enable reading signature permission allowlist from APEXes"
- bug: "308573169"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "check_op_validate_package"
namespace: "permissions"
description: "Validate package/uid match in checkOp similar to noteOp"
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 98d58d0..5ecf361 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3209,7 +3209,11 @@
return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_NOT_SET, null);
}
- private static boolean isCloudOrSimAccount(@DefaultAccountState int state) {
+ /**
+ *
+ * @hide
+ */
+ public static boolean isCloudOrSimAccount(@DefaultAccountState int state) {
return state == DEFAULT_ACCOUNT_STATE_CLOUD
|| state == DEFAULT_ACCOUNT_STATE_SIM;
}
@@ -3287,23 +3291,20 @@
Bundle response = nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, null);
- int defaultContactsAccountState = response.getInt(KEY_DEFAULT_ACCOUNT_STATE, -1);
- if (defaultContactsAccountState
- == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
+ int defaultAccountState = response.getInt(KEY_DEFAULT_ACCOUNT_STATE, -1);
+ if (DefaultAccountAndState.isCloudOrSimAccount(defaultAccountState)) {
String accountName = response.getString(Settings.ACCOUNT_NAME);
String accountType = response.getString(Settings.ACCOUNT_TYPE);
if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
throw new IllegalStateException(
"account name and type cannot be null or empty");
}
- return new DefaultAccountAndState(
- DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD,
+ return new DefaultAccountAndState(defaultAccountState,
new Account(accountName, accountType));
- } else if (defaultContactsAccountState
- == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL
- || defaultContactsAccountState
+ } else if (defaultAccountState == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL
+ || defaultAccountState
== DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_NOT_SET) {
- return new DefaultAccountAndState(defaultContactsAccountState, /*cloudAccount=*/
+ return new DefaultAccountAndState(defaultAccountState, /*account=*/
null);
} else {
throw new IllegalStateException("Invalid default account state");
@@ -3348,12 +3349,11 @@
Bundle extras = new Bundle();
extras.putInt(KEY_DEFAULT_ACCOUNT_STATE, defaultAccountAndState.getState());
- if (defaultAccountAndState.getState()
- == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
- Account cloudAccount = defaultAccountAndState.getAccount();
- assert cloudAccount != null;
- extras.putString(Settings.ACCOUNT_NAME, cloudAccount.name);
- extras.putString(Settings.ACCOUNT_TYPE, cloudAccount.type);
+ if (DefaultAccountAndState.isCloudOrSimAccount(defaultAccountAndState.getState())) {
+ Account account = defaultAccountAndState.getAccount();
+ assert account != null;
+ extras.putString(Settings.ACCOUNT_NAME, account.name);
+ extras.putString(Settings.ACCOUNT_TYPE, account.type);
}
nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, extras);
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 5c41516..67050e0 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -38,7 +38,7 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0ca442d..5afc7b2 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -125,7 +125,7 @@
import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme;
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index b9e9750..69cbb9b 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -11,6 +11,13 @@
}
flag {
+ name: "a11y_is_required_api"
+ namespace: "accessibility"
+ description: "Adds an API to indicate whether a form field (or similar element) is required."
+ bug: "362784403"
+}
+
+flag {
name: "a11y_overlay_callbacks"
is_exported: true
namespace: "accessibility"
@@ -210,3 +217,13 @@
description: "Feature flag for declaring system pinch zoom opt-out apis"
bug: "315089687"
}
+
+flag {
+ name: "warning_use_default_dialog_type"
+ namespace: "accessibility"
+ description: "Uses the default type for the A11yService warning dialog, instead of SYSTEM_ALERT_DIALOG"
+ bug: "336719951"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 06820cd..d7b5211 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -46,6 +46,7 @@
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView;
+import android.appwidget.flags.Flags;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -4119,6 +4120,71 @@
public void visitUris(@NonNull Consumer<Uri> visitor) {
mNestedViews.visitUris(visitor);
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ if (!Flags.remoteViewsProto()) return;
+ final long token = out.start(RemoteViewsProto.Action.VIEW_GROUP_ADD_ACTION);
+ out.write(RemoteViewsProto.ViewGroupAddAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ out.write(RemoteViewsProto.ViewGroupAddAction.INDEX, mIndex);
+ out.write(RemoteViewsProto.ViewGroupAddAction.STABLE_ID, mStableId);
+ long rvToken = out.start(RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS);
+ mNestedViews.writePreviewToProto(context, out);
+ out.end(rvToken);
+ out.end(token);
+ }
+ }
+
+ private PendingResources<Action> createViewGroupActionAddFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ final long token = in.start(RemoteViewsProto.Action.VIEW_GROUP_ADD_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.ViewGroupAddAction.VIEW_ID:
+ values.put(RemoteViewsProto.ViewGroupAddAction.VIEW_ID,
+ in.readString(RemoteViewsProto.ViewGroupAddAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS:
+ final long nvToken = in.start(RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS);
+ values.put(RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS,
+ createFromProto(in));
+ in.end(nvToken);
+ break;
+ case (int) RemoteViewsProto.ViewGroupAddAction.INDEX:
+ values.put(RemoteViewsProto.ViewGroupAddAction.INDEX,
+ in.readInt(RemoteViewsProto.ViewGroupAddAction.INDEX));
+ break;
+ case (int) RemoteViewsProto.ViewGroupAddAction.STABLE_ID:
+ values.put(RemoteViewsProto.ViewGroupAddAction.STABLE_ID,
+ in.readInt(RemoteViewsProto.ViewGroupAddAction.STABLE_ID));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values, new long[]{RemoteViewsProto.ViewGroupAddAction.VIEW_ID,
+ RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.ViewGroupAddAction.VIEW_ID);
+ return new ViewGroupActionAdd(viewId, ((PendingResources<RemoteViews>) values.get(
+ RemoteViewsProto.ViewGroupAddAction.NESTED_VIEWS)).create(context, resources,
+ rootData, depth),
+ (int) values.get(RemoteViewsProto.ViewGroupAddAction.INDEX, 0),
+ (int) values.get(RemoteViewsProto.ViewGroupAddAction.STABLE_ID, 0));
+ };
}
/**
@@ -4241,6 +4307,60 @@
public int mergeBehavior() {
return MERGE_APPEND;
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ final long token = out.start(RemoteViewsProto.Action.VIEW_GROUP_REMOVE_ACTION);
+ out.write(RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ if (mViewIdToKeep != REMOVE_ALL_VIEWS_ID) {
+ out.write(RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP,
+ appResources.getResourceName(mViewIdToKeep));
+ }
+ out.end(token);
+ }
+
+ public static PendingResources<Action> createFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ final long token = in.start(RemoteViewsProto.Action.VIEW_GROUP_REMOVE_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID:
+ values.put(RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID,
+ in.readString(RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP:
+ values.put(RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP,
+ in.readString(
+ RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values, new long[]{RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID);
+ int viewIdToKeep = (values.indexOfKey(
+ RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP) >= 0)
+ ? getAsIdentifier(resources, values,
+ RemoteViewsProto.ViewGroupRemoveAction.VIEW_ID_TO_KEEP)
+ : REMOVE_ALL_VIEWS_ID;
+ return new ViewGroupActionRemove(viewId, viewIdToKeep);
+ };
+ }
}
/**
@@ -4497,6 +4617,200 @@
visitIconUri(mI4, visitor);
}
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context,
+ Resources appResources) { // rebase
+ final long token = out.start(RemoteViewsProto.Action.TEXT_VIEW_DRAWABLE_ACTION);
+ out.write(RemoteViewsProto.TextViewDrawableAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ out.write(RemoteViewsProto.TextViewDrawableAction.IS_RELATIVE, mIsRelative);
+ if (mUseIcons) {
+ long iconsToken = out.start(RemoteViewsProto.TextViewDrawableAction.ICONS);
+ if (mI1 != null) {
+ writeIconToProto(out, appResources, mI1,
+ RemoteViewsProto.TextViewDrawableAction.Icons.ONE);
+ }
+ if (mI2 != null) {
+ writeIconToProto(out, appResources, mI2,
+ RemoteViewsProto.TextViewDrawableAction.Icons.TWO);
+ }
+ if (mI3 != null) {
+ writeIconToProto(out, appResources, mI3,
+ RemoteViewsProto.TextViewDrawableAction.Icons.THREE);
+ }
+ if (mI4 != null) {
+ writeIconToProto(out, appResources, mI4,
+ RemoteViewsProto.TextViewDrawableAction.Icons.FOUR);
+ }
+ out.end(iconsToken);
+ } else {
+ long resourcesToken = out.start(RemoteViewsProto.TextViewDrawableAction.RESOURCES);
+ if (mD1 != 0) {
+ out.write(RemoteViewsProto.TextViewDrawableAction.Resources.ONE,
+ appResources.getResourceName(mD1));
+ }
+ if (mD2 != 0) {
+ out.write(RemoteViewsProto.TextViewDrawableAction.Resources.TWO,
+ appResources.getResourceName(mD2));
+ }
+ if (mD3 != 0) {
+ out.write(RemoteViewsProto.TextViewDrawableAction.Resources.THREE,
+ appResources.getResourceName(mD3));
+ }
+ if (mD4 != 0) {
+ out.write(RemoteViewsProto.TextViewDrawableAction.Resources.FOUR,
+ appResources.getResourceName(mD4));
+ }
+ out.end(resourcesToken);
+ }
+ out.end(token);
+ }
+
+ public static PendingResources<Action> createFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ values.put(RemoteViewsProto.TextViewDrawableAction.ICONS,
+ new SparseArray<PendingResources<Icon>>());
+ values.put(RemoteViewsProto.TextViewDrawableAction.RESOURCES,
+ new SparseArray<String>());
+ final long token = in.start(RemoteViewsProto.Action.TEXT_VIEW_DRAWABLE_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.TextViewDrawableAction.VIEW_ID:
+ values.put(RemoteViewsProto.TextViewDrawableAction.VIEW_ID,
+ in.readString(RemoteViewsProto.TextViewDrawableAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.IS_RELATIVE:
+ values.put(RemoteViewsProto.TextViewDrawableAction.IS_RELATIVE,
+ in.readBoolean(
+ RemoteViewsProto.TextViewDrawableAction.IS_RELATIVE));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.RESOURCES:
+ final long resourcesToken = in.start(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.TextViewDrawableAction.Resources.ONE:
+ ((SparseArray<String>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES)).put(
+ 1, in.readString(
+ RemoteViewsProto
+ .TextViewDrawableAction.Resources.ONE));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Resources.TWO:
+ ((SparseArray<String>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES)).put(
+ 2, in.readString(
+ RemoteViewsProto
+ .TextViewDrawableAction.Resources.TWO));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Resources.THREE:
+ ((SparseArray<String>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES)).put(
+ 3, in.readString(
+ RemoteViewsProto
+ .TextViewDrawableAction
+ .Resources.THREE));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Resources.FOUR:
+ ((SparseArray<String>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES)).put(
+ 4, in.readString(
+ RemoteViewsProto
+ .TextViewDrawableAction
+ .Resources.FOUR));
+ break;
+ default:
+ Log.w(LOG_TAG,
+ "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(resourcesToken);
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.ICONS:
+ final long iconsToken = in.start(
+ RemoteViewsProto.TextViewDrawableAction.ICONS);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.TextViewDrawableAction.Icons.ONE:
+ ((SparseArray<PendingResources<Icon>>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.ICONS)).put(1,
+ createIconFromProto(in,
+ RemoteViewsProto
+ .TextViewDrawableAction.Icons.ONE));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Icons.TWO:
+ ((SparseArray<PendingResources<Icon>>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.ICONS)).put(2,
+ createIconFromProto(in,
+ RemoteViewsProto
+ .TextViewDrawableAction.Icons.TWO));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Icons.THREE:
+ ((SparseArray<PendingResources<Icon>>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.ICONS)).put(3,
+ createIconFromProto(in,
+ RemoteViewsProto
+ .TextViewDrawableAction.Icons.THREE));
+ break;
+ case (int) RemoteViewsProto.TextViewDrawableAction.Icons.FOUR:
+ ((SparseArray<PendingResources<Icon>>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.ICONS)).put(4,
+ createIconFromProto(in,
+ RemoteViewsProto
+ .TextViewDrawableAction.Icons.FOUR));
+ break;
+ default:
+ Log.w(LOG_TAG,
+ "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(iconsToken);
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values, new long[]{RemoteViewsProto.TextViewDrawableAction.VIEW_ID});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.TextViewDrawableAction.VIEW_ID);
+ SparseArray<PendingResources<Icon>> icons =
+ (SparseArray<PendingResources<Icon>>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.ICONS);
+ SparseArray<String> resArray = (SparseArray<String>) values.get(
+ RemoteViewsProto.TextViewDrawableAction.RESOURCES);
+ boolean isRelative = (boolean) values.get(
+ RemoteViewsProto.TextViewDrawableAction.IS_RELATIVE, false);
+ if (icons.size() > 0) {
+ return new TextViewDrawableAction(viewId, isRelative,
+ icons.get(1).create(context, resources, rootData, depth),
+ icons.get(2).create(context, resources, rootData, depth),
+ icons.get(3).create(context, resources, rootData, depth),
+ icons.get(4).create(context, resources, rootData, depth));
+ } else {
+ int first = resArray.contains(1) ? getAsIdentifier(resources, resArray, 1) : 0;
+ int second = resArray.contains(2) ? getAsIdentifier(resources, resArray, 2) : 0;
+ int third = resArray.contains(3) ? getAsIdentifier(resources, resArray, 3) : 0;
+ int fourth = resArray.contains(4) ? getAsIdentifier(resources, resArray, 4) : 0;
+ return new TextViewDrawableAction(viewId, isRelative, first, second, third,
+ fourth);
+ }
+ };
+ }
}
/**
@@ -4535,6 +4849,58 @@
public int getActionTag() {
return TEXT_VIEW_SIZE_ACTION_TAG;
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ final long token = out.start(RemoteViewsProto.Action.TEXT_VIEW_SIZE_ACTION);
+ out.write(RemoteViewsProto.TextViewSizeAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ out.write(RemoteViewsProto.TextViewSizeAction.UNITS, mUnits);
+ out.write(RemoteViewsProto.TextViewSizeAction.SIZE, mSize);
+ out.end(token);
+ }
+
+ public static PendingResources<Action> createFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ final long token = in.start(RemoteViewsProto.Action.TEXT_VIEW_SIZE_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.TextViewSizeAction.VIEW_ID:
+ values.put(RemoteViewsProto.TextViewSizeAction.VIEW_ID,
+ in.readString(RemoteViewsProto.TextViewSizeAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.TextViewSizeAction.UNITS:
+ values.put(RemoteViewsProto.TextViewSizeAction.UNITS,
+ in.readInt(RemoteViewsProto.TextViewSizeAction.UNITS));
+ break;
+ case (int) RemoteViewsProto.TextViewSizeAction.SIZE:
+ values.put(RemoteViewsProto.TextViewSizeAction.SIZE,
+ in.readFloat(RemoteViewsProto.TextViewSizeAction.SIZE));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values, new long[]{RemoteViewsProto.TextViewSizeAction.VIEW_ID});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.TextViewSizeAction.VIEW_ID);
+ return new TextViewSizeAction(viewId,
+ (int) values.get(RemoteViewsProto.TextViewSizeAction.UNITS, 0),
+ (float) values.get(RemoteViewsProto.TextViewSizeAction.SIZE, 0));
+ };
+ }
}
/**
@@ -4579,6 +4945,70 @@
public int getActionTag() {
return VIEW_PADDING_ACTION_TAG;
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ final long token = out.start(RemoteViewsProto.Action.VIEW_PADDING_ACTION);
+ out.write(RemoteViewsProto.ViewPaddingAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ out.write(RemoteViewsProto.ViewPaddingAction.LEFT, mLeft);
+ out.write(RemoteViewsProto.ViewPaddingAction.RIGHT, mRight);
+ out.write(RemoteViewsProto.ViewPaddingAction.TOP, mTop);
+ out.write(RemoteViewsProto.ViewPaddingAction.BOTTOM, mBottom);
+ out.end(token);
+ }
+
+ public static PendingResources<Action> createFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ final long token = in.start(RemoteViewsProto.Action.VIEW_PADDING_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.ViewPaddingAction.VIEW_ID:
+ values.put(RemoteViewsProto.ViewPaddingAction.VIEW_ID,
+ in.readString(RemoteViewsProto.ViewPaddingAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.ViewPaddingAction.LEFT:
+ values.put(RemoteViewsProto.ViewPaddingAction.LEFT,
+ in.readInt(RemoteViewsProto.ViewPaddingAction.LEFT));
+ break;
+ case (int) RemoteViewsProto.ViewPaddingAction.RIGHT:
+ values.put(RemoteViewsProto.ViewPaddingAction.RIGHT,
+ in.readInt(RemoteViewsProto.ViewPaddingAction.RIGHT));
+ break;
+ case (int) RemoteViewsProto.ViewPaddingAction.TOP:
+ values.put(RemoteViewsProto.ViewPaddingAction.TOP,
+ in.readInt(RemoteViewsProto.ViewPaddingAction.TOP));
+ break;
+ case (int) RemoteViewsProto.ViewPaddingAction.BOTTOM:
+ values.put(RemoteViewsProto.ViewPaddingAction.BOTTOM,
+ in.readInt(RemoteViewsProto.ViewPaddingAction.BOTTOM));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values, new long[]{RemoteViewsProto.ViewPaddingAction.VIEW_ID});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.ViewPaddingAction.VIEW_ID);
+ return new ViewPaddingAction(viewId,
+ (int) values.get(RemoteViewsProto.ViewPaddingAction.LEFT, 0),
+ (int) values.get(RemoteViewsProto.ViewPaddingAction.TOP, 0),
+ (int) values.get(RemoteViewsProto.ViewPaddingAction.RIGHT, 0),
+ (int) values.get(RemoteViewsProto.ViewPaddingAction.BOTTOM, 0));
+ };
+ }
}
/**
@@ -5241,6 +5671,69 @@
public int getActionTag() {
return SET_VIEW_OUTLINE_RADIUS_TAG;
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return true;
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ final long token = out.start(
+ RemoteViewsProto.Action.SET_VIEW_OUTLINE_PREFERRED_RADIUS_ACTION);
+ out.write(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VIEW_ID,
+ appResources.getResourceName(mViewId));
+ out.write(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE_TYPE, mValueType);
+ out.write(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE, mValue);
+ out.end(token);
+ }
+
+ public static PendingResources<Action> createFromProto(ProtoInputStream in)
+ throws Exception {
+ final LongSparseArray<Object> values = new LongSparseArray<>();
+
+ final long token = in.start(
+ RemoteViewsProto.Action.SET_VIEW_OUTLINE_PREFERRED_RADIUS_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VIEW_ID:
+ values.put(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VIEW_ID,
+ in.readString(
+ RemoteViewsProto
+ .SetViewOutlinePreferredRadiusAction.VIEW_ID));
+ break;
+ case (int) RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE_TYPE:
+ values.put(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE_TYPE,
+ in.readInt(
+ RemoteViewsProto
+ .SetViewOutlinePreferredRadiusAction.VALUE_TYPE));
+ break;
+ case (int) RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE:
+ values.put(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE,
+ in.readInt(
+ RemoteViewsProto
+ .SetViewOutlinePreferredRadiusAction.VALUE));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ checkContainsKeys(values,
+ new long[]{RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VIEW_ID,
+ RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE_TYPE});
+
+ return (context, resources, rootData, depth) -> {
+ int viewId = getAsIdentifier(resources, values,
+ RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VIEW_ID);
+ return new SetViewOutlinePreferredRadiusAction(viewId,
+ (int) values.get(RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE,
+ 0), (int) values.get(
+ RemoteViewsProto.SetViewOutlinePreferredRadiusAction.VALUE_TYPE));
+ };
+ }
}
/**
@@ -5324,6 +5817,46 @@
public int getActionTag() {
return SET_DRAW_INSTRUCTION_TAG;
}
+
+ @Override
+ public boolean canWriteToProto() {
+ return drawDataParcel();
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) {
+ if (!drawDataParcel()) return;
+ final long token = out.start(RemoteViewsProto.Action.SET_DRAW_INSTRUCTION_ACTION);
+ if (mInstructions != null) {
+ for (byte[] bytes : mInstructions.mInstructions) {
+ out.write(RemoteViewsProto.SetDrawInstructionAction.INSTRUCTIONS, bytes);
+ }
+ }
+ out.end(token);
+ }
+ }
+
+ @FlaggedApi(FLAG_DRAW_DATA_PARCEL)
+ private PendingResources<Action> createSetDrawInstructionActionFromProto(ProtoInputStream in)
+ throws Exception {
+ List<byte[]> instructions = new ArrayList<byte[]>();
+
+ final long token = in.start(RemoteViewsProto.Action.SET_DRAW_INSTRUCTION_ACTION);
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.SetDrawInstructionAction.INSTRUCTIONS:
+ instructions.add(
+ in.readBytes(RemoteViewsProto.SetDrawInstructionAction.INSTRUCTIONS));
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ in.end(token);
+
+ return (context, resources, rootData, depth) -> new SetDrawInstructionAction(
+ new DrawInstructions.Builder(instructions).build());
}
/**
@@ -9604,12 +10137,20 @@
}
if (ref.mMode == MODE_NORMAL) {
rv.setIdealSize(ref.mIdealSize);
+ boolean hasDrawInstructionAction = false;
for (PendingResources<Action> pendingAction : ref.mActions) {
Action action = pendingAction.create(appContext, appResources, rootData, depth);
if (action != null) {
+ if (action instanceof SetDrawInstructionAction) {
+ hasDrawInstructionAction = true;
+ }
rv.addAction(action);
}
}
+ if (rv.mHasDrawInstructions && !hasDrawInstructionAction) {
+ throw new InvalidProtoException(
+ "RemoteViews proto is missing DrawInstructions");
+ }
return rv;
} else if (ref.mMode == MODE_HAS_SIZED_REMOTEVIEWS) {
List<RemoteViews> sizedViews = new ArrayList<>();
@@ -9685,6 +10226,23 @@
return rv.createSetRemoteCollectionItemListAdapterActionFromProto(in);
case (int) RemoteViewsProto.Action.SET_RIPPLE_DRAWABLE_COLOR_ACTION:
return SetRippleDrawableColor.createFromProto(in);
+ case (int) RemoteViewsProto.Action.SET_VIEW_OUTLINE_PREFERRED_RADIUS_ACTION:
+ return SetViewOutlinePreferredRadiusAction.createFromProto(in);
+ case (int) RemoteViewsProto.Action.TEXT_VIEW_DRAWABLE_ACTION:
+ return TextViewDrawableAction.createFromProto(in);
+ case (int) RemoteViewsProto.Action.TEXT_VIEW_SIZE_ACTION:
+ return TextViewSizeAction.createFromProto(in);
+ case (int) RemoteViewsProto.Action.VIEW_GROUP_ADD_ACTION:
+ return rv.createViewGroupActionAddFromProto(in);
+ case (int) RemoteViewsProto.Action.VIEW_GROUP_REMOVE_ACTION:
+ return ViewGroupActionRemove.createFromProto(in);
+ case (int) RemoteViewsProto.Action.VIEW_PADDING_ACTION:
+ return ViewPaddingAction.createFromProto(in);
+ case (int) RemoteViewsProto.Action.SET_DRAW_INSTRUCTION_ACTION:
+ if (!drawDataParcel()) {
+ return null;
+ }
+ return rv.createSetDrawInstructionActionFromProto(in);
default:
throw new RuntimeException("Unhandled field while reading Action proto!\n"
+ ProtoUtils.currentFieldToString(in));
diff --git a/core/java/android/window/flags/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
similarity index 99%
rename from core/java/android/window/flags/DesktopModeFlags.java
rename to core/java/android/window/DesktopModeFlags.java
index 47af50da..6fb82af 100644
--- a/core/java/android/window/flags/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.window.flags;
+package android.window;
import android.annotation.Nullable;
import android.app.ActivityThread;
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceWarning.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceWarning.java
index 0f8ced2..3557633 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceWarning.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceWarning.java
@@ -29,6 +29,7 @@
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.accessibility.Flags;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
@@ -58,13 +59,15 @@
@NonNull View.OnClickListener uninstallListener) {
final AlertDialog ad = new AlertDialog.Builder(context)
.setView(createAccessibilityServiceWarningDialogContentView(
- context, info, allowListener, denyListener, uninstallListener))
+ context, info, allowListener, denyListener, uninstallListener))
.setCancelable(true)
.create();
Window window = ad.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.privateFlags |= SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
- params.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+ if (!Flags.warningUseDefaultDialogType()) {
+ params.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+ }
window.setAttributes(params);
return ad;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 6faea17..bd746d5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -38,8 +38,8 @@
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.flags.Flags.customizableWindowHeaders;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
diff --git a/core/proto/android/widget/remoteviews.proto b/core/proto/android/widget/remoteviews.proto
index f477d32..6a987a4 100644
--- a/core/proto/android/widget/remoteviews.proto
+++ b/core/proto/android/widget/remoteviews.proto
@@ -32,6 +32,8 @@
*
* Do not change the tag number or type of any fields in order to maintain compatibility with
* previous versions. If a field is deleted, use `reserved` to mark its tag number.
+ *
+ * Next tag: 17
*/
message RemoteViewsProto {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -290,6 +292,7 @@
}
}
+ // Next tag: 23
message Action {
oneof action {
AttributeReflectionAction attribute_reflection_action = 1;
@@ -307,6 +310,13 @@
SetRadioGroupCheckedAction set_radio_group_checked_action = 13;
SetRemoteCollectionItemListAdapterAction set_remote_collection_item_list_adapter_action = 14;
SetRippleDrawableColorAction set_ripple_drawable_color_action = 15;
+ SetViewOutlinePreferredRadiusAction set_view_outline_preferred_radius_action = 16;
+ TextViewDrawableAction text_view_drawable_action = 17;
+ TextViewSizeAction text_view_size_action = 18;
+ ViewGroupAddAction view_group_add_action = 19;
+ ViewGroupRemoveAction view_group_remove_action = 20;
+ ViewPaddingAction view_padding_action = 21;
+ SetDrawInstructionAction set_draw_instruction_action = 22;
}
}
@@ -428,6 +438,65 @@
optional string view_id = 1;
optional android.content.res.ColorStateListProto color_state_list = 2;
}
+
+ message SetViewOutlinePreferredRadiusAction {
+ optional string view_id = 1;
+ optional int32 value_type = 2;
+ optional int32 value = 3;
+ }
+
+ message TextViewDrawableAction {
+ optional string view_id = 1;
+ optional bool is_relative = 2;
+ oneof drawables {
+ Resources resources = 3;
+ Icons icons = 4;
+ };
+
+ message Resources {
+ optional string one = 1;
+ optional string two = 2;
+ optional string three = 3;
+ optional string four = 4;
+ }
+
+ message Icons {
+ optional Icon one = 1;
+ optional Icon two = 2;
+ optional Icon three = 3;
+ optional Icon four = 4;
+ }
+ }
+
+ message TextViewSizeAction {
+ optional string view_id = 1;
+ optional int32 units = 2;
+ optional float size = 3;
+ }
+
+ message ViewGroupAddAction {
+ optional string view_id = 1;
+ optional RemoteViewsProto nested_views = 2;
+ optional int32 index = 3;
+ optional int32 stableId = 4;
+ }
+
+ message ViewGroupRemoveAction {
+ optional string view_id = 1;
+ optional string view_id_to_keep = 2;
+ }
+
+ message ViewPaddingAction {
+ optional string view_id = 1;
+ optional int32 left = 2;
+ optional int32 right = 3;
+ optional int32 top = 4;
+ optional int32 bottom = 5;
+ }
+
+ message SetDrawInstructionAction {
+ repeated bytes instructions = 1;
+ }
}
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index b16c237..be8ecbe 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -470,6 +470,7 @@
@Test
@SmallTest
+ @DisabledOnRavenwood(blockedBy = ResourcesManager.class)
public void testResourceConfigurationAppliedWhenOverrideDoesNotExist() {
final int width = 240;
final int height = 360;
diff --git a/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java b/core/tests/coretests/src/android/window/DesktopModeFlagsTest.java
similarity index 88%
rename from core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java
rename to core/tests/coretests/src/android/window/DesktopModeFlagsTest.java
index a311d0d..b28e2b0 100644
--- a/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java
+++ b/core/tests/coretests/src/android/window/DesktopModeFlagsTest.java
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package android.window.flags;
+package android.window;
-import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE;
-import static android.window.flags.DesktopModeFlags.ToggleOverride.OVERRIDE_OFF;
-import static android.window.flags.DesktopModeFlags.ToggleOverride.OVERRIDE_ON;
-import static android.window.flags.DesktopModeFlags.ToggleOverride.OVERRIDE_UNSET;
-import static android.window.flags.DesktopModeFlags.ToggleOverride.fromSetting;
+import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE;
+import static android.window.DesktopModeFlags.ToggleOverride.OVERRIDE_OFF;
+import static android.window.DesktopModeFlags.ToggleOverride.OVERRIDE_ON;
+import static android.window.DesktopModeFlags.ToggleOverride.OVERRIDE_UNSET;
+import static android.window.DesktopModeFlags.ToggleOverride.fromSetting;
+import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS;
import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE;
import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TRANSITIONS;
@@ -40,6 +41,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -48,7 +50,7 @@
import java.lang.reflect.Field;
/**
- * Test class for {@link DesktopModeFlags}
+ * Test class for {@link android.window.DesktopModeFlags}
*
* Build/Install/Run:
* atest FrameworksCoreTests:DesktopModeFlagsTest
@@ -68,8 +70,12 @@
private static final int OVERRIDE_UNSET_SETTING = -1;
@Before
- public void setUp() throws Exception {
+ public void setUp() {
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ }
+
+ @After
+ public void tearDown() throws Exception {
resetCache();
}
@@ -203,7 +209,7 @@
setOverride(OVERRIDE_UNSET_SETTING);
// For unset overrides, follow flag
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -212,7 +218,7 @@
public void isTrue_dwFlagOn_overrideUnset_featureFlagOff_returnsFalse() {
setOverride(OVERRIDE_UNSET_SETTING);
// For unset overrides, follow flag
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -225,7 +231,7 @@
setOverride(OVERRIDE_ON_SETTING);
// When toggle override matches its default state (dw flag), don't override flags
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -235,7 +241,7 @@
setOverride(OVERRIDE_ON_SETTING);
// When toggle override matches its default state (dw flag), don't override flags
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -248,7 +254,7 @@
setOverride(OVERRIDE_OFF_SETTING);
// Follow override if they exist, and is not equal to default toggle state (dw flag)
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -258,7 +264,7 @@
setOverride(OVERRIDE_OFF_SETTING);
// Follow override if they exist, and is not equal to default toggle state (dw flag)
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -271,7 +277,7 @@
setOverride(OVERRIDE_UNSET_SETTING);
// For unset overrides, follow flag
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -284,7 +290,7 @@
setOverride(OVERRIDE_UNSET_SETTING);
// For unset overrides, follow flag
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -297,7 +303,7 @@
setOverride(OVERRIDE_ON_SETTING);
// Follow override if they exist, and is not equal to default toggle state (dw flag)
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -310,7 +316,7 @@
setOverride(OVERRIDE_ON_SETTING);
// Follow override if they exist, and is not equal to default toggle state (dw flag)
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -323,7 +329,7 @@
setOverride(OVERRIDE_OFF_SETTING);
// When toggle override matches its default state (dw flag), don't override flags
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isTrue();
}
@Test
@@ -336,7 +342,7 @@
setOverride(OVERRIDE_OFF_SETTING);
// When toggle override matches its default state (dw flag), don't override flags
- assertThat(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
+ assertThat(ENABLE_DESKTOP_WINDOWING_TRANSITIONS.isTrue()).isFalse();
}
@Test
@@ -375,5 +381,6 @@
"sCachedToggleOverride");
cachedToggleOverride.setAccessible(true);
cachedToggleOverride.set(null, null);
+ setOverride(OVERRIDE_UNSET_SETTING);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityServiceWarningTest.java b/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityServiceWarningTest.java
index 362eeea..8e906fd 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityServiceWarningTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/dialog/AccessibilityServiceWarningTest.java
@@ -25,6 +25,8 @@
import android.app.AlertDialog;
import android.content.Context;
import android.os.RemoteException;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.testing.AndroidTestingRunner;
@@ -33,6 +35,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
+import android.view.accessibility.Flags;
import android.widget.TextView;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -89,7 +92,19 @@
}
@Test
- public void createAccessibilityServiceWarningDialog_hasExpectedWindowParams() {
+ @RequiresFlagsDisabled(Flags.FLAG_WARNING_USE_DEFAULT_DIALOG_TYPE)
+ public void createAccessibilityServiceWarningDialog_hasExpectedWindowParams_isSystemDialog() {
+ createAccessibilityServiceWarningDialog_hasExpectedWindowParams(true);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_WARNING_USE_DEFAULT_DIALOG_TYPE)
+ public void createAccessibilityServiceWarningDialog_hasExpectedWindowParams_notSystemDialog() {
+ createAccessibilityServiceWarningDialog_hasExpectedWindowParams(false);
+ }
+
+ private void createAccessibilityServiceWarningDialog_hasExpectedWindowParams(
+ boolean expectSystemDialog) {
final AlertDialog dialog =
AccessibilityServiceWarning.createAccessibilityServiceWarningDialog(
mContext,
@@ -101,7 +116,11 @@
expect.that(dialogWindow.getAttributes().privateFlags
& SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
- expect.that(dialogWindow.getAttributes().type).isEqualTo(TYPE_SYSTEM_DIALOG);
+ if (expectSystemDialog) {
+ expect.that(dialogWindow.getAttributes().type).isEqualTo(TYPE_SYSTEM_DIALOG);
+ } else {
+ expect.that(dialogWindow.getAttributes().type).isNotEqualTo(TYPE_SYSTEM_DIALOG);
+ }
}
@Test
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/FocusTransitionListener.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/FocusTransitionListener.java
index 26aae2d..02a7991 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/FocusTransitionListener.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/FocusTransitionListener.java
@@ -26,5 +26,11 @@
/**
* Called when a transition changes the top, focused display.
*/
- void onFocusedDisplayChanged(int displayId);
+ default void onFocusedDisplayChanged(int displayId) {}
+
+ /**
+ * Called when the per-app or system-wide focus state has changed for a task.
+ */
+ default void onFocusedTaskChanged(int taskId, boolean isFocusedOnDisplay,
+ boolean isFocusedGlobally) {}
}
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
index 647a555a..0150bcd 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.os.SystemProperties;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
index c88a58b..1abe119 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
@@ -36,6 +36,8 @@
@VisibleForTesting
public enum Event implements UiEventLogger.UiEventEnum {
+ // region bubble events
+
@UiEvent(doc = "User dismissed the bubble via gesture, add bubble to overflow.")
BUBBLE_OVERFLOW_ADD_USER_GESTURE(483),
@@ -64,7 +66,89 @@
BUBBLE_OVERFLOW_SELECTED(600),
@UiEvent(doc = "Restore bubble to overflow after phone reboot.")
- BUBBLE_OVERFLOW_RECOVER(691);
+ BUBBLE_OVERFLOW_RECOVER(691),
+
+ // endregion
+
+ // region bubble bar events
+
+ @UiEvent(doc = "new bubble posted")
+ BUBBLE_BAR_BUBBLE_POSTED(1927),
+
+ @UiEvent(doc = "existing bubble updated")
+ BUBBLE_BAR_BUBBLE_UPDATED(1928),
+
+ @UiEvent(doc = "expanded a bubble from bubble bar")
+ BUBBLE_BAR_EXPANDED(1929),
+
+ @UiEvent(doc = "bubble bar collapsed")
+ BUBBLE_BAR_COLLAPSED(1930),
+
+ @UiEvent(doc = "dismissed single bubble from bubble bar by dragging it to dismiss target")
+ BUBBLE_BAR_BUBBLE_DISMISSED_DRAG_BUBBLE(1931),
+
+ @UiEvent(doc = "dismissed single bubble from bubble bar by dragging the expanded view to "
+ + "dismiss target")
+ BUBBLE_BAR_BUBBLE_DISMISSED_DRAG_EXP_VIEW(1932),
+
+ @UiEvent(doc = "dismiss bubble from app handle menu")
+ BUBBLE_BAR_BUBBLE_DISMISSED_APP_MENU(1933),
+
+ @UiEvent(doc = "bubble is dismissed due to app finishing the bubble activity")
+ BUBBLE_BAR_BUBBLE_ACTIVITY_FINISH(1934),
+
+ @UiEvent(doc = "dismissed the bubble bar by dragging it to dismiss target")
+ BUBBLE_BAR_DISMISSED_DRAG_BAR(1935),
+
+ @UiEvent(doc = "bubble bar moved to the left edge of the screen by dragging from the "
+ + "expanded view")
+ BUBBLE_BAR_MOVED_LEFT_DRAG_EXP_VIEW(1936),
+
+ @UiEvent(doc = "bubble bar moved to the left edge of the screen by dragging from a single"
+ + " bubble")
+ BUBBLE_BAR_MOVED_LEFT_DRAG_BUBBLE(1937),
+
+ @UiEvent(doc = "bubble bar moved to the left edge of the screen by dragging the bubble bar")
+ BUBBLE_BAR_MOVED_LEFT_DRAG_BAR(1938),
+
+ @UiEvent(doc = "bubble bar moved to the right edge of the screen by dragging from the "
+ + "expanded view")
+ BUBBLE_BAR_MOVED_RIGHT_DRAG_EXP_VIEW(1939),
+
+ @UiEvent(doc = "bubble bar moved to the right edge of the screen by dragging from a "
+ + "single bubble")
+ BUBBLE_BAR_MOVED_RIGHT_DRAG_BUBBLE(1940),
+
+ @UiEvent(doc = "bubble bar moved to the right edge of the screen by dragging the bubble "
+ + "bar")
+ BUBBLE_BAR_MOVED_RIGHT_DRAG_BAR(1941),
+
+ @UiEvent(doc = "stop bubbling conversation from app handle menu")
+ BUBBLE_BAR_APP_MENU_OPT_OUT(1942),
+
+ @UiEvent(doc = "open app settings from app handle menu")
+ BUBBLE_BAR_APP_MENU_GO_TO_SETTINGS(1943),
+
+ @UiEvent(doc = "flyout shown for a bubble")
+ BUBBLE_BAR_FLYOUT(1944),
+
+ @UiEvent(doc = "notification for the bubble was canceled")
+ BUBBLE_BAR_BUBBLE_REMOVED_CANCELED(1945),
+
+ @UiEvent(doc = "user turned off bubbles from settings")
+ BUBBLE_BAR_BUBBLE_REMOVED_BLOCKED(1946),
+
+ @UiEvent(doc = "bubble bar overflow opened")
+ BUBBLE_BAR_OVERFLOW_SELECTED(1947),
+
+ @UiEvent(doc = "max number of bubbles was reached in bubble bar, move bubble to overflow")
+ BUBBLE_BAR_OVERFLOW_ADD_AGED(1948),
+
+ @UiEvent(doc = "bubble promoted from overflow back to bubble bar")
+ BUBBLE_BAR_OVERFLOW_REMOVE_BACK_TO_BAR(1949),
+
+ // endregion
+ ;
private final int mId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index 4d15605c..2128cbc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -27,7 +27,7 @@
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 79c31e0..75adef4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -16,8 +16,8 @@
package com.android.wm.shell.dagger;
-import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS;
-import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT;
+import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS;
+import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT;
import android.annotation.Nullable;
import android.app.KeyguardManager;
@@ -71,10 +71,10 @@
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeLoggerTransitionObserver;
import com.android.wm.shell.desktopmode.DesktopRepository;
+import com.android.wm.shell.desktopmode.DesktopTaskChangeListener;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver;
-import com.android.wm.shell.desktopmode.DesktopTaskChangeListener;
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
@@ -92,9 +92,9 @@
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
-import com.android.wm.shell.freeform.TaskChangeListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarterInitializer;
+import com.android.wm.shell.freeform.TaskChangeListener;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.PipTransitionController;
@@ -111,6 +111,7 @@
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.DefaultMixedHandler;
+import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.HomeTransitionObserver;
import com.android.wm.shell.transition.MixedTransitionHandler;
import com.android.wm.shell.transition.Transitions;
@@ -391,10 +392,11 @@
Transitions transitions,
Optional<DesktopFullImmersiveTransitionHandler> desktopImmersiveTransitionHandler,
WindowDecorViewModel windowDecorViewModel,
- Optional<TaskChangeListener> taskChangeListener) {
+ Optional<TaskChangeListener> taskChangeListener,
+ FocusTransitionObserver focusTransitionObserver) {
return new FreeformTaskTransitionObserver(
context, shellInit, transitions, desktopImmersiveTransitionHandler,
- windowDecorViewModel, taskChangeListener);
+ windowDecorViewModel, taskChangeListener, focusTransitionObserver);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index fa8b6e6..75c795b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -48,14 +48,14 @@
import android.view.WindowManager.TRANSIT_NONE
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_FRONT
+import android.window.DesktopModeFlags
+import android.window.DesktopModeFlags.DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE
+import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
+import android.window.DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS
import android.window.RemoteTransition
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
-import android.window.flags.DesktopModeFlags
-import android.window.flags.DesktopModeFlags.DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE
-import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
-import android.window.flags.DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS
import androidx.annotation.BinderThread
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
index 37bec21..d6b7212 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
@@ -24,7 +24,7 @@
import android.view.WindowManager.TRANSIT_TO_BACK
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
-import android.window.flags.DesktopModeFlags
+import android.window.DesktopModeFlags
import androidx.annotation.VisibleForTesting
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
import com.android.internal.jank.InteractionJankMonitor
@@ -39,7 +39,7 @@
* Limits the number of tasks shown in Desktop Mode.
*
* This class should only be used if
- * [android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT]
+ * [android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT]
* is enabled and [maxTasksLimit] is strictly greater than 0.
*/
class DesktopTasksLimiter (
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 64ae35b..a4bc2fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -24,8 +24,8 @@
import android.view.WindowManager.TRANSIT_TO_BACK
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
-import android.window.flags.DesktopModeFlags
-import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
+import android.window.DesktopModeFlags
+import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 92e645d..ae65892 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -24,7 +24,7 @@
import android.content.Context;
import android.util.SparseArray;
import android.view.SurfaceControl;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
index c9eccc3..4106a10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
@@ -30,6 +30,7 @@
import com.android.window.flags.Flags;
import com.android.wm.shell.desktopmode.DesktopFullImmersiveTransitionHandler;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -50,6 +51,7 @@
private final Optional<DesktopFullImmersiveTransitionHandler> mImmersiveTransitionHandler;
private final WindowDecorViewModel mWindowDecorViewModel;
private final Optional<TaskChangeListener> mTaskChangeListener;
+ private final FocusTransitionObserver mFocusTransitionObserver;
private final Map<IBinder, List<ActivityManager.RunningTaskInfo>> mTransitionToTaskInfo =
new HashMap<>();
@@ -60,11 +62,13 @@
Transitions transitions,
Optional<DesktopFullImmersiveTransitionHandler> immersiveTransitionHandler,
WindowDecorViewModel windowDecorViewModel,
- Optional<TaskChangeListener> taskChangeListener) {
+ Optional<TaskChangeListener> taskChangeListener,
+ FocusTransitionObserver focusTransitionObserver) {
mTransitions = transitions;
mImmersiveTransitionHandler = immersiveTransitionHandler;
mWindowDecorViewModel = windowDecorViewModel;
mTaskChangeListener = taskChangeListener;
+ mFocusTransitionObserver = focusTransitionObserver;
if (FreeformComponents.isFreeformEnabled(context)) {
shellInit.addInitCallback(this::onInit, this);
}
@@ -87,6 +91,9 @@
// Otherwise window decoration relayout won't run with the immersive state up to date.
mImmersiveTransitionHandler.ifPresent(h -> h.onTransitionReady(transition));
}
+ // Update focus state first to ensure the correct state can be queried from listeners.
+ // TODO(371503964): Remove this once the unified task repository is ready.
+ mFocusTransitionObserver.updateFocusState(info);
final ArrayList<ActivityManager.RunningTaskInfo> taskInfoList = new ArrayList<>();
final ArrayList<WindowContainerToken> taskParents = new ArrayList<>();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterAnimator.java
new file mode 100644
index 0000000..f40a87c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterAnimator.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.animation;
+
+import android.animation.Animator;
+import android.animation.RectEvaluator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.pip.PipUtils;
+import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
+import com.android.wm.shell.shared.animation.Interpolators;
+
+/**
+ * Animator that handles bounds animations for entering PIP.
+ */
+public class PipEnterAnimator extends ValueAnimator
+ implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
+ @NonNull private final SurfaceControl mLeash;
+ private final SurfaceControl.Transaction mStartTransaction;
+ private final SurfaceControl.Transaction mFinishTransaction;
+
+ // Bounds updated by the evaluator as animator is running.
+ private final Rect mAnimatedRect = new Rect();
+
+ private final RectEvaluator mRectEvaluator;
+ private final Rect mEndBounds = new Rect();
+ @Nullable private final Rect mSourceRectHint;
+ private final @Surface.Rotation int mRotation;
+ @Nullable private Runnable mAnimationStartCallback;
+ @Nullable private Runnable mAnimationEndCallback;
+
+ private final PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
+ mSurfaceControlTransactionFactory;
+
+ // Internal state representing initial transform - cached to avoid recalculation.
+ private final PointF mInitScale = new PointF();
+ private final PointF mInitPos = new PointF();
+ private final Rect mInitCrop = new Rect();
+
+ public PipEnterAnimator(Context context,
+ @NonNull SurfaceControl leash,
+ SurfaceControl.Transaction startTransaction,
+ SurfaceControl.Transaction finishTransaction,
+ @NonNull Rect endBounds,
+ @Nullable Rect sourceRectHint,
+ @Surface.Rotation int rotation) {
+ mLeash = leash;
+ mStartTransaction = startTransaction;
+ mFinishTransaction = finishTransaction;
+ mRectEvaluator = new RectEvaluator(mAnimatedRect);
+ mEndBounds.set(endBounds);
+ mSourceRectHint = sourceRectHint != null ? new Rect(sourceRectHint) : null;
+ mRotation = rotation;
+ mSurfaceControlTransactionFactory =
+ new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
+
+ final int enterAnimationDuration = context.getResources()
+ .getInteger(R.integer.config_pipEnterAnimationDuration);
+ setDuration(enterAnimationDuration);
+ setFloatValues(0f, 1f);
+ setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ addListener(this);
+ addUpdateListener(this);
+ }
+
+ public void setAnimationStartCallback(@NonNull Runnable runnable) {
+ mAnimationStartCallback = runnable;
+ }
+
+ public void setAnimationEndCallback(@NonNull Runnable runnable) {
+ mAnimationEndCallback = runnable;
+ }
+
+ @Override
+ public void onAnimationStart(@NonNull Animator animation) {
+ if (mAnimationStartCallback != null) {
+ mAnimationStartCallback.run();
+ }
+ if (mStartTransaction != null) {
+ onEnterAnimationUpdate(mInitScale, mInitPos, mInitCrop,
+ 0f /* fraction */, mStartTransaction);
+ mStartTransaction.apply();
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation) {
+ if (mAnimationEndCallback != null) {
+ mAnimationEndCallback.run();
+ }
+ }
+
+ @Override
+ public void onAnimationUpdate(@NonNull ValueAnimator animation) {
+ final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
+ final float fraction = getAnimatedFraction();
+ onEnterAnimationUpdate(mInitScale, mInitPos, mInitCrop, fraction, tx);
+ tx.apply();
+ }
+
+ private void onEnterAnimationUpdate(PointF initScale, PointF initPos, Rect initCrop,
+ float fraction, SurfaceControl.Transaction tx) {
+ float scaleX = 1 + (initScale.x - 1) * (1 - fraction);
+ float scaleY = 1 + (initScale.y - 1) * (1 - fraction);
+ tx.setScale(mLeash, scaleX, scaleY);
+
+ float posX = initPos.x + (mEndBounds.left - initPos.x) * fraction;
+ float posY = initPos.y + (mEndBounds.top - initPos.y) * fraction;
+ tx.setPosition(mLeash, posX, posY);
+
+ Rect endCrop = new Rect(mEndBounds);
+ endCrop.offsetTo(0, 0);
+ mRectEvaluator.evaluate(fraction, initCrop, endCrop);
+ tx.setCrop(mLeash, mAnimatedRect);
+ }
+
+ // no-ops
+
+ @Override
+ public void onAnimationCancel(@NonNull Animator animation) {}
+
+ @Override
+ public void onAnimationRepeat(@NonNull Animator animation) {}
+
+ /**
+ * Caches the initial transform relevant values for the bounds enter animation.
+ *
+ * Since enter PiP makes use of a config-at-end transition, initial transform needs to be
+ * calculated differently from generic transitions.
+ * @param pipChange PiP change received as a transition target.
+ */
+ public void setEnterStartState(@NonNull TransitionInfo.Change pipChange) {
+ PipUtils.calcStartTransform(pipChange, mInitScale, mInitPos, mInitCrop);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipExpandAnimator.java
similarity index 77%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipExpandAnimator.java
index 8ebdc96..8fa5aa9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipExpandAnimator.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
-import android.annotation.IntDef;
import android.content.Context;
import android.graphics.Rect;
import android.view.Surface;
@@ -30,35 +29,22 @@
import com.android.wm.shell.R;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import com.android.wm.shell.shared.animation.Interpolators;
/**
- * Animator that handles bounds animations for entering / exiting PIP.
+ * Animator that handles bounds animations for exit-via-expanding PIP.
*/
-public class PipEnterExitAnimator extends ValueAnimator
+public class PipExpandAnimator extends ValueAnimator
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
- @IntDef(prefix = {"BOUNDS_"}, value = {
- BOUNDS_ENTER,
- BOUNDS_EXIT
- })
-
- @Retention(RetentionPolicy.SOURCE)
- public @interface BOUNDS {}
-
- public static final int BOUNDS_ENTER = 0;
- public static final int BOUNDS_EXIT = 1;
-
- @NonNull private final SurfaceControl mLeash;
+ @NonNull
+ private final SurfaceControl mLeash;
private final SurfaceControl.Transaction mStartTransaction;
private final SurfaceControl.Transaction mFinishTransaction;
- private final int mEnterExitAnimationDuration;
- private final @BOUNDS int mDirection;
private final @Surface.Rotation int mRotation;
// optional callbacks for tracking animation start and end
- @Nullable private Runnable mAnimationStartCallback;
+ @Nullable
+ private Runnable mAnimationStartCallback;
@Nullable private Runnable mAnimationEndCallback;
private final Rect mBaseBounds = new Rect();
@@ -78,7 +64,7 @@
private final RectEvaluator mInsetEvaluator;
private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
- public PipEnterExitAnimator(Context context,
+ public PipExpandAnimator(Context context,
@NonNull SurfaceControl leash,
SurfaceControl.Transaction startTransaction,
SurfaceControl.Transaction finishTransaction,
@@ -86,7 +72,6 @@
@NonNull Rect startBounds,
@NonNull Rect endBounds,
@Nullable Rect sourceRectHint,
- @BOUNDS int direction,
@Surface.Rotation int rotation) {
mLeash = leash;
mStartTransaction = startTransaction;
@@ -98,7 +83,6 @@
mRectEvaluator = new RectEvaluator(mAnimatedRect);
mInsetEvaluator = new RectEvaluator(new Rect());
mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context);
- mDirection = direction;
mRotation = rotation;
mSourceRectHint = sourceRectHint != null ? new Rect(sourceRectHint) : null;
@@ -113,12 +97,14 @@
mSurfaceControlTransactionFactory =
new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
- mEnterExitAnimationDuration = context.getResources()
+
+ final int enterAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipEnterAnimationDuration);
+ setDuration(enterAnimationDuration);
setObjectValues(startBounds, endBounds);
- setDuration(mEnterExitAnimationDuration);
setEvaluator(mRectEvaluator);
+ setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
addListener(this);
addUpdateListener(this);
}
@@ -147,9 +133,10 @@
// finishTransaction might override some state (eg. corner radii) so we want to
// manually set the state to the end of the animation
mPipSurfaceTransactionHelper.scaleAndCrop(mFinishTransaction, mLeash, mSourceRectHint,
- mBaseBounds, mAnimatedRect, getInsets(1f), isInPipDirection(), 1f)
- .round(mFinishTransaction, mLeash, isInPipDirection())
- .shadow(mFinishTransaction, mLeash, isInPipDirection());
+ mBaseBounds, mAnimatedRect, getInsets(1f),
+ false /* isInPipDirection */, 1f)
+ .round(mFinishTransaction, mLeash, false /* applyCornerRadius */)
+ .shadow(mFinishTransaction, mLeash, false /* applyCornerRadius */);
}
if (mAnimationEndCallback != null) {
mAnimationEndCallback.run();
@@ -160,32 +147,22 @@
public void onAnimationUpdate(@NonNull ValueAnimator animation) {
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
final float fraction = getAnimatedFraction();
- Rect insets = getInsets(fraction);
// TODO (b/350801661): implement fixed rotation
+ Rect insets = getInsets(fraction);
mPipSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mSourceRectHint,
- mBaseBounds, mAnimatedRect, insets, isInPipDirection(), fraction)
- .round(tx, mLeash, isInPipDirection())
- .shadow(tx, mLeash, isInPipDirection());
+ mBaseBounds, mAnimatedRect, insets, false /* isInPipDirection */, fraction)
+ .round(tx, mLeash, false /* applyCornerRadius */)
+ .shadow(tx, mLeash, false /* applyCornerRadius */);
tx.apply();
}
-
private Rect getInsets(float fraction) {
- Rect startInsets = isInPipDirection() ? mZeroInsets : mSourceRectHintInsets;
- Rect endInsets = isInPipDirection() ? mSourceRectHintInsets : mZeroInsets;
-
+ final Rect startInsets = mSourceRectHintInsets;
+ final Rect endInsets = mZeroInsets;
return mInsetEvaluator.evaluate(fraction, startInsets, endInsets);
}
- private boolean isInPipDirection() {
- return mDirection == BOUNDS_ENTER;
- }
-
- private boolean isOutPipDirection() {
- return mDirection == BOUNDS_EXIT;
- }
-
// no-ops
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 62a60fa..b57f51a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -56,7 +56,8 @@
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip2.animation.PipAlphaAnimator;
-import com.android.wm.shell.pip2.animation.PipEnterExitAnimator;
+import com.android.wm.shell.pip2.animation.PipEnterAnimator;
+import com.android.wm.shell.pip2.animation.PipExpandAnimator;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.shared.pip.PipContentOverlay;
import com.android.wm.shell.sysui.ShellInit;
@@ -218,6 +219,7 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ mFinishCallback = finishCallback;
if (transition == mEnterTransition || info.getType() == TRANSIT_PIP) {
mEnterTransition = null;
// If we are in swipe PiP to Home transition we are ENTERING_PIP as a jumpcut transition
@@ -258,6 +260,7 @@
if (isRemovePipTransition(info)) {
return removePipImmediately(info, startTransaction, finishTransaction, finishCallback);
}
+ mFinishCallback = null;
return false;
}
@@ -297,7 +300,6 @@
mBoundsChangeDuration = BOUNDS_CHANGE_JUMPCUT_DURATION;
}
- mFinishCallback = finishCallback;
mPipTransitionState.setState(PipTransitionState.CHANGING_PIP_BOUNDS, extra);
return true;
}
@@ -349,7 +351,6 @@
startTransaction.setMatrix(pipLeash, transformTensor, matrixTmp);
}
startTransaction.apply();
- finishCallback.onTransitionFinished(null /* finishWct */);
finishInner();
return true;
}
@@ -386,14 +387,6 @@
return false;
}
- WindowContainerToken pipTaskToken = pipChange.getContainer();
- if (pipTaskToken == null) {
- return false;
- }
-
- WindowContainerTransaction finishWct = new WindowContainerTransaction();
- SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
-
Rect startBounds = pipChange.getStartAbsBounds();
Rect endBounds = pipChange.getEndAbsBounds();
SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash;
@@ -405,29 +398,22 @@
sourceRectHint = pipChange.getTaskInfo().pictureInPictureParams.getSourceRectHint();
}
- // For opening type transitions, if there is a non-pip change of mode TO_FRONT/OPEN,
+ // For opening type transitions, if there is a change of mode TO_FRONT/OPEN,
// make sure that change has alpha of 1f, since it's init state might be set to alpha=0f
// by the Transitions framework to simplify Task opening transitions.
if (TransitionUtil.isOpeningType(info.getType())) {
for (TransitionInfo.Change change : info.getChanges()) {
- if (change.getLeash() == null || change == pipChange) continue;
+ if (change.getLeash() == null) continue;
if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
startTransaction.setAlpha(change.getLeash(), 1f);
}
}
}
- PipEnterExitAnimator animator = new PipEnterExitAnimator(mContext, pipLeash,
- startTransaction, finishTransaction, startBounds, startBounds, endBounds,
- sourceRectHint, PipEnterExitAnimator.BOUNDS_ENTER, Surface.ROTATION_0);
-
- tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(),
- this::finishInner);
- finishWct.setBoundsChangeTransaction(pipTaskToken, tx);
-
- animator.setAnimationEndCallback(() ->
- finishCallback.onTransitionFinished(finishWct));
-
+ PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash,
+ startTransaction, finishTransaction, endBounds, sourceRectHint, Surface.ROTATION_0);
+ animator.setAnimationStartCallback(() -> animator.setEnterStartState(pipChange));
+ animator.setAnimationEndCallback(this::finishInner);
animator.start();
return true;
}
@@ -452,11 +438,8 @@
PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipLeash, startTransaction,
PipAlphaAnimator.FADE_IN);
- animator.setAnimationEndCallback(() -> {
- finishCallback.onTransitionFinished(null);
- // This should update the pip transition state accordingly after we stop playing.
- finishInner();
- });
+ // This should update the pip transition state accordingly after we stop playing.
+ animator.setAnimationEndCallback(this::finishInner);
animator.start();
return true;
@@ -510,9 +493,9 @@
sourceRectHint = mPipTaskListener.getPictureInPictureParams().getSourceRectHint();
}
- PipEnterExitAnimator animator = new PipEnterExitAnimator(mContext, pipLeash,
+ PipExpandAnimator animator = new PipExpandAnimator(mContext, pipLeash,
startTransaction, finishTransaction, endBounds, startBounds, endBounds,
- sourceRectHint, PipEnterExitAnimator.BOUNDS_EXIT, Surface.ROTATION_0);
+ sourceRectHint, Surface.ROTATION_0);
animator.setAnimationEndCallback(() -> {
mPipTransitionState.setState(PipTransitionState.EXITED_PIP);
@@ -631,6 +614,7 @@
//
private void finishInner() {
+ finishTransition(null /* tx */);
if (mPipTransitionState.getSwipePipToHomeOverlay() != null) {
startOverlayFadeoutAnimation();
} else if (mPipTransitionState.getState() == PipTransitionState.ENTERING_PIP) {
@@ -652,6 +636,7 @@
}
if (mFinishCallback != null) {
mFinishCallback.onTransitionFinished(wct);
+ mFinishCallback = null;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index a0b7a29..6086801 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -38,8 +38,8 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.window.DesktopModeFlags;
import android.window.WindowContainerToken;
-import android.window.flags.DesktopModeFlags;
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt
index 0cbbb71..1af99f9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt
@@ -21,7 +21,7 @@
import android.util.ArrayMap
import android.view.SurfaceControl
import android.window.TransitionInfo
-import android.window.flags.DesktopModeFlags
+import android.window.DesktopModeFlags
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.Transitions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
index 399e39a..6d01e24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
@@ -16,7 +16,8 @@
package com.android.wm.shell.transition;
-import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
@@ -24,10 +25,11 @@
import static com.android.wm.shell.transition.Transitions.TransitionObserver;
import android.annotation.NonNull;
-import android.os.IBinder;
+import android.app.ActivityManager.RunningTaskInfo;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.util.Slog;
-import android.view.SurfaceControl;
+import android.util.SparseArray;
import android.window.TransitionInfo;
import com.android.wm.shell.shared.FocusTransitionListener;
@@ -43,44 +45,64 @@
* It reports transitions to callers outside of the process via {@link IFocusTransitionListener},
* and callers within the process via {@link FocusTransitionListener}.
*/
-public class FocusTransitionObserver implements TransitionObserver {
+public class FocusTransitionObserver {
private static final String TAG = FocusTransitionObserver.class.getSimpleName();
private IFocusTransitionListener mRemoteListener;
private final Map<FocusTransitionListener, Executor> mLocalListeners =
new HashMap<>();
- private int mFocusedDisplayId = INVALID_DISPLAY;
+ private int mFocusedDisplayId = DEFAULT_DISPLAY;
+ private final SparseArray<RunningTaskInfo> mFocusedTaskOnDisplay = new SparseArray<>();
+
+ private final ArraySet<RunningTaskInfo> mTmpTasksToBeNotified = new ArraySet<>();
public FocusTransitionObserver() {}
- @Override
- public void onTransitionReady(@NonNull IBinder transition,
- @NonNull TransitionInfo info,
- @NonNull SurfaceControl.Transaction startTransaction,
- @NonNull SurfaceControl.Transaction finishTransaction) {
+ /**
+ * Update display/window focus state from the given transition info and notifies changes if any.
+ */
+ public void updateFocusState(@NonNull TransitionInfo info) {
+ if (!enableDisplayFocusInShellTransitions()) {
+ return;
+ }
final List<TransitionInfo.Change> changes = info.getChanges();
for (int i = changes.size() - 1; i >= 0; i--) {
final TransitionInfo.Change change = changes.get(i);
+
+ final RunningTaskInfo task = change.getTaskInfo();
+ if (task != null
+ && (change.hasFlags(FLAG_MOVED_TO_TOP) || change.getMode() == TRANSIT_OPEN)) {
+ final RunningTaskInfo lastFocusedTaskOnDisplay =
+ mFocusedTaskOnDisplay.get(task.displayId);
+ if (lastFocusedTaskOnDisplay != null) {
+ mTmpTasksToBeNotified.add(lastFocusedTaskOnDisplay);
+ }
+ mTmpTasksToBeNotified.add(task);
+ mFocusedTaskOnDisplay.put(task.displayId, task);
+ }
+
if (change.hasFlags(FLAG_IS_DISPLAY) && change.hasFlags(FLAG_MOVED_TO_TOP)) {
if (mFocusedDisplayId != change.getEndDisplayId()) {
+ final RunningTaskInfo lastGloballyFocusedTask =
+ mFocusedTaskOnDisplay.get(mFocusedDisplayId);
+ if (lastGloballyFocusedTask != null) {
+ mTmpTasksToBeNotified.add(lastGloballyFocusedTask);
+ }
mFocusedDisplayId = change.getEndDisplayId();
notifyFocusedDisplayChanged();
+ final RunningTaskInfo currentGloballyFocusedTask =
+ mFocusedTaskOnDisplay.get(mFocusedDisplayId);
+ if (currentGloballyFocusedTask != null) {
+ mTmpTasksToBeNotified.add(currentGloballyFocusedTask);
+ }
}
- return;
}
}
+ mTmpTasksToBeNotified.forEach(this::notifyTaskFocusChanged);
+ mTmpTasksToBeNotified.clear();
}
- @Override
- public void onTransitionStarting(@NonNull IBinder transition) {}
-
- @Override
- public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {}
-
- @Override
- public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {}
-
/**
* Sets the focus transition listener that receives any transitions resulting in focus switch.
* This is for calls from outside the Shell, within the host process.
@@ -92,7 +114,10 @@
return;
}
mLocalListeners.put(listener, executor);
- executor.execute(() -> listener.onFocusedDisplayChanged(mFocusedDisplayId));
+ executor.execute(() -> {
+ listener.onFocusedDisplayChanged(mFocusedDisplayId);
+ mTmpTasksToBeNotified.forEach(this::notifyTaskFocusChanged);
+ });
}
/**
@@ -120,13 +145,20 @@
notifyFocusedDisplayChangedToRemote();
}
- /**
- * Notifies the listener that display focus has changed.
- */
- public void notifyFocusedDisplayChanged() {
+ private void notifyTaskFocusChanged(RunningTaskInfo task) {
+ final boolean isFocusedOnDisplay = isFocusedOnDisplay(task);
+ final boolean isFocusedGlobally = hasGlobalFocus(task);
+ mLocalListeners.forEach((listener, executor) ->
+ executor.execute(() -> listener.onFocusedTaskChanged(task.taskId,
+ isFocusedOnDisplay, isFocusedGlobally)));
+ }
+
+ private void notifyFocusedDisplayChanged() {
notifyFocusedDisplayChangedToRemote();
mLocalListeners.forEach((listener, executor) ->
- executor.execute(() -> listener.onFocusedDisplayChanged(mFocusedDisplayId)));
+ executor.execute(() -> {
+ listener.onFocusedDisplayChanged(mFocusedDisplayId);
+ }));
}
private void notifyFocusedDisplayChangedToRemote() {
@@ -138,4 +170,23 @@
}
}
}
+
+ private boolean isFocusedOnDisplay(@NonNull RunningTaskInfo task) {
+ if (!enableDisplayFocusInShellTransitions()) {
+ return task.isFocused;
+ }
+ final RunningTaskInfo focusedTaskOnDisplay = mFocusedTaskOnDisplay.get(task.displayId);
+ return focusedTaskOnDisplay != null && focusedTaskOnDisplay.taskId == task.taskId;
+ }
+
+ /**
+ * Checks whether the given task has focused globally on the system.
+ * (Note {@link RunningTaskInfo#isFocused} represents per-display focus.)
+ */
+ public boolean hasGlobalFocus(@NonNull RunningTaskInfo task) {
+ if (!enableDisplayFocusInShellTransitions()) {
+ return task.isFocused;
+ }
+ return task.displayId == mFocusedDisplayId && isFocusedOnDisplay(task);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index d5e92e6..346f21b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -392,8 +392,6 @@
mShellCommandHandler.addCommandCallback("transitions", this, this);
mShellCommandHandler.addDumpCallback(this::dump, this);
-
- registerObserver(mFocusTransitionObserver);
}
public boolean isRegistered() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 839973f..576c911 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -16,7 +16,7 @@
package com.android.wm.shell.windowdecor;
-import static android.window.flags.DesktopModeFlags.ENABLE_WINDOWING_SCALED_RESIZING;
+import static android.window.DesktopModeFlags.ENABLE_WINDOWING_SCALED_RESIZING;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index bcf48d9..e55bc67 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -77,10 +77,10 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Toast;
+import android.window.DesktopModeFlags;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
-import android.window.flags.DesktopModeFlags;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
@@ -103,8 +103,8 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
-import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator;
+import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
@@ -133,14 +133,14 @@
import kotlin.Pair;
import kotlin.Unit;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
/**
* View model for the window decoration with a caption and shadows. Works with
* {@link DesktopModeWindowDecoration}.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 25d37fc..a78fb9b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -24,8 +24,8 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
import static com.android.launcher3.icons.BaseIconFactory.MODE_DEFAULT;
import static com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode;
@@ -72,9 +72,9 @@
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.ImageButton;
+import android.window.DesktopModeFlags;
import android.window.TaskSnapshot;
import android.window.WindowContainerTransaction;
-import android.window.flags.DesktopModeFlags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.ScreenDecorationsUtils;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
index 38f9cfa..60c9222 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
@@ -27,7 +27,7 @@
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.SurfaceControl;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import androidx.annotation.NonNull;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index d726f50..33d1c26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -18,7 +18,7 @@
import static android.view.InputDevice.SOURCE_MOUSE;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
-import static android.window.flags.DesktopModeFlags.ENABLE_WINDOWING_EDGE_DRAG_RESIZE;
+import static android.window.DesktopModeFlags.ENABLE_WINDOWING_EDGE_DRAG_RESIZE;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt
index 68a58ee0..376cd2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeButtonView.kt
@@ -33,7 +33,7 @@
import androidx.core.animation.doOnStart
import androidx.core.content.ContextCompat
import com.android.wm.shell.R
-import android.window.flags.DesktopModeFlags
+import android.window.DesktopModeFlags
private const val OPEN_MAXIMIZE_MENU_DELAY_ON_HOVER_MS = 350
private const val MAX_DRAWABLE_ALPHA = 255
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
index 52bf400..c2af1d4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
@@ -49,7 +49,7 @@
import com.android.window.flags.Flags
import com.android.window.flags.Flags.enableMinimizeButton
import com.android.wm.shell.R
-import android.window.flags.DesktopModeFlags
+import android.window.DesktopModeFlags
import com.android.wm.shell.windowdecor.MaximizeButtonView
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
import com.android.wm.shell.windowdecor.common.OPACITY_100
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
index d4a319e..145819f3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
@@ -22,7 +22,6 @@
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.view.WindowManager.TRANSIT_CHANGE;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -44,18 +43,14 @@
import androidx.test.filters.SmallTest;
import com.android.window.flags.Flags;
-
-import com.android.wm.shell.desktopmode.DesktopTaskChangeListener;
import com.android.wm.shell.desktopmode.DesktopFullImmersiveTransitionHandler;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.TransitionInfoBuilder;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
-import java.util.Optional;
-
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -80,6 +75,9 @@
private WindowDecorViewModel mWindowDecorViewModel;
@Mock
private TaskChangeListener mTaskChangeListener;
+ @Mock
+ private FocusTransitionObserver mFocusTransitionObserver;
+
private FreeformTaskTransitionObserver mTransitionObserver;
@Before
@@ -95,7 +93,7 @@
mTransitionObserver = new FreeformTaskTransitionObserver(
context, mShellInit, mTransitions,
Optional.of(mDesktopFullImmersiveTransitionHandler),
- mWindowDecorViewModel, Optional.of(mTaskChangeListener));
+ mWindowDecorViewModel, Optional.of(mTaskChangeListener), mFocusTransitionObserver);
final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass(
Runnable.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
index d63158c..015ea20 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
@@ -23,6 +23,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -30,9 +31,6 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager.RunningTaskInfo;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteException;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -43,17 +41,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.window.flags.Flags;
-import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.shared.IFocusTransitionListener;
-import com.android.wm.shell.shared.TransactionPool;
-import com.android.wm.shell.sysui.ShellController;
-import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.shared.FocusTransitionListener;
import org.junit.Before;
import org.junit.Rule;
@@ -75,57 +67,64 @@
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
- private IFocusTransitionListener mListener;
- private Transitions mTransition;
+ private FocusTransitionListener mListener;
+ private final TestShellExecutor mShellExecutor = new TestShellExecutor();
private FocusTransitionObserver mFocusTransitionObserver;
@Before
public void setUp() {
- mListener = mock(IFocusTransitionListener.class);
- when(mListener.asBinder()).thenReturn(mock(IBinder.class));
-
+ mListener = mock(FocusTransitionListener.class);
mFocusTransitionObserver = new FocusTransitionObserver();
- mTransition =
- new Transitions(InstrumentationRegistry.getInstrumentation().getTargetContext(),
- mock(ShellInit.class), mock(ShellController.class),
- mock(ShellTaskOrganizer.class), mock(TransactionPool.class),
- mock(DisplayController.class), new TestShellExecutor(),
- new Handler(Looper.getMainLooper()), new TestShellExecutor(),
- mock(HomeTransitionObserver.class),
- mFocusTransitionObserver);
- mFocusTransitionObserver.setRemoteFocusTransitionListener(mTransition, mListener);
+ mFocusTransitionObserver.setLocalFocusTransitionListener(mListener, mShellExecutor);
+ mShellExecutor.flushAll();
+ clearInvocations(mListener);
}
@Test
- public void testOnlyDisplayChangeAffectsDisplayFocus() throws RemoteException {
- final IBinder binder = mock(IBinder.class);
+ public void testBasicTaskAndDisplayFocusSwitch() throws RemoteException {
final SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class);
- // Open a task on the secondary display, but it doesn't change display focus because it only
- // has a task change.
+ // First, open a task on the default display.
TransitionInfo info = mock(TransitionInfo.class);
final List<TransitionInfo.Change> changes = new ArrayList<>();
- setupTaskChange(changes, 123 /* taskId */, TRANSIT_OPEN, SECONDARY_DISPLAY_ID,
- true /* focused */);
+ setupTaskChange(changes, 1 /* taskId */, TRANSIT_OPEN,
+ DEFAULT_DISPLAY, true /* focused */);
when(info.getChanges()).thenReturn(changes);
- mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
- verify(mListener, never()).onFocusedDisplayChanged(SECONDARY_DISPLAY_ID);
+ mFocusTransitionObserver.updateFocusState(info);
+ mShellExecutor.flushAll();
+ verify(mListener, never()).onFocusedDisplayChanged(anyInt());
+ verify(mListener, times(1)).onFocusedTaskChanged(1 /* taskId */,
+ true /* isFocusedOnDisplay */, true /* isFocusedGlobally */);
clearInvocations(mListener);
- // Moving the secondary display to front must change display focus to it.
- changes.clear();
+ // Open a task on the secondary display.
+ setupTaskChange(changes, 2 /* taskId */, TRANSIT_OPEN,
+ SECONDARY_DISPLAY_ID, true /* focused */);
setupDisplayToTopChange(changes, SECONDARY_DISPLAY_ID);
when(info.getChanges()).thenReturn(changes);
- mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
+ mFocusTransitionObserver.updateFocusState(info);
+ mShellExecutor.flushAll();
verify(mListener, times(1))
.onFocusedDisplayChanged(SECONDARY_DISPLAY_ID);
+ verify(mListener, times(1)).onFocusedTaskChanged(1 /* taskId */,
+ true /* isFocusedOnDisplay */, false /* isFocusedGlobally */);
+ verify(mListener, times(1)).onFocusedTaskChanged(2 /* taskId */,
+ true /* isFocusedOnDisplay */, true /* isFocusedGlobally */);
+ clearInvocations(mListener);
- // Moving the secondary display to front must change display focus back to it.
+ // Moving only the default display back to front, and verify that affected tasks are also
+ // notified.
changes.clear();
setupDisplayToTopChange(changes, DEFAULT_DISPLAY);
when(info.getChanges()).thenReturn(changes);
- mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
- verify(mListener, times(1)).onFocusedDisplayChanged(DEFAULT_DISPLAY);
+ mFocusTransitionObserver.updateFocusState(info);
+ mShellExecutor.flushAll();
+ verify(mListener, times(1))
+ .onFocusedDisplayChanged(DEFAULT_DISPLAY);
+ verify(mListener, times(1)).onFocusedTaskChanged(1 /* taskId */,
+ true /* isFocusedOnDisplay */, true /* isFocusedGlobally */);
+ verify(mListener, times(1)).onFocusedTaskChanged(2 /* taskId */,
+ true /* isFocusedOnDisplay */, false /* isFocusedGlobally */);
}
private void setupTaskChange(List<TransitionInfo.Change> changes, int taskId,
diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp
index e81cbfb..c0ef4b14 100644
--- a/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp
+++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp
@@ -29,37 +29,6 @@
namespace uirenderer {
namespace skiapipeline {
-BackdropFilterDrawable::~BackdropFilterDrawable() {}
-
-bool BackdropFilterDrawable::prepareToDraw(SkCanvas* canvas, const RenderProperties& properties,
- int backdropImageWidth, int backdropImageHeight) {
- // the drawing bounds for blurred content.
- mDstBounds.setWH(properties.getWidth(), properties.getHeight());
-
- float alphaMultiplier = 1.0f;
- RenderNodeDrawable::setViewProperties(properties, canvas, &alphaMultiplier, true);
-
- // get proper subset for previous content.
- canvas->getTotalMatrix().mapRect(&mImageSubset, mDstBounds);
- SkRect imageSubset(mImageSubset);
- // ensure the subset is inside bounds of previous content.
- if (!mImageSubset.intersect(SkRect::MakeWH(backdropImageWidth, backdropImageHeight))) {
- return false;
- }
-
- // correct the drawing bounds if subset was changed.
- if (mImageSubset != imageSubset) {
- SkMatrix inverse;
- if (canvas->getTotalMatrix().invert(&inverse)) {
- inverse.mapRect(&mDstBounds, mImageSubset);
- }
- }
-
- // follow the alpha from the target RenderNode.
- mPaint.setAlpha(properties.layerProperties().alpha() * alphaMultiplier);
- return true;
-}
-
void BackdropFilterDrawable::onDraw(SkCanvas* canvas) {
const RenderProperties& properties = mTargetRenderNode->properties();
auto* backdropFilter = properties.layerProperties().getBackdropImageFilter();
@@ -68,27 +37,43 @@
return;
}
- auto backdropImage = surface->makeImageSnapshot();
- // sync necessary properties from target RenderNode.
- if (!prepareToDraw(canvas, properties, backdropImage->width(), backdropImage->height())) {
+ SkRect srcBounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
+
+ float alphaMultiplier = 1.0f;
+ RenderNodeDrawable::setViewProperties(properties, canvas, &alphaMultiplier, true);
+ SkPaint paint;
+ paint.setAlpha(properties.layerProperties().alpha() * alphaMultiplier);
+
+ SkRect surfaceSubset;
+ canvas->getTotalMatrix().mapRect(&surfaceSubset, srcBounds);
+ if (!surfaceSubset.intersect(SkRect::MakeWH(surface->width(), surface->height()))) {
return;
}
- auto imageSubset = mImageSubset.roundOut();
+ auto backdropImage = surface->makeImageSnapshot(surfaceSubset.roundOut());
+
+ SkIRect imageBounds = SkIRect::MakeWH(backdropImage->width(), backdropImage->height());
+ SkIPoint offset;
+ SkIRect imageSubset;
+
#ifdef __ANDROID__
if (canvas->recordingContext()) {
backdropImage =
SkImages::MakeWithFilter(canvas->recordingContext(), backdropImage, backdropFilter,
- imageSubset, imageSubset, &mOutSubset, &mOutOffset);
+ imageBounds, imageBounds, &imageSubset, &offset);
} else
#endif
{
- backdropImage = SkImages::MakeWithFilter(backdropImage, backdropFilter, imageSubset,
- imageSubset, &mOutSubset, &mOutOffset);
+ backdropImage = SkImages::MakeWithFilter(backdropImage, backdropFilter, imageBounds,
+ imageBounds, &imageSubset, &offset);
}
- canvas->drawImageRect(backdropImage, SkRect::Make(mOutSubset), mDstBounds,
- SkSamplingOptions(SkFilterMode::kLinear), &mPaint,
- SkCanvas::kStrict_SrcRectConstraint);
+
+ canvas->save();
+ canvas->resetMatrix();
+ canvas->drawImageRect(backdropImage, SkRect::Make(imageSubset), surfaceSubset,
+ SkSamplingOptions(SkFilterMode::kLinear), &paint,
+ SkCanvas::kFast_SrcRectConstraint);
+ canvas->restore();
}
} // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.h b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h
index 9e35837..5e216a1 100644
--- a/libs/hwui/pipeline/skia/BackdropFilterDrawable.h
+++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h
@@ -37,23 +37,10 @@
BackdropFilterDrawable(RenderNode* renderNode, SkCanvas* canvas)
: mTargetRenderNode(renderNode), mBounds(canvas->getLocalClipBounds()) {}
- ~BackdropFilterDrawable();
+ ~BackdropFilterDrawable() = default;
private:
RenderNode* mTargetRenderNode;
- SkPaint mPaint;
-
- SkRect mDstBounds;
- SkRect mImageSubset;
- SkIRect mOutSubset;
- SkIPoint mOutOffset;
-
- /**
- * Check all necessary properties before actual drawing.
- * Return true if ready to draw.
- */
- bool prepareToDraw(SkCanvas* canvas, const RenderProperties& properties, int backdropImageWidth,
- int backdropImageHeight);
protected:
void onDraw(SkCanvas* canvas) override;
diff --git a/libs/hwui/tests/common/scenes/BackdropBlur.cpp b/libs/hwui/tests/common/scenes/BackdropBlur.cpp
new file mode 100644
index 0000000..a1133ff
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/BackdropBlur.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <SkBlendMode.h>
+
+#include "SkImageFilter.h"
+#include "SkImageFilters.h"
+#include "TestSceneBase.h"
+#include "utils/Blur.h"
+
+class BackdropBlurAnimation : public TestScene {
+private:
+ std::unique_ptr<TestScene> listView;
+
+public:
+ explicit BackdropBlurAnimation(const TestScene::Options& opts) {
+ listView.reset(TestScene::testMap()["listview"].createScene(opts));
+ }
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ sp<RenderNode> list = TestUtils::createNode(
+ 0, 0, width, height,
+ [this, width, height](RenderProperties& props, Canvas& canvas) {
+ props.setClipToBounds(false);
+ listView->createContent(width, height, canvas);
+ });
+
+ canvas.drawRenderNode(list.get());
+
+ int x = width / 8;
+ int y = height / 4;
+ sp<RenderNode> blurNode = TestUtils::createNode(
+ x, y, width - x, height - y, [](RenderProperties& props, Canvas& canvas) {
+ props.mutableOutline().setRoundRect(0, 0, props.getWidth(), props.getHeight(),
+ dp(16), 1);
+ props.mutableOutline().setShouldClip(true);
+ sk_sp<SkImageFilter> blurFilter = SkImageFilters::Blur(
+ Blur::convertRadiusToSigma(dp(8)), Blur::convertRadiusToSigma(dp(8)),
+ SkTileMode::kClamp, nullptr, nullptr);
+ props.mutateLayerProperties().setBackdropImageFilter(blurFilter.get());
+ canvas.drawColor(0x33000000, SkBlendMode::kSrcOver);
+ });
+
+ canvas.drawRenderNode(blurNode.get());
+ }
+
+ void doFrame(int frameNr) override { listView->doFrame(frameNr); }
+};
+
+static TestScene::Registrar _BackdropBlur(TestScene::Info{
+ "backdropblur", "A rounded rect that does a blur-behind of a sky animation.",
+ [](const TestScene::Options& opts) -> test::TestScene* {
+ return new BackdropBlurAnimation(opts);
+ }});
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index ca54087..4b29100 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -1280,7 +1280,7 @@
canvas->drawDrawable(&backdropDrawable);
// the drawable is still visible, ok to draw.
EXPECT_EQ(2, canvas->mDrawCounter);
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH - 30, CANVAS_HEIGHT - 30), canvas->mDstBounds);
+ EXPECT_EQ(SkRect::MakeLTRB(30, 30, CANVAS_WIDTH, CANVAS_HEIGHT), canvas->mDstBounds);
canvas->translate(CANVAS_WIDTH, CANVAS_HEIGHT);
canvas->drawDrawable(&drawable);
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index b10019a..67d5774 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -29,6 +29,10 @@
libs: [
"androidx.annotation_annotation",
],
+ stub_only_libs: [
+ // Needed for javadoc references.
+ "framework-location.stubs.system",
+ ],
api_packages: [
"android.location",
"com.android.location.provider",
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 2d7db5e..8b04644 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -16,6 +16,9 @@
package android.media;
+import static com.android.media.flags.Flags.FLAG_UPDATE_CLIENT_PROFILE_PRIORITY;
+
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -970,6 +973,27 @@
registerClient(context, tvInputServiceSessionId, priorityHint);
}
+ /**
+ * Updates client priority with an arbitrary value along with a nice value.
+ *
+ * <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
+ * to reclaim insufficient resources from another client.
+ *
+ * <p>The nice value represents how much the client intends to give up the resource when an
+ * insufficient resource situation happens.
+ *
+ * @see <a
+ * href="https://source.android.com/docs/devices/tv/tuner-framework#priority-nice-value">
+ * Priority value and nice value</a>
+ * @param priority the new priority. Any negative value would cause no-op on priority setting
+ * and the API would only process nice value setting in that case.
+ * @param niceValue the nice value.
+ */
+ @FlaggedApi(FLAG_UPDATE_CLIENT_PROFILE_PRIORITY)
+ public boolean updateResourcePriority(int priority, int niceValue) {
+ return mTunerResourceManager.updateClientPriority(mClientId, priority, niceValue);
+ }
+
IHwBinder getBinder() {
if (mICas != null) {
return null; // Return IHwBinder only for HIDL
diff --git a/media/java/android/media/flags/media_better_together.aconfig b/media/java/android/media/flags/media_better_together.aconfig
index 7252135..1ef98f2 100644
--- a/media/java/android/media/flags/media_better_together.aconfig
+++ b/media/java/android/media/flags/media_better_together.aconfig
@@ -70,6 +70,13 @@
}
flag {
+ name: "update_client_profile_priority"
+ namespace: "media"
+ description : "Feature flag to add updateResourcePriority api to MediaCas"
+ bug: "300565729"
+}
+
+flag {
name: "enable_built_in_speaker_route_suitability_statuses"
is_exported: true
namespace: "media_solutions"
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
index 9164b64..a72ba8d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
@@ -212,13 +212,14 @@
public int getMaxInputGain() {
// TODO (b/357123335): use real input gain implementation.
- // Using 15 for now since it matches the max index for output.
- return 15;
+ // Using 100 for now since it matches the maximum input gain index in classic ChromeOS.
+ return 100;
}
public int getCurrentInputGain() {
// TODO (b/357123335): use real input gain implementation.
- return 8;
+ // Show a fixed full gain in UI before it really works per UX requirement.
+ return 100;
}
public boolean isInputGainFixed() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
index 16c0c1c..29cc403 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
@@ -255,12 +255,12 @@
@Test
public void getMaxInputGain_returnMaxInputGain() {
- assertThat(mInputRouteManager.getMaxInputGain()).isEqualTo(15);
+ assertThat(mInputRouteManager.getMaxInputGain()).isEqualTo(100);
}
@Test
public void getCurrentInputGain_returnCurrentInputGain() {
- assertThat(mInputRouteManager.getCurrentInputGain()).isEqualTo(8);
+ assertThat(mInputRouteManager.getCurrentInputGain()).isEqualTo(100);
}
@Test
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 408ed1e..456fedf 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -743,6 +743,12 @@
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
<uses-permission android:name="android.permission.MANAGE_SAFETY_CENTER" />
+ <!-- Permissions required for CTS test - CtsVirtualDevicesTestCases -->
+ <uses-permission android:name="android.permission.CREATE_VIRTUAL_DEVICE" />
+ <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" />
+ <uses-permission android:name="android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY" />
+
+
<!-- Permission required for CTS test - Notification test suite -->
<uses-permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL" />
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 26e6e71..a21a805 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1473,3 +1473,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "magic_portrait_wallpapers"
+ namespace: "systemui"
+ description: "Magic Portrait related changes in systemui"
+ bug: "370863642"
+}
+
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/activity/EdgeToEdgeActivitContent.kt b/packages/SystemUI/compose/core/src/com/android/compose/activity/EdgeToEdgeActivitContent.kt
deleted file mode 100644
index 97c8076..0000000
--- a/packages/SystemUI/compose/core/src/com/android/compose/activity/EdgeToEdgeActivitContent.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compose.activity
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.contentColorFor
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import com.android.compose.rememberSystemUiController
-import com.android.compose.theme.PlatformTheme
-
-/** Scaffolding for an edge-to-edge activity content. */
-@Composable
-fun EdgeToEdgeActivityContent(
- modifier: Modifier = Modifier,
- content: @Composable () -> Unit,
-) {
- // Make the status and navigation bars transparent, ensuring that the status bar icons are dark
- // when the theme is light and vice-versa.
- val systemUiController = rememberSystemUiController()
- val isDarkTheme = isSystemInDarkTheme()
- val useDarkIcons = !isDarkTheme
- DisposableEffect(systemUiController, useDarkIcons) {
- systemUiController.setSystemBarsColor(
- color = Color.Transparent,
- darkIcons = useDarkIcons,
- )
- onDispose {}
- }
-
- PlatformTheme(isDarkTheme) {
- val backgroundColor = MaterialTheme.colorScheme.background
- Box(modifier.fillMaxSize().background(backgroundColor)) {
- CompositionLocalProvider(LocalContentColor provides contentColorFor(backgroundColor)) {
- content()
- }
- }
- }
-}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index bf8f6ce..7dc2901 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -522,13 +522,7 @@
val currentSceneKey =
if (isSplitAroundTheFold) SceneKeys.SplitSceneKey else SceneKeys.ContiguousSceneKey
- val state = remember {
- MutableSceneTransitionLayoutState(
- currentSceneKey,
- SceneTransitions,
- enableInterruptions = false,
- )
- }
+ val state = remember { MutableSceneTransitionLayoutState(currentSceneKey, SceneTransitions) }
// Update state whenever currentSceneKey has changed.
LaunchedEffect(state, currentSceneKey) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
index e9c5c03..edc4cba 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
@@ -199,7 +199,7 @@
QuickSettingsTheme {
val context = LocalContext.current
- LaunchedEffect(key1 = context) {
+ LaunchedEffect(context) {
if (qsView == null) {
qsSceneAdapter.inflate(context)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 417f2b8..2d58c8c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -24,6 +24,7 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -31,6 +32,8 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalContext
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.compose.animation.scene.OverlayKey
@@ -39,9 +42,13 @@
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.observableTransitionState
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter
+import com.android.systemui.qs.ui.composable.QuickSettingsTheme
import com.android.systemui.ribbon.ui.composable.BottomRightCornerRibbon
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
+import javax.inject.Provider
import kotlinx.coroutines.flow.collectLatest
/**
@@ -73,6 +80,7 @@
overlayByKey: Map<OverlayKey, Overlay>,
initialSceneKey: SceneKey,
dataSourceDelegator: SceneDataSourceDelegator,
+ qsSceneAdapter: Provider<QSSceneAdapter>,
modifier: Modifier = Modifier,
) {
val coroutineScope = rememberCoroutineScope()
@@ -118,6 +126,24 @@
}
}
+ // Inflate qsView here so that shade has the correct qqs height in the first measure pass after
+ // rebooting
+ if (
+ viewModel.allContentKeys.contains(Scenes.QuickSettings) ||
+ viewModel.allContentKeys.contains(Scenes.Shade)
+ ) {
+ val qsAdapter = qsSceneAdapter.get()
+ QuickSettingsTheme {
+ val context = LocalContext.current
+ val qsView by qsAdapter.qsView.collectAsStateWithLifecycle()
+ LaunchedEffect(context) {
+ if (qsView == null) {
+ qsAdapter.inflate(context)
+ }
+ }
+ }
+ }
+
Box(
modifier =
Modifier.fillMaxSize().pointerInput(Unit) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 2e8fc14..2657d7c 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -234,7 +234,6 @@
canHideOverlay: (OverlayKey) -> Boolean = { true },
canReplaceOverlay: (from: OverlayKey, to: OverlayKey) -> Boolean = { _, _ -> true },
stateLinks: List<StateLink> = emptyList(),
- enableInterruptions: Boolean = DEFAULT_INTERRUPTIONS_ENABLED,
): MutableSceneTransitionLayoutState {
return MutableSceneTransitionLayoutStateImpl(
initialScene,
@@ -245,7 +244,6 @@
canHideOverlay,
canReplaceOverlay,
stateLinks,
- enableInterruptions,
)
}
@@ -261,9 +259,6 @@
true
},
private val stateLinks: List<StateLink> = emptyList(),
-
- // TODO(b/290930950): Remove this flag.
- internal val enableInterruptions: Boolean = DEFAULT_INTERRUPTIONS_ENABLED,
) : MutableSceneTransitionLayoutState {
private val creationThread: Thread = Thread.currentThread()
@@ -406,13 +401,6 @@
transition.updateOverscrollSpecs(fromSpec = null, toSpec = null)
}
- if (!enableInterruptions) {
- // Set the current transition.
- check(transitionStates.size == 1)
- transitionStates = listOf(transition)
- return
- }
-
when (val currentState = transitionStates.last()) {
is TransitionState.Idle -> {
// Replace [Idle] by [transition].
@@ -755,9 +743,6 @@
private const val TAG = "SceneTransitionLayoutState"
-/** Whether support for interruptions in enabled by default. */
-internal const val DEFAULT_INTERRUPTIONS_ENABLED = true
-
/**
* The max number of concurrent transitions. If the number of transitions goes past this number,
* this probably means that there is a leak and we will Log.wtf before clearing the list of
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
index d6751ae..9d3f25e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -337,10 +337,6 @@
}
internal open fun interruptionProgress(layoutImpl: SceneTransitionLayoutImpl): Float {
- if (!layoutImpl.state.enableInterruptions) {
- return 0f
- }
-
if (replacedTransition != null) {
return replacedTransition.interruptionProgress(layoutImpl)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 1eed54e..a2c2729 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -213,10 +213,6 @@
from(SceneA, to = SceneB) { spec = tween }
from(SceneB, to = SceneC) { spec = tween }
},
-
- // Disable interruptions so that the current transition is directly removed
- // when starting a new one.
- enableInterruptions = false,
)
}
@@ -243,7 +239,12 @@
onElement(TestElements.Bar).assertExists()
// Start transition from SceneB to SceneC
- rule.runOnUiThread { state.setTargetScene(SceneC, coroutineScope) }
+ rule.runOnUiThread {
+ // We snap to scene B so that the transition A => B is removed from the list of
+ // transitions.
+ state.snapToScene(SceneB)
+ state.setTargetScene(SceneC, coroutineScope)
+ }
}
at(3 * frameDuration) { onElement(TestElements.Bar).assertIsNotDisplayed() }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 400f0b3..b00b894b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -85,15 +85,9 @@
/** The content under test. */
@Composable
- private fun TestContent(enableInterruptions: Boolean = true) {
+ private fun TestContent() {
coroutineScope = rememberCoroutineScope()
- layoutState = remember {
- MutableSceneTransitionLayoutState(
- SceneA,
- EmptyTestTransitions,
- enableInterruptions = enableInterruptions,
- )
- }
+ layoutState = remember { MutableSceneTransitionLayoutState(SceneA, EmptyTestTransitions) }
SceneTransitionLayout(state = layoutState, modifier = Modifier.size(LayoutSize)) {
scene(SceneA, userActions = mapOf(Back to SceneB)) {
@@ -205,7 +199,7 @@
@Test
fun testSharedElement() {
- rule.setContent { TestContent(enableInterruptions = false) }
+ rule.setContent { TestContent() }
// In scene A, the shared element SharedFoo() is at the top end of the layout and has a size
// of 50.dp.
@@ -253,6 +247,9 @@
.isWithin(DpOffsetSubject.DefaultTolerance)
.of(DpOffset(25.dp, 25.dp))
+ // Finish the transition.
+ rule.mainClock.advanceTimeBy(TestTransitionDuration / 2)
+
// Animate to scene C, let the animation start then go to the middle of the transition.
currentScene = SceneC
rule.mainClock.advanceTimeByFrame()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/TileLayoutTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/TileLayoutTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/model/ScreenRecordModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/model/ScreenRecordModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/model/ScreenRecordModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/model/ScreenRecordModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/AnnouncementResolverTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/AnnouncementResolverTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/AnnouncementResolverTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/AnnouncementResolverTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeImageCapture.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeImageCapture.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeImageCapture.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeImageCapture.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RecyclerViewActivity.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/RecyclerViewActivity.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/RecyclerViewActivity.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/RecyclerViewActivity.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/TestUserIds.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/TestUserIds.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/TestUserIds.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/TestUserIds.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureFrameworkSmokeTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureFrameworkSmokeTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureFrameworkSmokeTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollCaptureFrameworkSmokeTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollViewActivity.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollViewActivity.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollViewActivity.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/scroll/ScrollViewActivity.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/scrim/ScrimViewTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/scrim/ScrimViewTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ConstraintChangeTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ConstraintChangeTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ConstraintChangesTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ConstraintChangesTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/FakeCondition.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/QuickStepContractTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationListenerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationListenerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilderTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/core/CommandQueueInitializerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/CommandQueueInitializerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/core/CommandQueueInitializerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/CommandQueueInitializerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/SectionStyleProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/SectionStyleProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/SectionStyleProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/SectionStyleProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DreamCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DreamCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DreamCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/DreamCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/listbuilder/SemiStableSortTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/listbuilder/SemiStableSortTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/listbuilder/SemiStableSortTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/listbuilder/SemiStableSortTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelperTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelperTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelperTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLoggerFake.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLoggerFake.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLoggerFake.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLoggerFake.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProviderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProviderImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProviderImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/HeadsUpStyleProviderImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifRemoteViewCacheImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifRemoteViewCacheImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifRemoteViewCacheImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotifRemoteViewCacheImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/NotificationViewFlipperViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/NotificationViewFlipperViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/NotificationViewFlipperViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/NotificationViewFlipperViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLoggerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLoggerViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLoggerViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLoggerViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/IconManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/IconManagerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/IconManagerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/IconManagerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModelParameterizedTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModelParameterizedTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModelParameterizedTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModelParameterizedTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
index 5036e77..46f822a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
@@ -21,6 +21,7 @@
import android.app.StatusBarManager.DISABLE_NONE
import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -31,8 +32,10 @@
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith;
@SmallTest
+@RunWith(AndroidJUnit4::class)
class CollapsedStatusBarInteractorTest : SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewBinder.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BlockingQueueIntentReceiver.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BlockingQueueIntentReceiver.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BlockingQueueIntentReceiver.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BlockingQueueIntentReceiver.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
similarity index 99%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index 2588f1f..e3bd885 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -61,7 +61,7 @@
import java.util.List;
import java.util.concurrent.Executor;
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
@RunWithLooper
@SmallTest
public class BluetoothControllerImplTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ClockTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ClockTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/FakeBluetoothRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/bluetooth/FakeBluetoothRepository.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/FakeBluetoothRepository.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/bluetooth/FakeBluetoothRepository.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt
index 0c27e58..c7c7fdc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt
@@ -21,6 +21,7 @@
import android.app.StatusBarManager.WINDOW_STATE_HIDING
import android.app.StatusBarManager.WINDOW_STATE_SHOWING
import android.app.StatusBarManager.WINDOW_STATUS_BAR
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -34,11 +35,13 @@
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mockito.verify
import org.mockito.kotlin.argumentCaptor
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
class StatusBarWindowStatePerDisplayRepositoryTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt
index b6a3f36..e23e88c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt
@@ -19,6 +19,7 @@
import android.app.StatusBarManager.WINDOW_STATE_HIDDEN
import android.app.StatusBarManager.WINDOW_STATE_SHOWING
import android.app.StatusBarManager.WINDOW_STATUS_BAR
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -33,12 +34,14 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith
import org.mockito.Mockito.verify
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.reset
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
class StatusBarWindowStateRepositoryStoreTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/CreateUserActivityTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/CreateUserActivityTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/UserCreatorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/UserCreatorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/NotificationChannelsTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/NotificationChannelsTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/LeakDetectorTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/LeakDetectorTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/CsdWarningDialogTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/CsdWarningDialogTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTestKt.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTestKt.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTestKt.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTestKt.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
index fe5024f..59676ce 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
@@ -17,10 +17,17 @@
package com.android.systemui.wallpapers.data.repository
import android.app.WallpaperInfo
+import android.view.View
import kotlinx.coroutines.flow.MutableStateFlow
/** Fake implementation of the wallpaper repository. */
class FakeWallpaperRepository : WallpaperRepository {
override val wallpaperInfo = MutableStateFlow<WallpaperInfo?>(null)
override val wallpaperSupportsAmbientMode = MutableStateFlow(false)
+ override var rootView: View? = null
+ private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ _notificationStackAbsoluteBottom.value = bottom
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTestActivity.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/BubblesTestActivity.java
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTestActivity.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/BubblesTestActivity.java
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8e01e04..431f048 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -315,6 +315,7 @@
};
private final FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig;
+ private final Object mSimDataLockObject = new Object();
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
HashMap<Integer, ServiceState> mServiceStates = new HashMap<>();
@@ -610,14 +611,26 @@
// It is possible for active subscriptions to become invalid (-1), and these will not be
// present in the subscriptionInfo list
- Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<Integer, SimData> simData = iter.next();
- if (!activeSubIds.contains(simData.getKey())) {
- mSimLogger.logInvalidSubId(simData.getKey());
- iter.remove();
+ synchronized (mSimDataLockObject) {
+ Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<Integer, SimData> simData = iter.next();
+ if (!activeSubIds.contains(simData.getKey())) {
+ mSimLogger.logInvalidSubId(simData.getKey());
+ iter.remove();
- SimData data = simData.getValue();
+ SimData data = simData.getValue();
+ for (int j = 0; j < mCallbacks.size(); j++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
+ if (cb != null) {
+ cb.onSimStateChanged(data.subId, data.slotId, data.simState);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < changedSubscriptions.size(); i++) {
+ SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
for (int j = 0; j < mCallbacks.size(); j++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
if (cb != null) {
@@ -625,18 +638,8 @@
}
}
}
+ callbacksRefreshCarrierInfo();
}
-
- for (int i = 0; i < changedSubscriptions.size(); i++) {
- SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
- for (int j = 0; j < mCallbacks.size(); j++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
- if (cb != null) {
- cb.onSimStateChanged(data.subId, data.slotId, data.simState);
- }
- }
- }
- callbacksRefreshCarrierInfo();
}
private void handleAirplaneModeChanged() {
@@ -3376,12 +3379,15 @@
* Removes all valid subscription info from the map for the given slotId.
*/
private void invalidateSlot(int slotId) {
- Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
- while (iter.hasNext()) {
- SimData data = iter.next().getValue();
- if (data.slotId == slotId && SubscriptionManager.isValidSubscriptionId(data.subId)) {
- mSimLogger.logInvalidSubId(data.subId);
- iter.remove();
+ synchronized (mSimDataLockObject) {
+ Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
+ while (iter.hasNext()) {
+ SimData data = iter.next().getValue();
+ if (data.slotId == slotId
+ && SubscriptionManager.isValidSubscriptionId(data.subId)) {
+ mSimLogger.logInvalidSubId(data.subId);
+ iter.remove();
+ }
}
}
}
@@ -3408,23 +3414,25 @@
}
// TODO(b/327476182): Preserve SIM_STATE_CARD_IO_ERROR sims in a separate data source.
- SimData data = mSimDatas.get(subId);
- final boolean changed;
- if (data == null) {
- data = new SimData(state, slotId, subId);
- mSimDatas.put(subId, data);
- changed = true; // no data yet; force update
- } else {
- changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
- data.simState = state;
- data.subId = subId;
- data.slotId = slotId;
- }
- if ((changed || becameAbsent)) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onSimStateChanged(subId, slotId, state);
+ synchronized (mSimDataLockObject) {
+ SimData data = mSimDatas.get(subId);
+ final boolean changed;
+ if (data == null) {
+ data = new SimData(state, slotId, subId);
+ mSimDatas.put(subId, data);
+ changed = true; // no data yet; force update
+ } else {
+ changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
+ data.simState = state;
+ data.subId = subId;
+ data.slotId = slotId;
+ }
+ if ((changed || becameAbsent)) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onSimStateChanged(subId, slotId, state);
+ }
}
}
}
@@ -3684,9 +3692,11 @@
callback.onKeyguardVisibilityChanged(isKeyguardVisible());
callback.onTelephonyCapable(mTelephonyCapable);
- for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
- final SimData state = data.getValue();
- callback.onSimStateChanged(state.subId, state.slotId, state.simState);
+ synchronized (mSimDataLockObject) {
+ for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
+ final SimData state = data.getValue();
+ callback.onSimStateChanged(state.subId, state.slotId, state.simState);
+ }
}
}
@@ -3823,19 +3833,23 @@
}
public int getSimState(int subId) {
- if (mSimDatas.containsKey(subId)) {
- return mSimDatas.get(subId).simState;
- } else {
- return TelephonyManager.SIM_STATE_UNKNOWN;
+ synchronized (mSimDataLockObject) {
+ if (mSimDatas.containsKey(subId)) {
+ return mSimDatas.get(subId).simState;
+ } else {
+ return TelephonyManager.SIM_STATE_UNKNOWN;
+ }
}
}
private int getSlotId(int subId) {
- if (!mSimDatas.containsKey(subId)) {
- refreshSimState(subId, SubscriptionManager.getSlotIndex(subId));
+ synchronized (mSimDataLockObject) {
+ if (!mSimDatas.containsKey(subId)) {
+ refreshSimState(subId, SubscriptionManager.getSlotIndex(subId));
+ }
+ SimData simData = mSimDatas.get(subId);
+ return simData != null ? simData.slotId : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- SimData simData = mSimDatas.get(subId);
- return simData != null ? simData.slotId : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@@ -3876,22 +3890,24 @@
*/
private boolean refreshSimState(int subId, int slotId) {
int state = mTelephonyManager.getSimState(slotId);
- SimData data = mSimDatas.get(subId);
+ synchronized (mSimDataLockObject) {
+ SimData data = mSimDatas.get(subId);
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- invalidateSlot(slotId);
- }
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ invalidateSlot(slotId);
+ }
- final boolean changed;
- if (data == null) {
- data = new SimData(state, slotId, subId);
- mSimDatas.put(subId, data);
- changed = true; // no data yet; force update
- } else {
- changed = data.simState != state;
- data.simState = state;
+ final boolean changed;
+ if (data == null) {
+ data = new SimData(state, slotId, subId);
+ mSimDatas.put(subId, data);
+ changed = true; // no data yet; force update
+ } else {
+ changed = data.simState != state;
+ data.simState = state;
+ }
+ return changed;
}
- return changed;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
index ec52055..95d1b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
@@ -68,11 +68,16 @@
val previewClock: Flow<ClockController>
+ /** top of notifications without bcsmartspace in small clock settings */
+ val notificationDefaultTop: StateFlow<Float>
+
val clockEventController: ClockEventController
val shouldForceSmallClock: Boolean
fun setClockSize(size: ClockSize)
+
+ fun setNotificationDefaultTop(top: Float)
}
@SysUISingleton
@@ -108,7 +113,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = getClockSize()
+ initialValue = getClockSize(),
)
override val currentClockId: Flow<ClockId> =
@@ -138,7 +143,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = clockRegistry.createCurrentClock()
+ initialValue = clockRegistry.createCurrentClock(),
)
override val previewClock: Flow<ClockController> =
@@ -149,6 +154,14 @@
clockRegistry.createCurrentClock()
}
+ private val _notificationDefaultTop: MutableStateFlow<Float> = MutableStateFlow(0F)
+
+ override val notificationDefaultTop: StateFlow<Float> = _notificationDefaultTop.asStateFlow()
+
+ override fun setNotificationDefaultTop(top: Float) {
+ _notificationDefaultTop.value = top
+ }
+
override val shouldForceSmallClock: Boolean
get() =
featureFlags.isEnabled(Flags.LOCKSCREEN_ENABLE_LANDSCAPE) &&
@@ -160,7 +173,7 @@
secureSettings.getIntForUser(
Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
/* defaultValue= */ 1,
- UserHandle.USER_CURRENT
+ UserHandle.USER_CURRENT,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 130242f..8210174 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -269,6 +269,9 @@
*/
val isEncryptedOrLockdown: Flow<Boolean>
+ /** The top of shortcut in screen, used by wallpaper to find remaining space in lockscreen */
+ val shortcutAbsoluteTop: StateFlow<Float>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -339,6 +342,8 @@
* otherwise.
*/
fun isShowKeyguardWhenReenabled(): Boolean
+
+ fun setShortcutAbsoluteTop(top: Float)
}
/** Encapsulates application state for the keyguard. */
@@ -503,7 +508,7 @@
trySendWithFailureLogging(
statusBarStateController.dozeAmount,
TAG,
- "initial dozeAmount"
+ "initial dozeAmount",
)
awaitClose { statusBarStateController.removeCallback(callback) }
@@ -521,7 +526,7 @@
object : DozeTransitionCallback {
override fun onDozeTransition(
oldState: DozeMachine.State,
- newState: DozeMachine.State
+ newState: DozeMachine.State,
) {
trySendWithFailureLogging(
DozeTransitionModel(
@@ -529,7 +534,7 @@
to = dozeMachineStateToModel(newState),
),
TAG,
- "doze transition model"
+ "doze transition model",
)
}
}
@@ -541,7 +546,7 @@
to = dozeMachineStateToModel(dozeTransitionListener.newState),
),
TAG,
- "initial doze transition model"
+ "initial doze transition model",
)
awaitClose { dozeTransitionListener.removeCallback(callback) }
@@ -579,7 +584,7 @@
trySendWithFailureLogging(
statusBarStateIntToObject(state),
TAG,
- "state"
+ "state",
)
}
}
@@ -590,7 +595,7 @@
.stateIn(
scope,
SharingStarted.Eagerly,
- statusBarStateIntToObject(statusBarStateController.state)
+ statusBarStateIntToObject(statusBarStateController.state),
)
private val _biometricUnlockState: MutableStateFlow<BiometricUnlockModel> =
@@ -610,7 +615,7 @@
trySendWithFailureLogging(
authController.fingerprintSensorLocation,
TAG,
- "AuthController.Callback#onFingerprintLocationChanged"
+ "AuthController.Callback#onFingerprintLocationChanged",
)
}
@@ -635,6 +640,9 @@
private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
override val isActiveDreamLockscreenHosted = _isActiveDreamLockscreenHosted.asStateFlow()
+ private val _shortcutAbsoluteTop = MutableStateFlow(0F)
+ override val shortcutAbsoluteTop = _shortcutAbsoluteTop.asStateFlow()
+
init {
val callback =
object : KeyguardStateController.Callback {
@@ -721,6 +729,10 @@
}
}
+ override fun setShortcutAbsoluteTop(top: Float) {
+ _shortcutAbsoluteTop.value = top
+ }
+
private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
return when (state) {
DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index c0049d4..5b7eedd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -94,7 +94,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = ClockSize.LARGE
+ initialValue = ClockSize.LARGE,
)
} else {
keyguardClockRepository.clockSize
@@ -152,4 +152,8 @@
clock.largeClock.animations.fold(foldFraction)
}
}
+
+ fun setNotificationStackDefaultTop(top: Float) {
+ keyguardClockRepository.setNotificationDefaultTop(top)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index e6ee112..d7f96b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -526,6 +526,10 @@
repository.showDismissibleKeyguard()
}
+ fun setShortcutAbsoluteTop(top: Float) {
+ repository.setShortcutAbsoluteTop(top)
+ }
+
companion object {
private const val TAG = "KeyguardInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index a1c963b..d745522 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -44,6 +44,7 @@
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceLayout
import com.android.systemui.res.R
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shared.R as sharedR
import com.android.systemui.util.ui.value
import dagger.Lazy
@@ -53,6 +54,9 @@
internal fun ConstraintSet.setVisibility(views: Iterable<View>, visibility: Int) =
views.forEach { view -> this.setVisibility(view.id, visibility) }
+internal fun ConstraintSet.setAlpha(views: Iterable<View>, alpha: Float) =
+ views.forEach { view -> this.setAlpha(view.id, alpha) }
+
internal fun ConstraintSet.setScaleX(views: Iterable<View>, scaleX: Float) =
views.forEach { view -> this.setScaleX(view.id, scaleX) }
@@ -70,6 +74,7 @@
val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
private val rootViewModel: KeyguardRootViewModel,
private val aodBurnInViewModel: AodBurnInViewModel,
+ private val largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
) : KeyguardSection() {
private var disposableHandle: DisposableHandle? = null
@@ -123,6 +128,8 @@
return constraintSet.apply {
setVisibility(getTargetClockFace(clock).views, VISIBLE)
setVisibility(getNonTargetClockFace(clock).views, GONE)
+ setAlpha(getTargetClockFace(clock).views, 1F)
+ setAlpha(getNonTargetClockFace(clock).views, 0F)
if (!keyguardClockViewModel.isLargeClockVisible.value) {
connect(sharedR.id.bc_smartspace_view, TOP, sharedR.id.date_smartspace_view, BOTTOM)
} else {
@@ -172,7 +179,7 @@
}
}
- open fun applyDefaultConstraints(constraints: ConstraintSet) {
+ fun applyDefaultConstraints(constraints: ConstraintSet) {
val guideline =
if (keyguardClockViewModel.clockShouldBeCentered.value) PARENT_ID
else R.id.split_shade_guideline
@@ -211,6 +218,28 @@
// Explicitly clear pivot to force recalculate pivot instead of using legacy value
setTransformPivot(R.id.lockscreen_clock_view_large, Float.NaN, Float.NaN)
+
+ val smallClockBottom =
+ keyguardClockViewModel.getSmallClockTopMargin() +
+ context.resources.getDimensionPixelSize(
+ com.android.systemui.customization.R.dimen.small_clock_height
+ )
+ val dateWeatherSmartspaceHeight = getDimen(context, DATE_WEATHER_VIEW_HEIGHT).toFloat()
+ val marginBetweenSmartspaceAndNotification =
+ context.resources.getDimensionPixelSize(
+ R.dimen.keyguard_status_view_bottom_margin
+ ) +
+ if (context.resources.getBoolean(R.bool.config_use_large_screen_shade_header)) {
+ largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ } else {
+ 0
+ }
+
+ clockInteractor.setNotificationStackDefaultTop(
+ smallClockBottom +
+ dateWeatherSmartspaceHeight +
+ marginBetweenSmartspaceAndNotification
+ )
}
constrainWeatherClockDateIconsBarrier(constraints)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 6c6e14c..d3895de 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -30,6 +30,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
@@ -52,6 +53,7 @@
private val indicationController: KeyguardIndicationController,
private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
private val keyguardQuickAffordanceViewBinder: KeyguardQuickAffordanceViewBinder,
+ private val keyguardInteractor: KeyguardInteractor,
) : BaseShortcutSection() {
// Amount to increase the bottom margin by to avoid colliding with inset
@@ -117,7 +119,7 @@
BOTTOM,
PARENT_ID,
BOTTOM,
- verticalOffsetMargin + safeInsetBottom
+ verticalOffsetMargin + safeInsetBottom,
)
constrainWidth(R.id.end_button, width)
@@ -128,7 +130,7 @@
BOTTOM,
PARENT_ID,
BOTTOM,
- verticalOffsetMargin + safeInsetBottom
+ verticalOffsetMargin + safeInsetBottom,
)
// The constraint set visibility for start and end button are default visible, set to
@@ -136,5 +138,13 @@
setVisibilityMode(R.id.start_button, VISIBILITY_MODE_IGNORE)
setVisibilityMode(R.id.end_button, VISIBILITY_MODE_IGNORE)
}
+
+ val shortcutAbsoluteTopInScreen =
+ (resources.displayMetrics.heightPixels -
+ (verticalOffsetMargin + safeInsetBottom) -
+ height)
+ .toFloat()
+
+ keyguardInteractor.setShortcutAbsoluteTop(shortcutAbsoluteTopInScreen)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 1511f31..fa987dd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -255,7 +255,8 @@
* @return size in pixels of QQS
*/
public int getQqsHeight() {
- return mHeader.getHeight();
+ SceneContainerFlag.assertInNewMode();
+ return mHeader.getMeasuredHeight();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index 8a2e274..cd38ca6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -6,6 +6,7 @@
import android.view.View
import android.view.WindowInsets
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.scene.ui.composable.Overlay
@@ -13,19 +14,13 @@
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.shade.TouchLogger
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
+import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
/** A root view of the main SysUI window that supports scenes. */
@ExperimentalCoroutinesApi
-class SceneWindowRootView(
- context: Context,
- attrs: AttributeSet?,
-) :
- WindowRootView(
- context,
- attrs,
- ) {
+class SceneWindowRootView(context: Context, attrs: AttributeSet?) : WindowRootView(context, attrs) {
private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null
// TODO(b/298525212): remove once Compose exposes window inset bounds.
@@ -39,6 +34,7 @@
overlays: Set<Overlay>,
layoutInsetController: LayoutInsetsController,
sceneDataSourceDelegator: SceneDataSourceDelegator,
+ qsSceneAdapter: Provider<QSSceneAdapter>,
alternateBouncerDependencies: AlternateBouncerDependencies,
) {
setLayoutInsetsController(layoutInsetController)
@@ -57,6 +53,7 @@
super.setVisibility(if (isVisible) View.VISIBLE else View.INVISIBLE)
},
dataSourceDelegator = sceneDataSourceDelegator,
+ qsSceneAdapter = qsSceneAdapter,
alternateBouncerDependencies = alternateBouncerDependencies,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 38f4e73..1e3a233 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -42,6 +42,7 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.setSnapshotBinding
import com.android.systemui.lifecycle.viewModel
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.SceneContainerConfig
@@ -51,6 +52,7 @@
import com.android.systemui.scene.ui.composable.SceneContainer
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
+import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
@@ -74,6 +76,7 @@
overlays: Set<Overlay>,
onVisibilityChangedInternal: (isVisible: Boolean) -> Unit,
dataSourceDelegator: SceneDataSourceDelegator,
+ qsSceneAdapter: Provider<QSSceneAdapter>,
alternateBouncerDependencies: AlternateBouncerDependencies,
) {
val unsortedSceneByKey: Map<SceneKey, Scene> = scenes.associateBy { scene -> scene.key }
@@ -132,6 +135,7 @@
sceneByKey = sortedSceneByKey,
overlayByKey = sortedOverlayByKey,
dataSourceDelegator = dataSourceDelegator,
+ qsSceneAdapter = qsSceneAdapter,
containerConfig = containerConfig,
)
.also { it.id = R.id.scene_container_root_composable }
@@ -177,6 +181,7 @@
sceneByKey: Map<SceneKey, Scene>,
overlayByKey: Map<OverlayKey, Overlay>,
dataSourceDelegator: SceneDataSourceDelegator,
+ qsSceneAdapter: Provider<QSSceneAdapter>,
containerConfig: SceneContainerConfig,
): View {
return ComposeView(context).apply {
@@ -192,6 +197,7 @@
overlayByKey = overlayByKey,
initialSceneKey = containerConfig.initialSceneKey,
dataSourceDelegator = dataSourceDelegator,
+ qsSceneAdapter = qsSceneAdapter,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 889380a..ce942fe 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -73,6 +73,8 @@
/** Whether the container is visible. */
val isVisible: Boolean by hydrator.hydratedStateOf("isVisible", sceneInteractor.isVisible)
+ val allContentKeys: List<ContentKey> = sceneInteractor.allContentKeys
+
private val hapticsViewModel = hapticsViewModelFactory.create(view)
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
index 63ced5d..acfcd13 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
@@ -641,7 +641,7 @@
private void saveScreenshotInBackground(ScreenshotData screenshot, UUID requestId,
Consumer<Uri> finisher, Consumer<ImageExporter.Result> onResult) {
ListenableFuture<ImageExporter.Result> future = mImageExporter.export(mBgExecutor,
- requestId, screenshot.getBitmap(), screenshot.getUserOrDefault(),
+ requestId, screenshot.getBitmap(), screenshot.getUserHandle(),
mDisplay.getDisplayId());
future.addListener(() -> {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
index c390e71..b5b15a9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
@@ -4,7 +4,6 @@
import android.graphics.Bitmap
import android.graphics.Insets
import android.graphics.Rect
-import android.os.Process
import android.os.UserHandle
import android.view.Display
import android.view.WindowManager
@@ -30,10 +29,6 @@
val packageNameString
get() = topComponent?.packageName ?: ""
- fun getUserOrDefault(): UserHandle {
- return userHandle ?: Process.myUserHandle()
- }
-
companion object {
@JvmStatic
fun fromRequest(request: ScreenshotRequest, displayId: Int = Display.DEFAULT_DISPLAY) =
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index fc8a593..5afc539 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -35,6 +35,7 @@
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.SceneContainerConfig
@@ -89,6 +90,7 @@
overlaysProvider: Provider<Set<@JvmSuppressWildcards Overlay>>,
layoutInsetController: NotificationInsetsController,
sceneDataSourceDelegator: Provider<SceneDataSourceDelegator>,
+ qsSceneAdapter: Provider<QSSceneAdapter>,
alternateBouncerDependencies: Provider<AlternateBouncerDependencies>,
): WindowRootView {
return if (SceneContainerFlag.isEnabled) {
@@ -104,6 +106,7 @@
overlays = overlaysProvider.get(),
layoutInsetController = layoutInsetController,
sceneDataSourceDelegator = sceneDataSourceDelegator.get(),
+ qsSceneAdapter = qsSceneAdapter,
alternateBouncerDependencies = alternateBouncerDependencies.get(),
)
sceneWindowRootView
@@ -119,9 +122,7 @@
// {@link NotificationShadeWindowViewController} can inject this view.
@Provides
@SysUISingleton
- fun providesNotificationShadeWindowView(
- root: WindowRootView,
- ): NotificationShadeWindowView {
+ fun providesNotificationShadeWindowView(root: WindowRootView): NotificationShadeWindowView {
if (SceneContainerFlag.isEnabled) {
return root.requireViewById(R.id.legacy_window_root)
}
@@ -133,7 +134,7 @@
@Provides
@SysUISingleton
fun providesNotificationStackScrollLayout(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): NotificationStackScrollLayout {
return notificationShadeWindowView.requireViewById(R.id.notification_stack_scroller)
}
@@ -142,7 +143,7 @@
@Provides
@SysUISingleton
fun providesNotificationPanelView(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): NotificationPanelView {
return notificationShadeWindowView.requireViewById(R.id.notification_panel)
}
@@ -178,7 +179,7 @@
@Provides
@SysUISingleton
fun providesKeyguardRootView(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): KeyguardRootView {
return notificationShadeWindowView.requireViewById(R.id.keyguard_root_view)
}
@@ -186,7 +187,7 @@
@Provides
@SysUISingleton
fun providesSharedNotificationContainer(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): SharedNotificationContainer {
return notificationShadeWindowView.requireViewById(R.id.shared_notification_container)
}
@@ -195,7 +196,7 @@
@Provides
@SysUISingleton
fun providesAuthRippleView(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): AuthRippleView? {
return notificationShadeWindowView.requireViewById(R.id.auth_ripple)
}
@@ -203,9 +204,7 @@
// TODO(b/277762009): Only allow this view's controller to inject the view. See above.
@Provides
@SysUISingleton
- fun providesTapAgainView(
- notificationPanelView: NotificationPanelView,
- ): TapAgainView {
+ fun providesTapAgainView(notificationPanelView: NotificationPanelView): TapAgainView {
return notificationPanelView.requireViewById(R.id.shade_falsing_tap_again)
}
@@ -213,7 +212,7 @@
@Provides
@SysUISingleton
fun providesNotificationsQuickSettingsContainer(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): NotificationsQuickSettingsContainer {
return notificationShadeWindowView.requireViewById(R.id.notification_container_parent)
}
@@ -223,7 +222,7 @@
@SysUISingleton
@Named(SHADE_HEADER)
fun providesShadeHeaderView(
- notificationShadeWindowView: NotificationShadeWindowView,
+ notificationShadeWindowView: NotificationShadeWindowView
): MotionLayout {
val stub = notificationShadeWindowView.requireViewById<ViewStub>(R.id.qs_header_stub)
val layoutId = R.layout.combined_qs_header
@@ -275,7 +274,7 @@
@SysUISingleton
@Named(SHADE_HEADER)
fun providesOngoingPrivacyChip(
- @Named(SHADE_HEADER) header: MotionLayout,
+ @Named(SHADE_HEADER) header: MotionLayout
): OngoingPrivacyChip {
return header.requireViewById(R.id.privacy_chip)
}
@@ -284,7 +283,7 @@
@SysUISingleton
@Named(SHADE_HEADER)
fun providesStatusIconContainer(
- @Named(SHADE_HEADER) header: MotionLayout,
+ @Named(SHADE_HEADER) header: MotionLayout
): StatusIconContainer {
return header.requireViewById(R.id.statusIcons)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 2c6b09c..adb3352 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -3884,6 +3884,7 @@
}
showingLayout.dump(pw, args);
dumpCustomOutline(pw, args);
+ dumpClipping(pw, args);
if (getViewState() != null) {
getViewState().dump(pw, args);
pw.println();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index afda426..ef6cad1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -856,17 +856,23 @@
pw.println();
}
if (DUMP_VERBOSE) {
- pw.println("mInRemovalAnimation: " + mInRemovalAnimation);
- pw.println("mClipTopAmount: " + mClipTopAmount);
- pw.println("mClipBottomAmount " + mClipBottomAmount);
- pw.println("mClipToActualHeight: " + mClipToActualHeight);
- pw.println("mExtraWidthForClipping: " + mExtraWidthForClipping);
- pw.println("mMinimumHeightForClipping: " + mMinimumHeightForClipping);
- pw.println("getClipBounds(): " + getClipBounds());
+ dumpClipping(pw, args);
}
});
}
+ protected void dumpClipping(IndentingPrintWriter pw, String[] args) {
+ pw.print("Clipping: ");
+ pw.print("mInRemovalAnimation", mInRemovalAnimation);
+ pw.print("mClipTopAmount", mClipTopAmount);
+ pw.print("mClipBottomAmount", mClipBottomAmount);
+ pw.print("mClipToActualHeight", mClipToActualHeight);
+ pw.print("mExtraWidthForClipping", mExtraWidthForClipping);
+ pw.print("mMinimumHeightForClipping", mMinimumHeightForClipping);
+ pw.print("getClipBounds()", getClipBounds());
+ pw.println();
+ }
+
/**
* return the amount that the content is translated
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 8ae6b79..d828a67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -130,6 +130,7 @@
import com.android.systemui.util.ColorUtilKt;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.ListenerSet;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import com.google.errorprone.annotations.CompileTimeConstant;
@@ -628,6 +629,9 @@
@Nullable
private OnClickListener mManageButtonClickListener;
+ @Nullable
+ private WallpaperInteractor mWallpaperInteractor;
+
public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -1192,6 +1196,7 @@
if (!SceneContainerFlag.isEnabled()) {
setMaxLayoutHeight(getHeight());
updateContentHeight();
+ mWallpaperInteractor.setNotificationStackAbsoluteBottom(mContentHeight);
}
clampScrollPosition();
requestChildrenUpdate();
@@ -1253,6 +1258,7 @@
if (mAmbientState.getStackTop() != stackTop) {
mAmbientState.setStackTop(stackTop);
onTopPaddingChanged(/* animate = */ isAddOrRemoveAnimationPending());
+ mWallpaperInteractor.setNotificationStackAbsoluteBottom((int) stackTop);
}
}
@@ -5898,6 +5904,10 @@
mController.getNotificationRoundnessManager().setAnimatedChildren(mChildrenToAddAnimated);
}
+ public void setWallpaperInteractor(WallpaperInteractor wallpaperInteractor) {
+ mWallpaperInteractor = wallpaperInteractor;
+ }
+
void addSwipedOutView(View v) {
mSwipedOutViews.add(v);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 7b02d0c..00c5c40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -145,6 +145,7 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Compile;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -226,6 +227,8 @@
private final SensitiveNotificationProtectionController
mSensitiveNotificationProtectionController;
+ private final WallpaperInteractor mWallpaperInteractor;
+
private View mLongPressedView;
private final NotificationListContainerImpl mNotificationListContainer =
@@ -756,7 +759,8 @@
NotificationDismissibilityProvider dismissibilityProvider,
ActivityStarter activityStarter,
SplitShadeStateController splitShadeStateController,
- SensitiveNotificationProtectionController sensitiveNotificationProtectionController) {
+ SensitiveNotificationProtectionController sensitiveNotificationProtectionController,
+ WallpaperInteractor wallpaperInteractor) {
mView = view;
mKeyguardTransitionRepo = keyguardTransitionRepo;
mViewBinder = viewBinder;
@@ -812,6 +816,7 @@
mDismissibilityProvider = dismissibilityProvider;
mActivityStarter = activityStarter;
mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController;
+ mWallpaperInteractor = wallpaperInteractor;
mView.passSplitShadeStateController(splitShadeStateController);
if (SceneContainerFlag.isEnabled()) {
mWakeUpCoordinator.setStackScroller(this);
@@ -948,6 +953,8 @@
collectFlow(mView, mKeyguardTransitionRepo.getTransitions(),
this::onKeyguardTransitionChanged);
}
+
+ mView.setWallpaperInteractor(mWallpaperInteractor);
}
private boolean isInVisibleLocation(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 178c318..6a77988 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -182,14 +182,8 @@
mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material));
- lp = (MarginLayoutParams) mCarrierLabel.getLayoutParams();
+ updateCarrierLabelMargin();
- int marginStart = calculateMargin(
- getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin),
- mPadding.left);
- lp.setMarginStart(marginStart);
-
- mCarrierLabel.setLayoutParams(lp);
updateKeyguardStatusBarHeight();
}
@@ -203,6 +197,15 @@
setLayoutParams(lp);
}
+ private void updateCarrierLabelMargin() {
+ MarginLayoutParams lp = (MarginLayoutParams) mCarrierLabel.getLayoutParams();
+ int marginStart = calculateMargin(
+ getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin),
+ mPadding.left);
+ lp.setMarginStart(marginStart);
+ mCarrierLabel.setLayoutParams(lp);
+ }
+
void loadDimens() {
Resources res = getResources();
mSystemIconsSwitcherHiddenExpandedMargin = res.getDimensionPixelSize(
@@ -334,6 +337,7 @@
RelativeLayout.LayoutParams lp = (LayoutParams) mCarrierLabel.getLayoutParams();
lp.addRule(RelativeLayout.START_OF, R.id.status_icon_area);
+ updateCarrierLabelMargin();
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
lp.removeRule(RelativeLayout.RIGHT_OF);
@@ -366,6 +370,7 @@
lp = (LayoutParams) mCarrierLabel.getLayoutParams();
lp.addRule(RelativeLayout.START_OF, R.id.cutout_space_view);
+ updateCarrierLabelMargin();
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
lp.addRule(RelativeLayout.RIGHT_OF, R.id.cutout_space_view);
diff --git a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
index 8957fe1..09cef1e 100644
--- a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt
@@ -18,6 +18,7 @@
package com.android.systemui.user.legacyhelper.ui
import android.content.Context
+import android.util.Log
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import com.android.systemui.res.R
@@ -32,6 +33,8 @@
*/
object LegacyUserUiHelper {
+ private const val TAG = "LegacyUserUiHelper"
+
@JvmStatic
@DrawableRes
fun getUserSwitcherActionIconResourceId(
@@ -67,7 +70,9 @@
val resourceId: Int? = getGuestUserRecordNameResourceId(record)
return when {
resourceId != null -> context.getString(resourceId)
- record.info != null -> checkNotNull(record.info.name)
+ record.info != null ->
+ record.info.name
+ ?: "".also { Log.i(TAG, "Expected display name for: ${record.info}") }
else ->
context.getString(
getUserSwitcherActionTextResourceId(
diff --git a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
index 65a0218..0744b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
@@ -32,19 +32,24 @@
* Note: New logic should be added to [WallpaperRepository], not this class.
*/
@SysUISingleton
-class WallpaperController @Inject constructor(
+class WallpaperController
+@Inject
+constructor(
private val wallpaperManager: WallpaperManager,
private val wallpaperRepository: WallpaperRepository,
) {
var rootView: View? = null
+ set(value) {
+ field = value
+ wallpaperRepository.rootView = value
+ }
private var notificationShadeZoomOut: Float = 0f
private var unfoldTransitionZoomOut: Float = 0f
private val shouldUseDefaultUnfoldTransition: Boolean
- get() = wallpaperRepository.wallpaperInfo.value?.shouldUseDefaultUnfoldTransition()
- ?: true
+ get() = wallpaperRepository.wallpaperInfo.value?.shouldUseDefaultUnfoldTransition() ?: true
fun setNotificationShadeZoom(zoomOut: Float) {
notificationShadeZoomOut = zoomOut
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
index b45b8cd..54953c9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.wallpapers.data.repository
import android.app.WallpaperInfo
+import android.view.View
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
@@ -33,4 +34,7 @@
class NoopWallpaperRepository @Inject constructor() : WallpaperRepository {
override val wallpaperInfo: StateFlow<WallpaperInfo?> = MutableStateFlow(null).asStateFlow()
override val wallpaperSupportsAmbientMode = MutableStateFlow(false).asStateFlow()
+ override var rootView: View? = null
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index 041b6f9..203e1da 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -21,10 +21,16 @@
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import android.os.Bundle
import android.os.UserHandle
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.Flags
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
@@ -32,16 +38,19 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/** A repository storing information about the current wallpaper. */
@@ -51,6 +60,15 @@
/** Emits true if the current user's current wallpaper supports ambient mode. */
val wallpaperSupportsAmbientMode: StateFlow<Boolean>
+
+ /** Set rootView to get its windowToken afterwards */
+ var rootView: View?
+
+ /**
+ * Set bottom of notifications from notification stack, and Magic Portrait will layout base on
+ * this value
+ */
+ fun setNotificationStackAbsoluteBottom(bottom: Float)
}
@SysUISingleton
@@ -61,6 +79,8 @@
@Background private val bgDispatcher: CoroutineDispatcher,
broadcastDispatcher: BroadcastDispatcher,
userRepository: UserRepository,
+ keyguardRepository: KeyguardRepository,
+ keyguardClockRepository: KeyguardClockRepository,
private val wallpaperManager: WallpaperManager,
context: Context,
) : WallpaperRepository {
@@ -69,10 +89,7 @@
private val wallpaperChanged: Flow<Unit> =
broadcastDispatcher
- .broadcastFlow(
- IntentFilter(Intent.ACTION_WALLPAPER_CHANGED),
- user = UserHandle.ALL,
- )
+ .broadcastFlow(IntentFilter(Intent.ACTION_WALLPAPER_CHANGED), user = UserHandle.ALL)
// The `combine` defining `wallpaperSupportsAmbientMode` will not run until both of the
// input flows emit at least once. Since this flow is an input flow, it needs to emit
// when it starts up to ensure that the `combine` will run if the user changes before we
@@ -87,6 +104,27 @@
// Only update the wallpaper status once the user selection has finished.
.filter { it.selectionStatus == SelectionStatus.SELECTION_COMPLETE }
+ /** The bottom of notification stack respect to the top of screen. */
+ private val notificationStackAbsoluteBottom: MutableStateFlow<Float> = MutableStateFlow(0F)
+
+ /** The top of shortcut respect to the top of screen. */
+ private val shortcutAbsoluteTop: StateFlow<Float> = keyguardRepository.shortcutAbsoluteTop
+
+ /**
+ * The top of notification stack to give a default state of lockscreen remaining space for
+ * states with notifications to compare with. It's the bottom of smartspace date and weather
+ * smartspace in small clock state, plus proper bottom margin.
+ */
+ private val notificationStackDefaultTop = keyguardClockRepository.notificationDefaultTop
+ @VisibleForTesting var sendLockscreenLayoutJob: Job? = null
+ private val lockscreenRemainingSpaceWithNotification: Flow<Triple<Float, Float, Float>> =
+ combine(
+ notificationStackAbsoluteBottom,
+ notificationStackDefaultTop,
+ shortcutAbsoluteTop,
+ ::Triple,
+ )
+
override val wallpaperInfo: StateFlow<WallpaperInfo?> =
if (!wallpaperManager.isWallpaperSupported || !deviceSupportsAodWallpaper) {
MutableStateFlow(null).asStateFlow()
@@ -116,9 +154,70 @@
initialValue = wallpaperInfo.value?.supportsAmbientMode() == true,
)
+ override var rootView: View? = null
+
+ val shouldSendNotificationLayout =
+ wallpaperInfo
+ .map {
+ val shouldSendNotificationLayout = shouldSendNotificationLayout(it)
+ if (shouldSendNotificationLayout) {
+ sendLockscreenLayoutJob =
+ scope.launch {
+ lockscreenRemainingSpaceWithNotification.collect {
+ (notificationBottom, notificationDefaultTop, shortcutTop) ->
+ wallpaperManager.sendWallpaperCommand(
+ /* windowToken = */ rootView?.windowToken,
+ /* action = */ WallpaperManager
+ .COMMAND_LOCKSCREEN_LAYOUT_CHANGED,
+ /* x = */ 0,
+ /* y = */ 0,
+ /* z = */ 0,
+ /* extras = */ Bundle().apply {
+ putFloat("screenLeft", 0F)
+ putFloat("smartspaceBottom", notificationDefaultTop)
+ putFloat("notificationBottom", notificationBottom)
+ putFloat(
+ "screenRight",
+ context.resources.displayMetrics.widthPixels.toFloat(),
+ )
+ putFloat("shortCutTop", shortcutTop)
+ },
+ )
+ }
+ }
+ } else {
+ sendLockscreenLayoutJob?.cancel()
+ }
+ shouldSendNotificationLayout
+ }
+ .stateIn(
+ scope,
+ // Always be listening for wallpaper changes.
+ if (Flags.magicPortraitWallpapers()) SharingStarted.Eagerly
+ else SharingStarted.Lazily,
+ initialValue = false,
+ )
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ notificationStackAbsoluteBottom.value = bottom
+ }
+
private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
return withContext(bgDispatcher) {
wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
}
}
+
+ private fun shouldSendNotificationLayout(wallpaperInfo: WallpaperInfo?): Boolean {
+ return if (wallpaperInfo != null && wallpaperInfo.component != null) {
+ wallpaperInfo.component!!.className == MAGIC_PORTRAIT_CLASSNAME
+ } else {
+ false
+ }
+ }
+
+ companion object {
+ const val MAGIC_PORTRAIT_CLASSNAME =
+ "com.google.android.apps.magicportrait.service.MagicPortraitWallpaperService"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
new file mode 100644
index 0000000..79ebf01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wallpapers.domain.interactor
+
+import com.android.systemui.wallpapers.data.repository.WallpaperRepository
+import javax.inject.Inject
+
+class WallpaperInteractor @Inject constructor(val wallpaperRepository: WallpaperRepository) {
+ fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ wallpaperRepository.setNotificationStackAbsoluteBottom(bottom)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 0b944f0..96a0aad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -39,13 +39,13 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -57,6 +57,7 @@
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.mock
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@@ -122,6 +123,7 @@
{ keyguardBlueprintInteractor },
keyguardRootViewModel,
aodBurnInViewModel,
+ largeScreenHeaderHelperLazy = { mock<LargeScreenHeaderHelper>() },
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 7cd306e..6425da4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -83,6 +83,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -103,7 +104,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.notification.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -113,6 +113,7 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import org.junit.Before;
import org.junit.Test;
@@ -154,6 +155,7 @@
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private PowerInteractor mPowerInteractor;
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
+ @Mock private WallpaperInteractor mWallpaperInteractor;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private MetricsLogger mMetricsLogger;
@Mock private ColorUpdateLogger mColorUpdateLogger;
@@ -1070,7 +1072,8 @@
mock(NotificationDismissibilityProvider.class),
mActivityStarter,
new ResourcesSplitShadeStateController(),
- mSensitiveNotificationProtectionController);
+ mSensitiveNotificationProtectionController,
+ mWallpaperInteractor);
}
static class LogMatcher implements ArgumentMatcher<LogMaker> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 8a3e551..59fc0d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -102,6 +102,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.AvalancheController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import kotlin.Unit;
@@ -146,6 +147,7 @@
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private NotificationShelf mNotificationShelf;
+ @Mock private WallpaperInteractor mWallpaperInteractor;
@Mock private NotificationStackSizeCalculator mStackSizeCalculator;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
@@ -208,6 +210,7 @@
.thenReturn(mNotificationRoundnessManager);
mStackScroller.setController(mStackScrollLayoutController);
mStackScroller.setShelf(mNotificationShelf);
+ mStackScroller.setWallpaperInteractor(mWallpaperInteractor);
when(mStackScroller.getExpandHelper()).thenReturn(mExpandHelper);
doNothing().when(mGroupExpansionManager).collapseGroups();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
index bdecf2b..b8dd334 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
@@ -18,18 +18,21 @@
import android.app.WallpaperInfo
import android.app.WallpaperManager
+import android.content.ComponentName
import android.content.Intent
import android.content.pm.UserInfo
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
+import com.android.systemui.wallpapers.data.repository.WallpaperRepositoryImpl.Companion.MAGIC_PORTRAIT_CLASSNAME
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -39,6 +42,9 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@@ -48,6 +54,8 @@
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val userRepository = FakeUserRepository()
+ private val keyguardClockRepository = FakeKeyguardClockRepository()
+ private val keyguardRepository = FakeKeyguardRepository()
private val wallpaperManager: WallpaperManager = mock()
private val underTest: WallpaperRepositoryImpl by lazy {
@@ -56,6 +64,8 @@
testDispatcher,
fakeBroadcastDispatcher,
userRepository,
+ keyguardRepository,
+ keyguardClockRepository,
wallpaperManager,
context,
)
@@ -219,7 +229,7 @@
testScope.runTest {
context.orCreateTestableResources.addOverride(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper,
- false
+ false,
)
val latest by collectLastValue(underTest.wallpaperInfo)
@@ -407,7 +417,7 @@
testScope.runTest {
context.orCreateTestableResources.addOverride(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper,
- false
+ false,
)
val latest by collectLastValue(underTest.wallpaperSupportsAmbientMode)
@@ -425,6 +435,54 @@
assertThat(latest).isFalse()
}
+ @Test
+ @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
+ fun shouldSendNotificationLayout_setMagicPortraitWallpaper_launchSendLayoutJob() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val magicPortraitWallpaper =
+ mock<WallpaperInfo>().apply {
+ whenever(this.component)
+ .thenReturn(ComponentName(context, MAGIC_PORTRAIT_CLASSNAME))
+ }
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(magicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isTrue()
+ assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
+ assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
+ fun shouldSendNotificationLayout_setNotMagicPortraitWallpaper_cancelSendLayoutJob() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val magicPortraitWallpaper = MAGIC_PORTRAIT_WP
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(magicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isTrue()
+ assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
+ assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
+
+ val nonMagicPortraitWallpaper = UNSUPPORTED_WP
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(nonMagicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isFalse()
+ assertThat(underTest.sendLockscreenLayoutJob?.isCancelled).isEqualTo(true)
+ }
+
private companion object {
val USER_WITH_UNSUPPORTED_WP = UserInfo(/* id= */ 3, /* name= */ "user3", /* flags= */ 0)
val UNSUPPORTED_WP =
@@ -433,5 +491,10 @@
val USER_WITH_SUPPORTED_WP = UserInfo(/* id= */ 4, /* name= */ "user4", /* flags= */ 0)
val SUPPORTED_WP =
mock<WallpaperInfo>().apply { whenever(this.supportsAmbientMode()).thenReturn(true) }
+
+ val MAGIC_PORTRAIT_WP =
+ mock<WallpaperInfo>().apply {
+ whenever(this.component).thenReturn(ComponentName("", MAGIC_PORTRAIT_CLASSNAME))
+ }
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt
new file mode 100644
index 0000000..2850ab7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.app
+
+import android.app.WallpaperManager
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.wallpaperManager: WallpaperManager by Fixture {
+ WallpaperManager.getInstance(applicationContext)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
index 5e5f8cb..159dd34 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
@@ -46,16 +46,27 @@
private val _previewClock = MutableStateFlow(Mockito.mock(ClockController::class.java))
override val previewClock: Flow<ClockController>
get() = _previewClock
+
+ private val _notificationDefaultTop = MutableStateFlow(0F)
+ override val notificationDefaultTop: StateFlow<Float>
+ get() = _notificationDefaultTop
+
override val clockEventController: ClockEventController
get() = mock()
+
override val shouldForceSmallClock: Boolean
get() = _shouldForceSmallClock
+
private var _shouldForceSmallClock: Boolean = false
override fun setClockSize(size: ClockSize) {
_clockSize.value = size
}
+ override fun setNotificationDefaultTop(top: Float) {
+ _notificationDefaultTop.value = top
+ }
+
fun setSelectedClockSize(size: ClockSizeSetting) {
_selectedClockSize.value = size
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 54a6c0c..e513e8d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -131,6 +131,10 @@
private val _isEncryptedOrLockdown = MutableStateFlow(true)
override val isEncryptedOrLockdown: Flow<Boolean> = _isEncryptedOrLockdown
+ private val _shortcutAbsoluteTop = MutableStateFlow(0F)
+ override val shortcutAbsoluteTop: StateFlow<Float>
+ get() = _shortcutAbsoluteTop.asStateFlow()
+
private val _isKeyguardEnabled = MutableStateFlow(true)
override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()
@@ -241,7 +245,7 @@
override fun setBiometricUnlockState(
mode: BiometricUnlockMode,
- source: BiometricUnlockSource?
+ source: BiometricUnlockSource?,
) {
_biometricUnlockState.tryEmit(BiometricUnlockModel(mode, source))
}
@@ -294,6 +298,10 @@
return isShowKeyguardWhenReenabled
}
+ override fun setShortcutAbsoluteTop(top: Float) {
+ _shortcutAbsoluteTop.value = top
+ }
+
override fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean) {
_canIgnoreAuthAndReturnToGone.value = canWake
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index 12d7c49..49a8c18 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -29,9 +29,10 @@
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.shade.LargeScreenHeaderHelper
import java.util.Optional
import org.mockito.Mockito.spy
+import org.mockito.kotlin.mock
val Kosmos.keyguardClockSection: ClockSection by
Kosmos.Fixture {
@@ -43,6 +44,7 @@
blueprintInteractor = { keyguardBlueprintInteractor },
rootViewModel = keyguardRootViewModel,
aodBurnInViewModel = aodBurnInViewModel,
+ largeScreenHeaderHelperLazy = { mock<LargeScreenHeaderHelper>() },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
index d52883e..bdb9abb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
@@ -27,13 +27,13 @@
val Kosmos.keyguardClockInteractor by
Kosmos.Fixture {
KeyguardClockInteractor(
- keyguardClockRepository = keyguardClockRepository,
- applicationScope = applicationCoroutineScope,
mediaCarouselInteractor = mediaCarouselInteractor,
activeNotificationsInteractor = activeNotificationsInteractor,
shadeInteractor = shadeInteractor,
keyguardInteractor = keyguardInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
headsUpNotificationInteractor = headsUpNotificationInteractor,
+ applicationScope = applicationCoroutineScope,
+ keyguardClockRepository = keyguardClockRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
new file mode 100644
index 0000000..1d8c891
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wallpapers.data.repository
+
+import android.content.applicationContext
+import com.android.app.wallpaperManager
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.user.data.repository.userRepository
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.wallpaperRepository by Fixture {
+ WallpaperRepositoryImpl(
+ context = applicationContext,
+ scope = testScope,
+ bgDispatcher = testDispatcher,
+ broadcastDispatcher = broadcastDispatcher,
+ userRepository = userRepository,
+ wallpaperManager = wallpaperManager,
+ keyguardClockRepository = keyguardClockRepository,
+ keyguardRepository = keyguardRepository,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt
new file mode 100644
index 0000000..5278351
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wallpapers.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.wallpapers.data.repository.wallpaperRepository
+
+val Kosmos.wallpaperInteractor by
+ Kosmos.Fixture { WallpaperInteractor(wallpaperRepository = wallpaperRepository) }
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index d80e40c..504137a 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -727,10 +727,8 @@
return;
}
// Read configuration of features, libs and priv-app permissions from apex module.
- int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
- if (android.permission.flags.Flags.apexSignaturePermissionAllowlistEnabled()) {
- apexPermissionFlag |= ALLOW_SIGNATURE_PERMISSIONS;
- }
+ int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
+ | ALLOW_SIGNATURE_PERMISSIONS;
// TODO: Use a solid way to filter apex module folders?
for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
if (f.isFile() || f.getPath().contains("@")) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 596e375..e0cf96f 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -72,9 +72,6 @@
import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
import static android.permission.flags.Flags.deviceAwareAppOpNewSchemaEnabled;
-import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION;
-import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_OPERATION;
-import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_PROXY_OPERATION;
import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
import android.Manifest;
@@ -163,7 +160,6 @@
import com.android.internal.pm.pkg.component.ParsedAttribution;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -2833,26 +2829,12 @@
@Override
public int checkOperation(int code, int uid, String packageName) {
- if (Flags.appopAccessTrackingLoggingEnabled()) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED,
- uid, code,
- APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION,
- false);
- }
return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, null,
Context.DEVICE_ID_DEFAULT, false /*raw*/);
}
@Override
public int checkOperationForDevice(int code, int uid, String packageName, int virtualDeviceId) {
- if (Flags.appopAccessTrackingLoggingEnabled()) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED,
- uid, code,
- APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION,
- false);
- }
return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, null,
virtualDeviceId, false /*raw*/);
}
@@ -3033,14 +3015,6 @@
public SyncNotedAppOp noteProxyOperationWithState(int code,
AttributionSourceState attributionSourceState, boolean shouldCollectAsyncNotedOp,
String message, boolean shouldCollectMessage, boolean skipProxyOperation) {
- if (Flags.appopAccessTrackingLoggingEnabled()) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED,
- attributionSourceState.uid, code,
- APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_PROXY_OPERATION,
- attributionSourceState.attributionTag != null);
- }
-
AttributionSource attributionSource = new AttributionSource(attributionSourceState);
return mCheckOpsDelegateDispatcher.noteProxyOperation(code, attributionSource,
shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation);
@@ -3122,14 +3096,6 @@
public SyncNotedAppOp noteOperation(int code, int uid, String packageName,
String attributionTag, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage) {
- if (Flags.appopAccessTrackingLoggingEnabled()) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED,
- uid, code,
- APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_OPERATION,
- attributionTag != null);
- }
-
return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName,
attributionTag, Context.DEVICE_ID_DEFAULT, shouldCollectAsyncNotedOp, message,
shouldCollectMessage);
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index eeec369..99ced7f 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -212,6 +212,10 @@
Flags.FLAG_BLOCK_AUTOBRIGHTNESS_CHANGES_ON_STYLUS_USAGE,
Flags::blockAutobrightnessChangesOnStylusUsage
);
+ private final FlagState mIsUserRefreshRateForExternalDisplayEnabled = new FlagState(
+ Flags.FLAG_ENABLE_USER_REFRESH_RATE_FOR_EXTERNAL_DISPLAY,
+ Flags::enableUserRefreshRateForExternalDisplay
+ );
private final FlagState mEnableBatteryStatsForAllDisplays = new FlagState(
Flags.FLAG_ENABLE_BATTERY_STATS_FOR_ALL_DISPLAYS,
@@ -456,6 +460,14 @@
}
/**
+ * @return {@code true} if need to use user refresh rate settings for
+ * external displays.
+ */
+ public boolean isUserRefreshRateForExternalDisplayEnabled() {
+ return mIsUserRefreshRateForExternalDisplayEnabled.isEnabled();
+ }
+
+ /**
* dumps all flagstates
* @param pw printWriter
*/
@@ -501,6 +513,7 @@
pw.println(" " + mIdleScreenConfigInSubscribingLightSensor);
pw.println(" " + mEnableBatteryStatsForAllDisplays);
pw.println(" " + mBlockAutobrightnessChangesOnStylusUsage);
+ pw.println(" " + mIsUserRefreshRateForExternalDisplayEnabled);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 20ecd2d..2f04d9e 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -381,3 +381,14 @@
bug: "352411468"
is_fixed_read_only: true
}
+
+flag {
+ name: "enable_user_refresh_rate_for_external_display"
+ namespace: "display_manager"
+ description: "Apply refresh rate from user preferred display mode to external displays"
+ bug: "370657357"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 18e0d6e..ffa64bf 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -1194,6 +1194,13 @@
@GuardedBy("mLock")
private void updateRefreshRateSettingLocked(float minRefreshRate, float peakRefreshRate,
float defaultRefreshRate, int displayId) {
+ if (mDisplayObserver.isExternalDisplayLocked(displayId)) {
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "skip updateRefreshRateSettingLocked for external display "
+ + displayId);
+ }
+ return;
+ }
// TODO(b/156304339): The logic in here, aside from updating the refresh rate votes, is
// used to predict if we're going to be doing frequent refresh rate switching, and if
// so, enable the brightness observer. The logic here is more complicated and fragile
@@ -1243,6 +1250,8 @@
}
private void removeRefreshRateSetting(int displayId) {
+ mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
+ null);
mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
null);
mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
@@ -1458,11 +1467,11 @@
public void onDisplayAdded(int displayId) {
updateDisplayDeviceConfig(displayId);
DisplayInfo displayInfo = getDisplayInfo(displayId);
+ registerExternalDisplay(displayInfo);
updateDisplayModes(displayId, displayInfo);
updateLayoutLimitedFrameRate(displayId, displayInfo);
updateUserSettingDisplayPreferredSize(displayInfo);
updateDisplaysPeakRefreshRateAndResolution(displayInfo);
- addDisplaysSynchronizedPeakRefreshRate(displayInfo);
}
@Override
@@ -1477,7 +1486,7 @@
updateLayoutLimitedFrameRate(displayId, null);
removeUserSettingDisplayPreferredSize(displayId);
removeDisplaysPeakRefreshRateAndResolution(displayId);
- removeDisplaysSynchronizedPeakRefreshRate(displayId);
+ unregisterExternalDisplay(displayId);
}
@Override
@@ -1489,6 +1498,30 @@
updateUserSettingDisplayPreferredSize(displayInfo);
}
+ private void registerExternalDisplay(DisplayInfo displayInfo) {
+ if (displayInfo == null || displayInfo.type != Display.TYPE_EXTERNAL) {
+ return;
+ }
+ synchronized (mLock) {
+ mExternalDisplaysConnected.add(displayInfo.displayId);
+ if (mExternalDisplaysConnected.size() == 1) {
+ addDisplaysSynchronizedPeakRefreshRate();
+ }
+ }
+ }
+
+ private void unregisterExternalDisplay(int displayId) {
+ synchronized (mLock) {
+ if (!isExternalDisplayLocked(displayId)) {
+ return;
+ }
+ mExternalDisplaysConnected.remove(displayId);
+ if (mExternalDisplaysConnected.isEmpty()) {
+ removeDisplaysSynchronizedPeakRefreshRate();
+ }
+ }
+ }
+
boolean isExternalDisplayLocked(int displayId) {
return mExternalDisplaysConnected.contains(displayId);
}
@@ -1534,10 +1567,24 @@
return;
}
- mVotesStorage.updateVote(info.displayId,
- Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
- Vote.forSize(/* width */ preferredMode.getPhysicalWidth(),
- /* height */ preferredMode.getPhysicalHeight()));
+ if (info.type == Display.TYPE_EXTERNAL
+ && mDisplayManagerFlags.isUserRefreshRateForExternalDisplayEnabled()
+ && !isRefreshRateSynchronizationEnabled()) {
+ mVotesStorage.updateVote(info.displayId,
+ Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
+ Vote.forSizeAndPhysicalRefreshRatesRange(
+ /* minWidth */ preferredMode.getPhysicalWidth(),
+ /* minHeight */ preferredMode.getPhysicalHeight(),
+ /* width */ preferredMode.getPhysicalWidth(),
+ /* height */ preferredMode.getPhysicalHeight(),
+ /* minRefreshRate */ preferredMode.getRefreshRate(),
+ /* maxRefreshRate */ preferredMode.getRefreshRate()));
+ } else {
+ mVotesStorage.updateVote(info.displayId,
+ Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
+ Vote.forSize(/* width */ preferredMode.getPhysicalWidth(),
+ /* height */ preferredMode.getPhysicalHeight()));
+ }
}
@Nullable
@@ -1584,17 +1631,10 @@
* Sets 60Hz target refresh rate as the vote with
* {@link Vote#PRIORITY_SYNCHRONIZED_REFRESH_RATE} priority.
*/
- private void addDisplaysSynchronizedPeakRefreshRate(@Nullable final DisplayInfo info) {
- if (info == null || info.type != Display.TYPE_EXTERNAL
- || !isRefreshRateSynchronizationEnabled()) {
+ private void addDisplaysSynchronizedPeakRefreshRate() {
+ if (!isRefreshRateSynchronizationEnabled()) {
return;
}
- synchronized (mLock) {
- mExternalDisplaysConnected.add(info.displayId);
- if (mExternalDisplaysConnected.size() != 1) {
- return;
- }
- }
// set minRefreshRate as the max refresh rate.
mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE,
Vote.forPhysicalRefreshRates(
@@ -1610,19 +1650,10 @@
+ SYNCHRONIZED_REFRESH_RATE_TOLERANCE));
}
- private void removeDisplaysSynchronizedPeakRefreshRate(final int displayId) {
+ private void removeDisplaysSynchronizedPeakRefreshRate() {
if (!isRefreshRateSynchronizationEnabled()) {
return;
}
- synchronized (mLock) {
- if (!isExternalDisplayLocked(displayId)) {
- return;
- }
- mExternalDisplaysConnected.remove(displayId);
- if (!mExternalDisplaysConnected.isEmpty()) {
- return;
- }
- }
mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE, null);
mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, null);
}
diff --git a/services/core/java/com/android/server/display/mode/Vote.java b/services/core/java/com/android/server/display/mode/Vote.java
index 459f9a6..f5abb05 100644
--- a/services/core/java/com/android/server/display/mode/Vote.java
+++ b/services/core/java/com/android/server/display/mode/Vote.java
@@ -44,7 +44,7 @@
// It votes [minRefreshRate, Float.POSITIVE_INFINITY]
int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3;
- // User setting preferred display resolution.
+ // User setting preferred display resolution, for external displays also includes refresh rate.
int PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE = 4;
// APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 5514ec7..48dab2f 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -214,12 +214,6 @@
version, ruleProvider));
}
- FrameworkStatsLog.write(
- FrameworkStatsLog.INTEGRITY_RULES_PUSHED,
- success,
- ruleProvider,
- version);
-
Intent intent = new Intent();
intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
try {
@@ -346,15 +340,6 @@
packageName, result.getEffect(), result.getMatchedRules()));
}
- FrameworkStatsLog.write(
- FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
- packageName,
- appCertificates.toString(),
- appInstallMetadata.getVersionCode(),
- installerPackageName,
- result.getLoggingResponse(),
- result.isCausedByAppCertRule(),
- result.isCausedByInstallerRule());
mPackageManagerInternal.setIntegrityVerificationResult(
verificationId,
result.getEffect() == IntegrityCheckResult.Effect.ALLOW
diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
index 1fa0670..05186cd 100644
--- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
+++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
@@ -82,21 +82,6 @@
return new IntegrityCheckResult(Effect.DENY, ruleList);
}
- /**
- * Returns the in value of the integrity check result for logging purposes.
- */
- public int getLoggingResponse() {
- if (getEffect() == Effect.DENY) {
- return FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED;
- } else if (getEffect() == Effect.ALLOW && getMatchedRules().isEmpty()) {
- return FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED;
- } else if (getEffect() == Effect.ALLOW && !getMatchedRules().isEmpty()) {
- return FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED;
- } else {
- throw new IllegalStateException("IntegrityCheckResult is not valid.");
- }
- }
-
/** Returns true when the {@code mEffect} is caused by an app certificate mismatch. */
public boolean isCausedByAppCertRule() {
return mRuleList.stream().anyMatch(rule -> rule.getFormula().isAppCertificateFormula());
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index cd0a2a7..03fc60c 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -106,8 +106,7 @@
protected final String TAG = getClass().getSimpleName().replace('$', '.');
protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- protected static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
- protected static final int ON_BINDING_DIED_REBIND_MSG = 1234;
+ private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
protected static final String ENABLED_SERVICES_SEPARATOR = ":";
private static final String DB_VERSION_1 = "1";
private static final String DB_VERSION_2 = "2";
@@ -857,13 +856,7 @@
String approvedItem = getApprovedValue(pkgOrComponent);
if (approvedItem != null) {
- final ComponentName component = ComponentName.unflattenFromString(approvedItem);
if (enabled) {
- if (component != null && !isValidService(component, userId)) {
- Log.e(TAG, "Skip allowing " + mConfig.caption + " " + pkgOrComponent
- + " (userSet: " + userSet + ") for invalid service");
- return;
- }
approved.add(approvedItem);
} else {
approved.remove(approvedItem);
@@ -961,7 +954,7 @@
|| isPackageOrComponentAllowed(component.getPackageName(), userId))) {
return false;
}
- return isValidService(component, userId);
+ return componentHasBindPermission(component, userId);
}
private boolean componentHasBindPermission(ComponentName component, int userId) {
@@ -1313,12 +1306,11 @@
if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) {
final ComponentName component = ComponentName.unflattenFromString(
approvedPackageOrComponent);
- if (component != null && !isValidService(component, userId)) {
+ if (component != null && !componentHasBindPermission(component, userId)) {
approved.removeAt(j);
if (DEBUG) {
Slog.v(TAG, "Removing " + approvedPackageOrComponent
- + " from approved list; no bind permission or "
- + "service interface filter found "
+ + " from approved list; no bind permission found "
+ mConfig.bindPermission);
}
}
@@ -1337,11 +1329,6 @@
}
}
- protected boolean isValidService(ComponentName component, int userId) {
- return componentHasBindPermission(component, userId) && queryPackageForServices(
- component.getPackageName(), userId).contains(component);
- }
-
protected boolean isValidEntry(String packageOrComponent, int userId) {
return hasMatchingServices(packageOrComponent, userId);
}
@@ -1499,25 +1486,23 @@
* Called when user switched to unbind all services from other users.
*/
@VisibleForTesting
- void unbindOtherUserServices(int switchedToUser) {
+ void unbindOtherUserServices(int currentUser) {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- t.traceBegin("ManagedServices.unbindOtherUserServices_current" + switchedToUser);
- unbindServicesImpl(switchedToUser, true /* allExceptUser */);
+ t.traceBegin("ManagedServices.unbindOtherUserServices_current" + currentUser);
+ unbindServicesImpl(currentUser, true /* allExceptUser */);
t.traceEnd();
}
- void unbindUserServices(int removedUser) {
+ void unbindUserServices(int user) {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- t.traceBegin("ManagedServices.unbindUserServices" + removedUser);
- unbindServicesImpl(removedUser, false /* allExceptUser */);
+ t.traceBegin("ManagedServices.unbindUserServices" + user);
+ unbindServicesImpl(user, false /* allExceptUser */);
t.traceEnd();
}
void unbindServicesImpl(int user, boolean allExceptUser) {
final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
synchronized (mMutex) {
- // Remove enqueued rebinds to avoid rebinding services for a switched user
- mHandler.removeMessages(ON_BINDING_DIED_REBIND_MSG);
final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
for (ManagedServiceInfo info : removableBoundServices) {
if ((allExceptUser && (info.userid != user))
@@ -1712,7 +1697,6 @@
mServicesRebinding.add(servicesBindingTag);
mHandler.postDelayed(() ->
reregisterService(name, userid),
- ON_BINDING_DIED_REBIND_MSG,
ON_BINDING_DIED_REBIND_DELAY_MS);
} else {
Slog.v(TAG, getCaption() + " not rebinding in user " + userid
diff --git a/services/core/java/com/android/server/power/feature/PowerManagerFlags.java b/services/core/java/com/android/server/power/feature/PowerManagerFlags.java
index fd60e06..db57d11 100644
--- a/services/core/java/com/android/server/power/feature/PowerManagerFlags.java
+++ b/services/core/java/com/android/server/power/feature/PowerManagerFlags.java
@@ -47,6 +47,9 @@
Flags::perDisplayWakeByTouch
);
+ private final FlagState mFrameworkWakelockInfo =
+ new FlagState(Flags.FLAG_FRAMEWORK_WAKELOCK_INFO, Flags::frameworkWakelockInfo);
+
/** Returns whether early-screen-timeout-detector is enabled on not. */
public boolean isEarlyScreenTimeoutDetectorEnabled() {
return mEarlyScreenTimeoutDetectorFlagState.isEnabled();
@@ -67,6 +70,13 @@
}
/**
+ * @return Whether FrameworkWakelockInfo atom logging is enabled or not.
+ */
+ public boolean isFrameworkWakelockInfoEnabled() {
+ return mFrameworkWakelockInfo.isEnabled();
+ }
+
+ /**
* dumps all flagstates
* @param pw printWriter
*/
@@ -75,6 +85,7 @@
pw.println(" " + mEarlyScreenTimeoutDetectorFlagState);
pw.println(" " + mImproveWakelockLatency);
pw.println(" " + mPerDisplayWakeByTouch);
+ pw.println(" " + mFrameworkWakelockInfo);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/power/feature/power_flags.aconfig b/services/core/java/com/android/server/power/feature/power_flags.aconfig
index 9cf3bb6..8bb69ba 100644
--- a/services/core/java/com/android/server/power/feature/power_flags.aconfig
+++ b/services/core/java/com/android/server/power/feature/power_flags.aconfig
@@ -26,3 +26,10 @@
bug: "343295183"
is_fixed_read_only: true
}
+
+flag {
+ name: "framework_wakelock_info"
+ namespace: "power"
+ description: "Feature flag to enable statsd pulling of FrameworkWakelockInfo atoms"
+ bug: "352602149"
+}
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 936fadf..391071f 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -145,6 +145,7 @@
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.LocalServices;
+import com.android.server.power.feature.PowerManagerFlags;
import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
@@ -5142,6 +5143,10 @@
mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
uidStats.mProcessState, true /* acquired */,
getPowerManagerWakeLockLevel(type));
+ if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
+ mFrameworkEvents.noteStartWakeLock(
+ mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
+ }
}
}
@@ -5187,6 +5192,10 @@
mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
uidStats.mProcessState, false/* acquired */,
getPowerManagerWakeLockLevel(type));
+ if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
+ mFrameworkEvents.noteStopWakeLock(
+ mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
+ }
if (mappedUid != uid) {
// Decrement the ref count for the isolated uid and delete the mapping if uneeded.
@@ -11343,6 +11352,9 @@
return mTmpCpuTimeInFreq;
}
+ WakelockStatsFrameworkEvents mFrameworkEvents = new WakelockStatsFrameworkEvents();
+ PowerManagerFlags mPowerManagerFlags = new PowerManagerFlags();
+
public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
@NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
@NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
@@ -15964,6 +15976,10 @@
// Already plugged in. Schedule the long plug in alarm.
scheduleNextResetWhilePluggedInCheck();
}
+
+ if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
+ mFrameworkEvents.initialize(context);
+ }
}
}
@@ -16791,7 +16807,8 @@
}
int NSORPMS = in.readInt();
if (NSORPMS > 10000) {
- throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
+ throw new ParcelFormatException(
+ "File corrupt: too many screen-off rpm stats " + NSORPMS);
}
for (int irpm = 0; irpm < NSORPMS; irpm++) {
if (in.readInt() != 0) {
diff --git a/services/core/java/com/android/server/power/stats/WakelockStatsFrameworkEvents.java b/services/core/java/com/android/server/power/stats/WakelockStatsFrameworkEvents.java
new file mode 100644
index 0000000..c9693bd
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WakelockStatsFrameworkEvents.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.app.StatsManager;
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.StatsEvent;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/** A class to initialise and log metrics pulled by statsd. */
+public class WakelockStatsFrameworkEvents {
+ // statsd has a dimensional limit on the number of different keys it can handle.
+ // Beyond that limit, statsd will drop data.
+ //
+ // When we have seem SUMMARY_THRESHOLD distinct (uid, tag, wakeLockLevel) keys,
+ // we start summarizing new keys as (uid, OVERFLOW_TAG, OVERFLOW_LEVEL) to
+ // reduce the number of keys we pass to statsd.
+ //
+ // When we reach MAX_WAKELOCK_DIMENSIONS distinct keys, we summarize all new keys
+ // as (OVERFLOW_UID, HARD_CAP_TAG, OVERFLOW_LEVEL) to hard cap the number of
+ // distinct keys we pass to statsd.
+ @VisibleForTesting public static final int SUMMARY_THRESHOLD = 500;
+ @VisibleForTesting public static final int MAX_WAKELOCK_DIMENSIONS = 1000;
+
+ @VisibleForTesting public static final int HARD_CAP_UID = -1;
+ @VisibleForTesting public static final String OVERFLOW_TAG = "*overflow*";
+ @VisibleForTesting public static final String HARD_CAP_TAG = "*overflow hard cap*";
+ @VisibleForTesting public static final int OVERFLOW_LEVEL = 1;
+
+ private static class WakeLockKey {
+ private int uid;
+ private String tag;
+ private int powerManagerWakeLockLevel;
+ private int hashCode;
+
+ WakeLockKey(int uid, String tag, int powerManagerWakeLockLevel) {
+ this.uid = uid;
+ this.tag = new String(tag);
+ this.powerManagerWakeLockLevel = powerManagerWakeLockLevel;
+
+ this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
+ }
+
+ int getUid() {
+ return uid;
+ }
+
+ String getTag() {
+ return tag;
+ }
+
+ int getPowerManagerWakeLockLevel() {
+ return powerManagerWakeLockLevel;
+ }
+
+ void setOverflow() {
+ tag = OVERFLOW_TAG;
+ powerManagerWakeLockLevel = OVERFLOW_LEVEL;
+ this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
+ }
+
+ void setHardCap() {
+ uid = HARD_CAP_UID;
+ tag = HARD_CAP_TAG;
+ powerManagerWakeLockLevel = OVERFLOW_LEVEL;
+ this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !(o instanceof WakeLockKey)) return false;
+
+ WakeLockKey that = (WakeLockKey) o;
+ return uid == that.uid
+ && tag.equals(that.tag)
+ && powerManagerWakeLockLevel == that.powerManagerWakeLockLevel;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.hashCode;
+ }
+ }
+
+ private static class WakeLockStats {
+ // accumulated uptime attributed to this WakeLock since boot, where overlap
+ // (including nesting) is ignored
+ public long uptimeMillis = 0;
+
+ // count of WakeLocks that have been acquired and then released
+ public long completedCount = 0;
+ }
+
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private final Map<WakeLockKey, WakeLockStats> mWakeLockStats = new HashMap<>();
+
+ private static class WakeLockData {
+ // uptime millis when first acquired
+ public long acquireUptimeMillis = 0;
+ public int refCount = 0;
+
+ WakeLockData(long uptimeMillis) {
+ acquireUptimeMillis = uptimeMillis;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private final Map<WakeLockKey, WakeLockData> mOpenWakeLocks = new HashMap<>();
+
+ public void noteStartWakeLock(
+ int uid, String tag, int powerManagerWakeLockLevel, long eventUptimeMillis) {
+ final WakeLockKey key = new WakeLockKey(uid, tag, powerManagerWakeLockLevel);
+
+ synchronized (mLock) {
+ WakeLockData data =
+ mOpenWakeLocks.computeIfAbsent(key, k -> new WakeLockData(eventUptimeMillis));
+ data.refCount++;
+ mOpenWakeLocks.put(key, data);
+ }
+ }
+
+ @VisibleForTesting
+ public boolean inOverflow() {
+ synchronized (mLock) {
+ return inOverflowLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean inOverflowLocked() {
+ return mWakeLockStats.size() >= SUMMARY_THRESHOLD;
+ }
+
+ @VisibleForTesting
+ public boolean inHardCap() {
+ synchronized (mLock) {
+ return inHardCapLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean inHardCapLocked() {
+ return mWakeLockStats.size() >= MAX_WAKELOCK_DIMENSIONS;
+ }
+
+ public void noteStopWakeLock(
+ int uid, String tag, int powerManagerWakeLockLevel, long eventUptimeMillis) {
+ WakeLockKey key = new WakeLockKey(uid, tag, powerManagerWakeLockLevel);
+
+ synchronized (mLock) {
+ WakeLockData data = mOpenWakeLocks.get(key);
+ if (data == null) {
+ Log.e(TAG, "WakeLock not found when stopping: " + uid + " " + tag);
+ return;
+ }
+
+ if (data.refCount == 1) {
+ mOpenWakeLocks.remove(key);
+ long wakeLockDur = eventUptimeMillis - data.acquireUptimeMillis;
+
+ // Rewrite key if in an overflow state.
+ if (inOverflowLocked() && !mWakeLockStats.containsKey(key)) {
+ key.setOverflow();
+ if (inHardCapLocked() && !mWakeLockStats.containsKey(key)) {
+ key.setHardCap();
+ }
+ }
+
+ WakeLockStats stats = mWakeLockStats.computeIfAbsent(key, k -> new WakeLockStats());
+ stats.uptimeMillis += wakeLockDur;
+ stats.completedCount++;
+ mWakeLockStats.put(key, stats);
+ } else {
+ data.refCount--;
+ mOpenWakeLocks.put(key, data);
+ }
+ }
+ }
+
+ public List<StatsEvent> pullFrameworkWakelockInfoAtoms() {
+ return pullFrameworkWakelockInfoAtoms(SystemClock.uptimeMillis());
+ }
+
+ public List<StatsEvent> pullFrameworkWakelockInfoAtoms(long nowMillis) {
+ List<StatsEvent> result = new ArrayList<>();
+ HashSet<WakeLockKey> keys = new HashSet<>();
+
+ // Used to collect open WakeLocks when in an overflow state.
+ HashMap<WakeLockKey, WakeLockStats> openOverflowStats = new HashMap<>();
+
+ synchronized (mLock) {
+ keys.addAll(mWakeLockStats.keySet());
+
+ // If we are in an overflow state, an open wakelock may have a new key
+ // that needs to be summarized.
+ if (inOverflowLocked()) {
+ for (WakeLockKey key : mOpenWakeLocks.keySet()) {
+ if (!mWakeLockStats.containsKey(key)) {
+ WakeLockData data = mOpenWakeLocks.get(key);
+
+ key.setOverflow();
+ if (inHardCapLocked() && !mWakeLockStats.containsKey(key)) {
+ key.setHardCap();
+ }
+ keys.add(key);
+
+ WakeLockStats stats =
+ openOverflowStats.computeIfAbsent(key, k -> new WakeLockStats());
+ stats.uptimeMillis += nowMillis - data.acquireUptimeMillis;
+ openOverflowStats.put(key, stats);
+ }
+ }
+ } else {
+ keys.addAll(mOpenWakeLocks.keySet());
+ }
+
+ for (WakeLockKey key : keys) {
+ long openWakeLockUptime = 0;
+ WakeLockData data = mOpenWakeLocks.get(key);
+ if (data != null) {
+ openWakeLockUptime = nowMillis - data.acquireUptimeMillis;
+ }
+
+ WakeLockStats stats = mWakeLockStats.computeIfAbsent(key, k -> new WakeLockStats());
+ WakeLockStats extraTime =
+ openOverflowStats.computeIfAbsent(key, k -> new WakeLockStats());
+
+ stats.uptimeMillis += openWakeLockUptime + extraTime.uptimeMillis;
+
+ StatsEvent event =
+ StatsEvent.newBuilder()
+ .setAtomId(FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO)
+ .writeInt(key.getUid())
+ .writeString(key.getTag())
+ .writeInt(key.getPowerManagerWakeLockLevel())
+ .writeLong(stats.uptimeMillis)
+ .writeLong(stats.completedCount)
+ .build();
+ result.add(event);
+ }
+ }
+
+ return result;
+ }
+
+ private static final String TAG = "BatteryStatsPulledMetrics";
+
+ private final StatsPullCallbackHandler mStatsPullCallbackHandler =
+ new StatsPullCallbackHandler();
+
+ private boolean mIsInitialized = false;
+
+ public void initialize(Context context) {
+ if (mIsInitialized) {
+ return;
+ }
+
+ final StatsManager statsManager = context.getSystemService(StatsManager.class);
+ if (statsManager == null) {
+ Log.e(
+ TAG,
+ "Error retrieving StatsManager. Cannot initialize BatteryStatsPulledMetrics.");
+ } else {
+ Log.d(TAG, "Registering callback with StatsManager");
+
+ // DIRECT_EXECUTOR means that callback will run on binder thread.
+ statsManager.setPullAtomCallback(
+ FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO,
+ null /* metadata */,
+ ConcurrentUtils.DIRECT_EXECUTOR,
+ mStatsPullCallbackHandler);
+ mIsInitialized = true;
+ }
+ }
+
+ private class StatsPullCallbackHandler implements StatsManager.StatsPullAtomCallback {
+ @Override
+ public int onPullAtom(int atomTag, List<StatsEvent> data) {
+ // handle the tags appropriately.
+ List<StatsEvent> events = pullEvents(atomTag);
+ if (events == null) {
+ return StatsManager.PULL_SKIP;
+ }
+
+ data.addAll(events);
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ private List<StatsEvent> pullEvents(int atomTag) {
+ switch (atomTag) {
+ case FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO:
+ return pullFrameworkWakelockInfoAtoms();
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 31f4d08..74aa908 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5877,6 +5877,7 @@
return;
}
+ final State prevState = mState;
mState = state;
if (getTaskFragment() != null) {
@@ -5917,6 +5918,14 @@
mAtmService.updateBatteryStats(this, false);
mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
break;
+ case STOPPING:
+ // It is possible that an Activity is scheduled to be STOPPED directly from RESUMED
+ // state. Updating the PAUSED usage state in that case, since the Activity will be
+ // STOPPED while cycled through the PAUSED state.
+ if (prevState == RESUMED) {
+ mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
+ }
+ break;
case STOPPED:
mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
if (mDisplayContent != null) {
diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
index 1a8f5fc..fcf88d3 100644
--- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
+++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
@@ -36,7 +36,7 @@
import android.os.SystemProperties;
import android.util.Size;
import android.view.Gravity;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import java.util.function.Consumer;
diff --git a/services/core/java/com/android/server/wm/DesktopModeHelper.java b/services/core/java/com/android/server/wm/DesktopModeHelper.java
index b5ea0bd..6bf1c46 100644
--- a/services/core/java/com/android/server/wm/DesktopModeHelper.java
+++ b/services/core/java/com/android/server/wm/DesktopModeHelper.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.os.SystemProperties;
-import android.window.flags.DesktopModeFlags;
+import android.window.DesktopModeFlags;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index af57c84..95cf6bc 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -36,7 +36,7 @@
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.window.TaskFragmentAnimationParams.DEFAULT_ANIMATION_BACKGROUND_COLOR;
-import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
+import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ANIM;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index d91f154..58f0ab4 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -1872,6 +1872,60 @@
}
@Test
+ public void testPeakRefreshRate_notAppliedToExternalDisplays() {
+ when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
+ .thenReturn(true);
+ mInjector.mDisplayInfo.type = Display.TYPE_EXTERNAL;
+ DisplayModeDirector director =
+ new DisplayModeDirector(mContext, mHandler, mInjector,
+ mDisplayManagerFlags, mDisplayDeviceConfigProvider);
+ director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
+ director.getDisplayObserver().onDisplayAdded(DISPLAY_ID);
+ director.getDisplayObserver().onDisplayAdded(DISPLAY_ID_2);
+
+ Display.Mode[] modes1 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 130),
+ };
+ Display.Mode[] modes2 = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720,
+ /* refreshRate= */ 140),
+ };
+ SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
+ supportedModesByDisplay.put(DISPLAY_ID, modes1);
+ supportedModesByDisplay.put(DISPLAY_ID_2, modes2);
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+ director.start(sensorManager);
+ director.injectSupportedModesByDisplay(supportedModesByDisplay);
+
+ // Disable Smooth Display
+ setPeakRefreshRate(RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+
+ Vote vote1 = director.getVote(DISPLAY_ID,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ Vote vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertThat(vote1).isNull();
+ assertThat(vote2).isNull();
+
+ // Enable Smooth Display
+ setPeakRefreshRate(Float.POSITIVE_INFINITY);
+
+ vote1 = director.getVote(DISPLAY_ID,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ vote2 = director.getVote(DISPLAY_ID_2,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertThat(vote1).isNull();
+ assertThat(vote2).isNull();
+ }
+
+ @Test
public void testPeakRefreshRate_DisplayChanged() {
when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
.thenReturn(true);
@@ -1968,8 +2022,9 @@
@Test
@Parameters({
"true, true, 60",
- "false, true, 50",
- "true, false, 50"
+ "false, true, 60",
+ "true, false, 50",
+ "false, false, 50"
})
public void testExternalDisplayMaxRefreshRate(boolean isRefreshRateSynchronizationEnabled,
boolean isExternalDisplay, float expectedMaxRenderFrameRate) {
@@ -3810,6 +3865,7 @@
SensorManagerInternal sensorManagerInternal) {
mDeviceConfig = new FakeDeviceConfig();
mDisplayInfo = new DisplayInfo();
+ mDisplayInfo.type = Display.TYPE_INTERNAL;
mDisplayInfo.defaultModeId = MODE_ID;
mDisplayInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
800, 600, /* refreshRate= */ 60)};
@@ -3856,6 +3912,7 @@
@Override
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.displayId = displayId;
return mDisplayInfoValid;
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
index 5e240cf..e3f150e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
@@ -189,6 +189,7 @@
@Test
public void testExternalDisplay_voteUserPreferredMode() {
when(mDisplayManagerFlags.isUserPreferredModeVoteEnabled()).thenReturn(true);
+ when(mDisplayManagerFlags.isUserRefreshRateForExternalDisplayEnabled()).thenReturn(false);
var preferredMode = mExternalDisplayModes[5];
mExternalDisplayUserPreferredModeId = preferredMode.getModeId();
var expectedVote = Vote.forSize(
@@ -229,6 +230,108 @@
.isEqualTo(null);
}
+ /** Vote for user preferred mode */
+ @Test
+ public void testDefaultDisplay_voteUserPreferredMode() {
+ when(mDisplayManagerFlags.isUserPreferredModeVoteEnabled()).thenReturn(true);
+ when(mDisplayManagerFlags.isUserRefreshRateForExternalDisplayEnabled()).thenReturn(true);
+ var preferredMode = mInternalDisplayModes[5];
+ mInternalDisplayUserPreferredModeId = preferredMode.getModeId();
+ var expectedVote = Vote.forSize(
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight());
+ init();
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ mObserver.onDisplayAdded(EXTERNAL_DISPLAY);
+ mObserver.onDisplayAdded(DEFAULT_DISPLAY);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(expectedVote);
+
+ mInternalDisplayUserPreferredModeId = INVALID_MODE_ID;
+ mObserver.onDisplayChanged(EXTERNAL_DISPLAY);
+ mObserver.onDisplayChanged(DEFAULT_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+
+ preferredMode = mInternalDisplayModes[4];
+ mInternalDisplayUserPreferredModeId = preferredMode.getModeId();
+ expectedVote = Vote.forSize(
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight());
+ mObserver.onDisplayChanged(EXTERNAL_DISPLAY);
+ mObserver.onDisplayChanged(DEFAULT_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(expectedVote);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+
+ // Testing that the vote is removed.
+ mObserver.onDisplayRemoved(EXTERNAL_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(expectedVote);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ }
+
+ /** Vote for user preferred mode with refresh rate, synchronization vote must be disabled */
+ @Test
+ public void testExternalDisplay_voteUserPreferredMode_withRefreshRate() {
+ when(mDisplayManagerFlags.isUserPreferredModeVoteEnabled()).thenReturn(true);
+ when(mDisplayManagerFlags.isDisplaysRefreshRatesSynchronizationEnabled()).thenReturn(false);
+ when(mDisplayManagerFlags.isUserRefreshRateForExternalDisplayEnabled()).thenReturn(true);
+ var preferredMode = mExternalDisplayModes[5];
+ mExternalDisplayUserPreferredModeId = preferredMode.getModeId();
+ var expectedVote = Vote.forSizeAndPhysicalRefreshRatesRange(
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight(),
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight(),
+ preferredMode.getRefreshRate(),
+ preferredMode.getRefreshRate());
+ init();
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ mObserver.onDisplayAdded(EXTERNAL_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(expectedVote);
+
+ mExternalDisplayUserPreferredModeId = INVALID_MODE_ID;
+ mObserver.onDisplayChanged(EXTERNAL_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+
+ preferredMode = mExternalDisplayModes[4];
+ mExternalDisplayUserPreferredModeId = preferredMode.getModeId();
+ expectedVote = Vote.forSizeAndPhysicalRefreshRatesRange(
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight(),
+ preferredMode.getPhysicalWidth(),
+ preferredMode.getPhysicalHeight(),
+ preferredMode.getRefreshRate(),
+ preferredMode.getRefreshRate());
+ mObserver.onDisplayChanged(EXTERNAL_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(expectedVote);
+
+ // Testing that the vote is removed.
+ mObserver.onDisplayRemoved(EXTERNAL_DISPLAY);
+ assertThat(getVote(DEFAULT_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ assertThat(getVote(EXTERNAL_DISPLAY, PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE))
+ .isEqualTo(null);
+ }
+
/** External display: Do not apply limit to user preferred mode */
@Test
public void testExternalDisplay_doNotApplyLimitToUserPreferredMode() {
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index d6ca10a..d9e071f 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -27,6 +27,9 @@
"servicestests-utils",
"platform-test-annotations",
"flag-junit",
+ "statsdprotolite",
+ "StatsdTestUtils",
+ "platformprotoslite",
],
libs: [
@@ -74,6 +77,10 @@
"src/com/android/server/power/stats/format/*.java",
"src/com/android/server/power/stats/processor/*.java",
],
+ // TODO(b/372292543): Enable this test.
+ exclude_srcs: [
+ "src/com/android/server/power/stats/WakelockStatsFrameworkEventsTest.java",
+ ],
java_resources: [
"res/xml/power_profile*.xml",
],
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WakelockStatsFrameworkEventsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WakelockStatsFrameworkEventsTest.java
new file mode 100644
index 0000000..cb644db
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WakelockStatsFrameworkEventsTest.java
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.WakeLockLevelEnum;
+import android.util.StatsEvent;
+import android.util.StatsEventTestUtils;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.os.AtomsProto;
+import com.android.os.framework.FrameworkExtensionAtoms;
+import com.android.os.framework.FrameworkExtensionAtoms.FrameworkWakelockInfo;
+
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.ExtensionRegistryLite;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WakelockStatsFrameworkEventsTest {
+ private WakelockStatsFrameworkEvents mEvents;
+ private ExtensionRegistryLite mRegistry;
+
+ @Before
+ public void setup() {
+ mEvents = new WakelockStatsFrameworkEvents();
+ mRegistry = ExtensionRegistryLite.newInstance();
+ FrameworkExtensionAtoms.registerAllExtensions(mRegistry);
+ }
+
+ private static final int UID_1 = 1;
+ private static final int UID_2 = 2;
+
+ private static final String TAG_1 = "TAG1";
+ private static final String TAG_2 = "TAG2";
+
+ private static final WakeLockLevelEnum WAKELOCK_TYPE_1 = WakeLockLevelEnum.PARTIAL_WAKE_LOCK;
+ private static final WakeLockLevelEnum WAKELOCK_TYPE_2 = WakeLockLevelEnum.DOZE_WAKE_LOCK;
+
+ private static final long TS_1 = 1000;
+ private static final long TS_2 = 2000;
+ private static final long TS_3 = 3000;
+ private static final long TS_4 = 4000;
+ private static final long TS_5 = 5000;
+
+ // Assumes that mEvents is empty.
+ private void makeMetricsAlmostOverflow() throws Exception {
+ for (int i = 0; i < mEvents.SUMMARY_THRESHOLD - 1; i++) {
+ String tag = "forceOverflow" + i;
+ mEvents.noteStartWakeLock(UID_1, tag, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(UID_1, tag, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ }
+
+ assertFalse("not overflow", mEvents.inOverflow());
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo notOverflowInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.OVERFLOW_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("not overflow", notOverflowInfo, null);
+
+ // Add one more to hit an overflow state.
+ String lastTag = "forceOverflowLast";
+ mEvents.noteStartWakeLock(UID_1, lastTag, WAKELOCK_TYPE_2.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(UID_1, lastTag, WAKELOCK_TYPE_2.getNumber(), TS_2);
+
+ assertTrue("overflow", mEvents.inOverflow());
+ info = pullResults(TS_4);
+
+ FrameworkWakelockInfo tag1Info =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(lastTag))
+ .findFirst()
+ .orElse(null);
+
+ assertTrue("lastTag found", tag1Info != null);
+ assertEquals("uid", UID_1, tag1Info.getAttributionUid());
+ assertEquals("tag", lastTag, tag1Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_2, tag1Info.getType());
+ assertEquals("duration", TS_2 - TS_1, tag1Info.getUptimeMillis());
+ assertEquals("count", 1, tag1Info.getCompletedCount());
+ }
+
+ // Assumes that mEvents is empty.
+ private void makeMetricsAlmostHardCap() throws Exception {
+ for (int i = 0; i < mEvents.MAX_WAKELOCK_DIMENSIONS - 1; i++) {
+ mEvents.noteStartWakeLock(i /* uid */, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(i /* uid */, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ }
+
+ assertFalse("not hard capped", mEvents.inHardCap());
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo notOverflowInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.HARD_CAP_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("not overflow", notOverflowInfo, null);
+
+ // Add one more to hit an hardcap state.
+ int hardCapUid = mEvents.MAX_WAKELOCK_DIMENSIONS;
+ mEvents.noteStartWakeLock(hardCapUid, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(hardCapUid, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_2);
+
+ assertTrue("hard capped", mEvents.inHardCap());
+ info = pullResults(TS_4);
+
+ FrameworkWakelockInfo tag2Info =
+ info.stream()
+ .filter(i -> i.getAttributionUid() == hardCapUid)
+ .findFirst()
+ .orElse(null);
+
+ assertTrue("hardCapUid found", tag2Info != null);
+ assertEquals("uid", hardCapUid, tag2Info.getAttributionUid());
+ assertEquals("tag", mEvents.OVERFLOW_TAG, tag2Info.getAttributionTag());
+ assertEquals(
+ "type", WakeLockLevelEnum.forNumber(mEvents.OVERFLOW_LEVEL), tag2Info.getType());
+ assertEquals("duration", TS_2 - TS_1, tag2Info.getUptimeMillis());
+ assertEquals("count", 1, tag2Info.getCompletedCount());
+ }
+
+ private ArrayList<FrameworkWakelockInfo> pullResults(long timestamp) throws Exception {
+ ArrayList<FrameworkWakelockInfo> result = new ArrayList<>();
+ List<StatsEvent> events = mEvents.pullFrameworkWakelockInfoAtoms(timestamp);
+
+ for (StatsEvent e : events) {
+ // The returned atom does not have external extensions registered.
+ // So we serialize and then deserialize with extensions registered.
+ AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(e);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedos = CodedOutputStream.newInstance(outputStream);
+ atom.writeTo(codedos);
+ codedos.flush();
+
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+ CodedInputStream codedis = CodedInputStream.newInstance(inputStream);
+ AtomsProto.Atom atomWithExtensions = AtomsProto.Atom.parseFrom(codedis, mRegistry);
+
+ assertTrue(
+ atomWithExtensions.hasExtension(FrameworkExtensionAtoms.frameworkWakelockInfo));
+ FrameworkWakelockInfo info =
+ atomWithExtensions.getExtension(FrameworkExtensionAtoms.frameworkWakelockInfo);
+ result.add(info);
+ }
+
+ return result;
+ }
+
+ @Test
+ public void singleWakelock() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_2);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_3);
+
+ assertEquals("size", 1, info.size());
+ assertEquals("uid", UID_1, info.get(0).getAttributionUid());
+ assertEquals("tag", TAG_1, info.get(0).getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, info.get(0).getType());
+ assertEquals("duration", TS_2 - TS_1, info.get(0).getUptimeMillis());
+ assertEquals("count", 1, info.get(0).getCompletedCount());
+ }
+
+ @Test
+ public void wakelockOpen() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_3);
+
+ assertEquals("size", 1, info.size());
+ assertEquals("uid", UID_1, info.get(0).getAttributionUid());
+ assertEquals("tag", TAG_1, info.get(0).getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, info.get(0).getType());
+ assertEquals("duration", TS_3 - TS_1, info.get(0).getUptimeMillis());
+ assertEquals("count", 0, info.get(0).getCompletedCount());
+ }
+
+ @Test
+ public void wakelockOpenOverlap() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_3);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+
+ assertEquals("size", 1, info.size());
+ assertEquals("uid", UID_1, info.get(0).getAttributionUid());
+ assertEquals("tag", TAG_1, info.get(0).getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, info.get(0).getType());
+ assertEquals("duration", TS_4 - TS_1, info.get(0).getUptimeMillis());
+ assertEquals("count", 0, info.get(0).getCompletedCount());
+ }
+
+ @Test
+ public void testOverflow() throws Exception {
+ makeMetricsAlmostOverflow();
+
+ // This one gets tagged as an overflow.
+ mEvents.noteStartWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_2);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo overflowInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.OVERFLOW_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("uid", UID_1, overflowInfo.getAttributionUid());
+ assertEquals(
+ "type",
+ WakeLockLevelEnum.forNumber(mEvents.OVERFLOW_LEVEL),
+ overflowInfo.getType());
+ assertEquals("duration", TS_2 - TS_1, overflowInfo.getUptimeMillis());
+ assertEquals("count", 1, overflowInfo.getCompletedCount());
+ }
+
+ @Test
+ public void testOverflowOpen() throws Exception {
+ makeMetricsAlmostOverflow();
+
+ // This is the open wakelock that overflows.
+ mEvents.noteStartWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_1);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo overflowInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.OVERFLOW_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("uid", UID_1, overflowInfo.getAttributionUid());
+ assertEquals(
+ "type",
+ WakeLockLevelEnum.forNumber(mEvents.OVERFLOW_LEVEL),
+ overflowInfo.getType());
+ assertEquals("duration", (TS_4 - TS_1), overflowInfo.getUptimeMillis());
+ assertEquals("count", 0, overflowInfo.getCompletedCount());
+ }
+
+ @Test
+ public void testHardCap() throws Exception {
+ makeMetricsAlmostHardCap();
+
+ // This one gets tagged as a hard cap.
+ mEvents.noteStartWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_1);
+ mEvents.noteStopWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_2);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo hardCapInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.HARD_CAP_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("uid", mEvents.HARD_CAP_UID, hardCapInfo.getAttributionUid());
+ assertEquals(
+ "type",
+ WakeLockLevelEnum.forNumber(mEvents.OVERFLOW_LEVEL),
+ hardCapInfo.getType());
+ assertEquals("duration", TS_2 - TS_1, hardCapInfo.getUptimeMillis());
+ assertEquals("count", 1, hardCapInfo.getCompletedCount());
+ }
+
+ @Test
+ public void testHardCapOpen() throws Exception {
+ makeMetricsAlmostHardCap();
+
+ // This is the open wakelock that overflows.
+ mEvents.noteStartWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_2.getNumber(), TS_1);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_4);
+ FrameworkWakelockInfo hardCapInfo =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(mEvents.HARD_CAP_TAG))
+ .findFirst()
+ .orElse(null);
+
+ assertEquals("uid", mEvents.HARD_CAP_UID, hardCapInfo.getAttributionUid());
+ assertEquals(
+ "type",
+ WakeLockLevelEnum.forNumber(mEvents.OVERFLOW_LEVEL),
+ hardCapInfo.getType());
+ assertEquals("duration", (TS_4 - TS_1), hardCapInfo.getUptimeMillis());
+ assertEquals("count", 0, hardCapInfo.getCompletedCount());
+ }
+
+ @Test
+ public void overlappingWakelocks() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_3);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_4);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_5);
+
+ assertEquals("size", 1, info.size());
+ assertEquals("uid", UID_1, info.get(0).getAttributionUid());
+ assertEquals("tag", TAG_1, info.get(0).getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, info.get(0).getType());
+ assertEquals("duration", TS_4 - TS_1, info.get(0).getUptimeMillis());
+ assertEquals("count", 1, info.get(0).getCompletedCount());
+ }
+
+ @Test
+ public void diffUid() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStartWakeLock(UID_2, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ mEvents.noteStopWakeLock(UID_2, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_3);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_4);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_5);
+ assertEquals("size", 2, info.size());
+
+ FrameworkWakelockInfo uid1Info =
+ info.stream().filter(i -> i.getAttributionUid() == UID_1).findFirst().orElse(null);
+
+ assertTrue("UID_1 found", uid1Info != null);
+ assertEquals("uid", UID_1, uid1Info.getAttributionUid());
+ assertEquals("tag", TAG_1, uid1Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, uid1Info.getType());
+ assertEquals("duration", TS_4 - TS_1, uid1Info.getUptimeMillis());
+ assertEquals("count", 1, uid1Info.getCompletedCount());
+
+ FrameworkWakelockInfo uid2Info =
+ info.stream().filter(i -> i.getAttributionUid() == UID_2).findFirst().orElse(null);
+ assertTrue("UID_2 found", uid2Info != null);
+ assertEquals("uid", UID_2, uid2Info.getAttributionUid());
+ assertEquals("tag", TAG_1, uid2Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, uid2Info.getType());
+ assertEquals("duration", TS_3 - TS_2, uid2Info.getUptimeMillis());
+ assertEquals("count", 1, uid2Info.getCompletedCount());
+ }
+
+ @Test
+ public void diffTag() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStartWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_1.getNumber(), TS_2);
+ mEvents.noteStopWakeLock(UID_1, TAG_2, WAKELOCK_TYPE_1.getNumber(), TS_3);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_4);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_5);
+ assertEquals("size", 2, info.size());
+
+ FrameworkWakelockInfo uid1Info =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(TAG_1))
+ .findFirst()
+ .orElse(null);
+
+ assertTrue("TAG_1 found", uid1Info != null);
+ assertEquals("uid", UID_1, uid1Info.getAttributionUid());
+ assertEquals("tag", TAG_1, uid1Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, uid1Info.getType());
+ assertEquals("duration", TS_4 - TS_1, uid1Info.getUptimeMillis());
+ assertEquals("count", 1, uid1Info.getCompletedCount());
+
+ FrameworkWakelockInfo uid2Info =
+ info.stream()
+ .filter(i -> i.getAttributionTag().equals(TAG_2))
+ .findFirst()
+ .orElse(null);
+ assertTrue("TAG_2 found", uid2Info != null);
+ assertEquals("uid", UID_1, uid2Info.getAttributionUid());
+ assertEquals("tag", TAG_2, uid2Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, uid2Info.getType());
+ assertEquals("duration", TS_3 - TS_2, uid2Info.getUptimeMillis());
+ assertEquals("count", 1, uid2Info.getCompletedCount());
+ }
+
+ @Test
+ public void diffType() throws Exception {
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_1);
+ mEvents.noteStartWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_2.getNumber(), TS_2);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_2.getNumber(), TS_3);
+ mEvents.noteStopWakeLock(UID_1, TAG_1, WAKELOCK_TYPE_1.getNumber(), TS_4);
+
+ ArrayList<FrameworkWakelockInfo> info = pullResults(TS_5);
+ assertEquals("size", 2, info.size());
+
+ FrameworkWakelockInfo uid1Info =
+ info.stream().filter(i -> i.getType() == WAKELOCK_TYPE_1).findFirst().orElse(null);
+
+ assertTrue("WAKELOCK_TYPE_1 found", uid1Info != null);
+ assertEquals("uid", UID_1, uid1Info.getAttributionUid());
+ assertEquals("tag", TAG_1, uid1Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_1, uid1Info.getType());
+ assertEquals("duration", TS_4 - TS_1, uid1Info.getUptimeMillis());
+ assertEquals("count", 1, uid1Info.getCompletedCount());
+
+ FrameworkWakelockInfo uid2Info =
+ info.stream().filter(i -> i.getType() == WAKELOCK_TYPE_2).findFirst().orElse(null);
+ assertTrue("WAKELOCK_TYPE_2 found", uid2Info != null);
+ assertEquals("uid", UID_1, uid2Info.getAttributionUid());
+ assertEquals("tag", TAG_1, uid2Info.getAttributionTag());
+ assertEquals("type", WAKELOCK_TYPE_2, uid2Info.getType());
+ assertEquals("duration", TS_3 - TS_2, uid2Info.getUptimeMillis());
+ assertEquals("count", 1, uid2Info.getCompletedCount());
+ }
+}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index c645c08..2724149 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -113,7 +113,6 @@
<uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
- <uses-permission android:name="android.permission.CREATE_VIRTUAL_DEVICE" />
<queries>
<package android:name="com.android.servicestests.apps.suspendtestapp" />
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
index 840e5c5..c970a3e 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
@@ -65,6 +65,7 @@
VirtualDeviceRule.withAdditionalPermissions(
Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE,
Manifest.permission.GET_APP_OPS_STATS
);
private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsDeviceAwareServiceTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsDeviceAwareServiceTest.java
index e3eca6d..7f2327aa 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsDeviceAwareServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsDeviceAwareServiceTest.java
@@ -58,6 +58,7 @@
VirtualDeviceRule.withAdditionalPermissions(
Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE,
Manifest.permission.GET_APP_OPS_STATS);
private static final String ATTRIBUTION_TAG_1 = "attributionTag1";
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index b0846f6..1abd4eb 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -22,14 +22,16 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OnOpNotedListener;
import android.companion.virtual.VirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceParams;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Process;
-import android.virtualdevice.cts.common.VirtualDeviceRule;
+import android.virtualdevice.cts.common.FakeAssociationRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -40,6 +42,8 @@
import org.junit.runner.RunWith;
import org.mockito.InOrder;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Tests watching noted ops.
*/
@@ -47,7 +51,7 @@
@RunWith(AndroidJUnit4.class)
public class AppOpsNotedWatcherTest {
@Rule
- public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault();
+ public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule();
private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
@Test
@@ -115,12 +119,19 @@
public void testWatchNotedOpsForExternalDevice() {
final AppOpsManager.OnOpNotedListener listener = mock(
AppOpsManager.OnOpNotedListener.class);
- final VirtualDeviceManager.VirtualDevice virtualDevice =
- mVirtualDeviceRule.createManagedVirtualDevice();
- final int virtualDeviceId = virtualDevice.getDeviceId();
+ final VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(
+ VirtualDeviceManager.class);
+ AtomicInteger virtualDeviceId = new AtomicInteger();
+ runWithShellPermissionIdentity(() -> {
+ final VirtualDeviceManager.VirtualDevice virtualDevice =
+ virtualDeviceManager.createVirtualDevice(
+ mFakeAssociationRule.getAssociationInfo().getId(),
+ new VirtualDeviceParams.Builder().setName("virtual_device").build());
+ virtualDeviceId.set(virtualDevice.getDeviceId());
+ });
AttributionSource attributionSource = new AttributionSource(Process.myUid(),
getContext().getOpPackageName(), getContext().getAttributionTag(),
- virtualDeviceId);
+ virtualDeviceId.get());
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
@@ -131,7 +142,7 @@
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpNoted(eq(AppOpsManager.OPSTR_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getOpPackageName()),
- eq(getContext().getAttributionTag()), eq(virtualDeviceId),
+ eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()),
eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
appOpsManager.finishOp(getContext().getAttributionSource().getToken(),
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
index d46fb90..8a6ba4d 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
@@ -16,6 +16,8 @@
package com.android.server.appop;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -26,10 +28,11 @@
import android.app.AppOpsManager;
import android.app.AppOpsManager.OnOpStartedListener;
import android.companion.virtual.VirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceParams;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Process;
-import android.virtualdevice.cts.common.VirtualDeviceRule;
+import android.virtualdevice.cts.common.FakeAssociationRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -40,13 +43,15 @@
import org.junit.runner.RunWith;
import org.mockito.InOrder;
+import java.util.concurrent.atomic.AtomicInteger;
+
/** Tests watching started ops. */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AppOpsStartedWatcherTest {
@Rule
- public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault();
+ public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule();
private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
@Test
@@ -119,13 +124,20 @@
@Test
public void testWatchStartedOpsForExternalDevice() {
- final VirtualDeviceManager.VirtualDevice virtualDevice =
- mVirtualDeviceRule.createManagedVirtualDevice();
- final int virtualDeviceId = virtualDevice.getDeviceId();
+ final VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(
+ VirtualDeviceManager.class);
+ AtomicInteger virtualDeviceId = new AtomicInteger();
+ runWithShellPermissionIdentity(() -> {
+ final VirtualDeviceManager.VirtualDevice virtualDevice =
+ virtualDeviceManager.createVirtualDevice(
+ mFakeAssociationRule.getAssociationInfo().getId(),
+ new VirtualDeviceParams.Builder().setName("virtual_device").build());
+ virtualDeviceId.set(virtualDevice.getDeviceId());
+ });
final OnOpStartedListener listener = mock(OnOpStartedListener.class);
AttributionSource attributionSource = new AttributionSource(Process.myUid(),
getContext().getOpPackageName(), getContext().getAttributionTag(),
- virtualDeviceId);
+ virtualDeviceId.get());
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
appOpsManager.startWatchingStarted(new int[]{AppOpsManager.OP_FINE_LOCATION,
@@ -138,7 +150,7 @@
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getOpPackageName()),
- eq(getContext().getAttributionTag()), eq(virtualDeviceId),
+ eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()),
eq(AppOpsManager.OP_FLAG_SELF),
eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
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 98b1191..e6c34ca 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
@@ -50,6 +50,7 @@
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
+import android.Manifest;
import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyManager;
import android.companion.AssociationInfo;
@@ -112,11 +113,10 @@
import android.view.DisplayInfo;
import android.view.KeyEvent;
import android.view.WindowManager;
-import android.virtualdevice.cts.common.VirtualDeviceRule;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import com.android.internal.app.BlockedAppStreamingActivity;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
@@ -224,7 +224,9 @@
public SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
- public VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault();
+ public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ Manifest.permission.CREATE_VIRTUAL_DEVICE);
private Context mContext;
private InputManagerMockHelper mInputManagerMockHelper;
@@ -1067,65 +1069,64 @@
@Test
public void createVirtualDpad_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER));
+ }
}
@Test
public void createVirtualKeyboard_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER));
+ }
}
@Test
public void createVirtualMouse_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER));
+ }
}
@Test
public void createVirtualTouchscreen_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER));
+ }
}
@Test
public void createVirtualNavigationTouchpad_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.createVirtualNavigationTouchpad(
- NAVIGATION_TOUCHPAD_CONFIG,
- BINDER)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG,
+ BINDER));
+ }
}
@Test
public void onAudioSessionStarting_noPermission_failsSecurityException() {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class,
- () -> mDeviceImpl.onAudioSessionStarting(
- DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback)));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class,
+ () -> mDeviceImpl.onAudioSessionStarting(
+ DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback));
+ }
}
@Test
public void onAudioSessionEnded_noPermission_failsSecurityException() {
- // Shell doesn't have CREATE_VIRTUAL_DEVICE permission.
- SystemUtil.runWithShellPermissionIdentity(() ->
- assertThrows(SecurityException.class, () -> mDeviceImpl.onAudioSessionEnded()));
+ try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
+ assertThrows(SecurityException.class, () -> mDeviceImpl.onAudioSessionEnded());
+ }
}
@Test
@@ -2000,4 +2001,18 @@
/* notifyOnDeviceNearby= */ false, /* revoked= */ false, /* pending= */ false,
/* timeApprovedMs= */0, /* lastTimeConnectedMs= */0, /* systemDataSyncFlags= */ -1);
}
+
+ /** Helper class to drop permissions temporarily and restore them at the end of a test. */
+ static final class DropShellPermissionsTemporarily implements AutoCloseable {
+ DropShellPermissionsTemporarily() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Override
+ public void close() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity();
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
index 6c23ff6..c39378f 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
@@ -40,8 +40,6 @@
assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
assertThat(allowResult.getMatchedRules()).isEmpty();
- assertThat(allowResult.getLoggingResponse())
- .isEqualTo(FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED);
}
@Test
@@ -58,9 +56,6 @@
assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
assertThat(allowResult.getMatchedRules()).containsExactly(forceAllowRule);
- assertThat(allowResult.getLoggingResponse())
- .isEqualTo(
- FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED);
}
@Test
@@ -77,8 +72,6 @@
assertThat(denyResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.DENY);
assertThat(denyResult.getMatchedRules()).containsExactly(failedRule);
- assertThat(denyResult.getLoggingResponse())
- .isEqualTo(FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 7e22d74..425bb15 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -1256,8 +1256,7 @@
Manifest.permission.BYPASS_ROLE_QUALIFICATION);
roleManager.setBypassingRoleQualification(true);
- roleManager.addRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
+ roleManager.addRoleHolderAsUser(role, packageName, /* flags = */ 0, user,
mContext.getMainExecutor(), success -> {
if (success) {
latch.countDown();
@@ -1272,9 +1271,9 @@
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
- roleManager.removeRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
- mContext.getMainExecutor(), (aBool) -> {});
+ roleManager.removeRoleHolderAsUser(role, packageName, 0, user,
+ mContext.getMainExecutor(), (aBool) -> {
+ });
roleManager.setBypassingRoleQualification(false);
instrumentation.getUiAutomation()
.dropShellPermissionIdentity();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 3bbc6b2..48bc9d7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -63,13 +63,11 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
-import android.testing.TestableLooper;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -84,7 +82,6 @@
import com.google.android.collect.Lists;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -106,7 +103,6 @@
import java.util.Set;
import java.util.concurrent.CountDownLatch;
-
public class ManagedServicesTest extends UiServiceTestCase {
@Mock
@@ -119,7 +115,6 @@
private ManagedServices.UserProfiles mUserProfiles;
@Mock private DevicePolicyManager mDpm;
Object mLock = new Object();
- private TestableLooper mTestableLooper;
UserInfo mZero = new UserInfo(0, "zero", 0);
UserInfo mTen = new UserInfo(10, "ten", 0);
@@ -147,7 +142,6 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mTestableLooper = new TestableLooper(Looper.getMainLooper());
mContext.setMockPackageManager(mPm);
mContext.addMockSystemService(Context.USER_SERVICE, mUm);
@@ -205,11 +199,6 @@
mIpm, APPROVAL_BY_COMPONENT);
}
- @After
- public void tearDown() throws Exception {
- mTestableLooper.destroy();
- }
-
@Test
public void testBackupAndRestore_migration() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
@@ -899,7 +888,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a", 0, true);
service.reregisterService(cn, 0);
@@ -930,7 +919,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a", 0, false);
service.reregisterService(cn, 0);
@@ -961,7 +950,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a/a", 0, true);
service.reregisterService(cn, 0);
@@ -992,7 +981,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a/a", 0, false);
service.reregisterService(cn, 0);
@@ -1064,77 +1053,6 @@
}
@Test
- public void registerService_bindingDied_rebindIsClearedOnUserSwitch() throws Exception {
- Context context = mock(Context.class);
- PackageManager pm = mock(PackageManager.class);
- ApplicationInfo ai = new ApplicationInfo();
- ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
-
- when(context.getPackageName()).thenReturn(mPkg);
- when(context.getUserId()).thenReturn(mUser.getIdentifier());
- when(context.getPackageManager()).thenReturn(pm);
- when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
-
- ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
- APPROVAL_BY_PACKAGE);
- service = spy(service);
- ComponentName cn = ComponentName.unflattenFromString("a/a");
-
- // Trigger onBindingDied for component when registering
- // => will schedule a rebind in 10 seconds
- when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- ServiceConnection sc = (ServiceConnection) args[1];
- sc.onBindingDied(cn);
- return true;
- });
- service.registerService(cn, 0);
- assertThat(service.isBound(cn, 0)).isFalse();
-
- // Switch to user 10
- service.onUserSwitched(10);
-
- // Check that the scheduled rebind for user 0 was cleared
- mTestableLooper.moveTimeForward(ManagedServices.ON_BINDING_DIED_REBIND_DELAY_MS);
- mTestableLooper.processAllMessages();
- verify(service, never()).reregisterService(any(), anyInt());
- }
-
- @Test
- public void registerService_bindingDied_rebindIsExecutedAfterTimeout() throws Exception {
- Context context = mock(Context.class);
- PackageManager pm = mock(PackageManager.class);
- ApplicationInfo ai = new ApplicationInfo();
- ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
-
- when(context.getPackageName()).thenReturn(mPkg);
- when(context.getUserId()).thenReturn(mUser.getIdentifier());
- when(context.getPackageManager()).thenReturn(pm);
- when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
-
- ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
- APPROVAL_BY_PACKAGE);
- service = spy(service);
- ComponentName cn = ComponentName.unflattenFromString("a/a");
-
- // Trigger onBindingDied for component when registering
- // => will schedule a rebind in 10 seconds
- when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- ServiceConnection sc = (ServiceConnection) args[1];
- sc.onBindingDied(cn);
- return true;
- });
- service.registerService(cn, 0);
- assertThat(service.isBound(cn, 0)).isFalse();
-
- // Check that the scheduled rebind is run
- mTestableLooper.moveTimeForward(ManagedServices.ON_BINDING_DIED_REBIND_DELAY_MS);
- mTestableLooper.processAllMessages();
- verify(service, times(1)).reregisterService(eq(cn), eq(0));
- }
-
- @Test
public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1293,64 +1211,6 @@
}
@Test
- public void testUpgradeAppNoIntentFilterNoRebind() throws Exception {
- Context context = spy(getContext());
- doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any());
-
- ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles,
- mIpm, APPROVAL_BY_COMPONENT);
-
- List<String> packages = new ArrayList<>();
- packages.add("package");
- addExpectedServices(service, packages, 0);
-
- final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1");
- final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2");
-
- // Both components are approved initially
- mExpectedPrimaryComponentNames.clear();
- mExpectedPrimaryPackages.clear();
- mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
- mExpectedSecondaryComponentNames.clear();
- mExpectedSecondaryPackages.clear();
-
- loadXml(service);
-
- //Component package/C1 loses serviceInterface intent filter
- ManagedServices.Config config = service.getConfig();
- when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt()))
- .thenAnswer(new Answer<List<ResolveInfo>>() {
- @Override
- public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
- throws Throwable {
- Object[] args = invocationOnMock.getArguments();
- Intent invocationIntent = (Intent) args[0];
- if (invocationIntent != null) {
- if (invocationIntent.getAction().equals(config.serviceInterface)
- && packages.contains(invocationIntent.getPackage())) {
- List<ResolveInfo> dummyServices = new ArrayList<>();
- ResolveInfo resolveInfo = new ResolveInfo();
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.packageName = invocationIntent.getPackage();
- serviceInfo.name = approvedComponent.getClassName();
- serviceInfo.permission = service.getConfig().bindPermission;
- resolveInfo.serviceInfo = serviceInfo;
- dummyServices.add(resolveInfo);
- return dummyServices;
- }
- }
- return new ArrayList<>();
- }
- });
-
- // Trigger package update
- service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});
-
- assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent));
- assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent));
- }
-
- @Test
public void testSetPackageOrComponentEnabled() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1363,21 +1223,6 @@
"user10package1/K", "user10.3/Component", "user10package2/L",
"user10.4/Component"}));
- // mock permissions for services
- PackageManager pm = mock(PackageManager.class);
- when(getContext().getPackageManager()).thenReturn(pm);
- List<ComponentName> enabledComponents = List.of(
- ComponentName.unflattenFromString("package/Comp"),
- ComponentName.unflattenFromString("package/C2"),
- ComponentName.unflattenFromString("again/M4"),
- ComponentName.unflattenFromString("user10package/B"),
- ComponentName.unflattenFromString("user10/Component"),
- ComponentName.unflattenFromString("user10package1/K"),
- ComponentName.unflattenFromString("user10.3/Component"),
- ComponentName.unflattenFromString("user10package2/L"),
- ComponentName.unflattenFromString("user10.4/Component"));
- mockServiceInfoWithMetaData(enabledComponents, service, pm, new ArrayMap<>());
-
for (int userId : expectedEnabled.keySet()) {
ArrayList<String> expectedForUser = expectedEnabled.get(userId);
for (int i = 0; i < expectedForUser.size(); i++) {
@@ -2099,7 +1944,7 @@
metaDataAutobindAllow.putBoolean(META_DATA_DEFAULT_AUTOBIND, true);
metaDatas.put(cn_allowed, metaDataAutobindAllow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_allowed.flattenToString(), 0, true);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2144,7 +1989,7 @@
metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2183,7 +2028,7 @@
metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2254,8 +2099,8 @@
}
private void mockServiceInfoWithMetaData(List<ComponentName> componentNames,
- ManagedServices service, PackageManager packageManager,
- ArrayMap<ComponentName, Bundle> metaDatas) throws RemoteException {
+ ManagedServices service, ArrayMap<ComponentName, Bundle> metaDatas)
+ throws RemoteException {
when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer(
(Answer<ServiceInfo>) invocation -> {
ComponentName invocationCn = invocation.getArgument(0);
@@ -2270,39 +2115,6 @@
return null;
}
);
-
- // add components to queryIntentServicesAsUser response
- final List<String> packages = new ArrayList<>();
- for (ComponentName cn: componentNames) {
- packages.add(cn.getPackageName());
- }
- ManagedServices.Config config = service.getConfig();
- when(packageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).
- thenAnswer(new Answer<List<ResolveInfo>>() {
- @Override
- public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
- throws Throwable {
- Object[] args = invocationOnMock.getArguments();
- Intent invocationIntent = (Intent) args[0];
- if (invocationIntent != null) {
- if (invocationIntent.getAction().equals(config.serviceInterface)
- && packages.contains(invocationIntent.getPackage())) {
- List<ResolveInfo> dummyServices = new ArrayList<>();
- for (ComponentName cn: componentNames) {
- ResolveInfo resolveInfo = new ResolveInfo();
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.packageName = invocationIntent.getPackage();
- serviceInfo.name = cn.getClassName();
- serviceInfo.permission = service.getConfig().bindPermission;
- resolveInfo.serviceInfo = serviceInfo;
- dummyServices.add(resolveInfo);
- }
- return dummyServices;
- }
- }
- return new ArrayList<>();
- }
- });
}
private void resetComponentsAndPackages() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index 7e4ae67..797b95b5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -25,7 +25,6 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertNull;
-
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
@@ -194,8 +193,6 @@
public void testWriteXml_userTurnedOffNAS() throws Exception {
int userId = ActivityManager.getCurrentUser();
- doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId));
-
mAssistants.loadDefaultsFromConfig(true);
mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true,
@@ -401,10 +398,6 @@
public void testSetPackageOrComponentEnabled_onlyOnePackage() throws Exception {
ComponentName component1 = ComponentName.unflattenFromString("package/Component1");
ComponentName component2 = ComponentName.unflattenFromString("package/Component2");
-
- doReturn(true).when(mAssistants).isValidService(eq(component1), eq(mZero.id));
- doReturn(true).when(mAssistants).isValidService(eq(component2), eq(mZero.id));
-
mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
true, true);
verify(mNm, never()).setNotificationAssistantAccessGrantedForUserInternal(
@@ -550,7 +543,6 @@
public void testSetAdjustmentTypeSupportedState() throws Exception {
int userId = ActivityManager.getCurrentUser();
- doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId));
mAssistants.loadDefaultsFromConfig(true);
mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true,
true, true);
@@ -574,7 +566,6 @@
public void testSetAdjustmentTypeSupportedState_readWriteXml_entries() throws Exception {
int userId = ActivityManager.getCurrentUser();
- doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId));
mAssistants.loadDefaultsFromConfig(true);
mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true,
true, true);
@@ -598,7 +589,6 @@
public void testSetAdjustmentTypeSupportedState_readWriteXml_empty() throws Exception {
int userId = ActivityManager.getCurrentUser();
- doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId));
mAssistants.loadDefaultsFromConfig(true);
mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true,
true, true);
diff --git a/tests/graphics/SilkFX/res/layout/view_blur_behind.xml b/tests/graphics/SilkFX/res/layout/view_blur_behind.xml
new file mode 100644
index 0000000..83b1fa4
--- /dev/null
+++ b/tests/graphics/SilkFX/res/layout/view_blur_behind.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="wowwowwowwowwowwowwowwowwowwowwowwowwowwowwow" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="I'm a little teapot" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="Something. Something." />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="/\\/\\/\\/\\/\\/\\/\\/\\/\\/" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="wowwowwowwowwowwowwowwowwowwowwowwowwowwowwow" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="I'm a little teapot" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="Something. Something." />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="/\\/\\/\\/\\/\\/\\/\\/\\/\\/" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:textSize="24dp"
+ android:text="^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^" />
+
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+
+ <com.android.test.silkfx.materials.BlurBehindContainer
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="#33AAAAAA"
+ android:padding="32dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="48dp"
+ android:text="Blur!" />
+
+ </com.android.test.silkfx.materials.BlurBehindContainer>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1024dp" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt
index 59a6078..6b6d3b8 100644
--- a/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -61,7 +61,8 @@
)),
DemoGroup("Materials", listOf(
Demo("Glass", GlassActivity::class),
- Demo("Background Blur", BackgroundBlurActivity::class)
+ Demo("Background Blur", BackgroundBlurActivity::class),
+ Demo("View blur behind", R.layout.view_blur_behind, commonControls = false)
))
)
diff --git a/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/BlurBehindContainer.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/BlurBehindContainer.kt
new file mode 100644
index 0000000..ce6348e
--- /dev/null
+++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/BlurBehindContainer.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.silkfx.materials
+
+import android.content.Context
+import android.graphics.RenderEffect
+import android.graphics.Shader
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+class BlurBehindContainer(context: Context, attributeSet: AttributeSet) : FrameLayout(context, attributeSet) {
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ setBackdropRenderEffect(
+ RenderEffect.createBlurEffect(16.0f, 16.0f, Shader.TileMode.CLAMP))
+ }
+}
\ No newline at end of file