Merge "Prevent activity being destroyed immediately if embedded" into sc-v2-dev
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 45588e8..9eb7bb71 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -3941,6 +3941,10 @@
if (idleUntil) {
mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
+ } else if (mState == STATE_LOCATING) {
+ // Use setExact so we don't keep the GPS active for too long.
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
} else {
if (mConstants.USE_WINDOW_ALARMS) {
mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6e27aff..98e447c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -107,9 +107,13 @@
static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
static constexpr size_t TEXT_POS_LEN_MAX = 16;
+static const int DYNAMIC_COLOR_COUNT = 4;
static const char U_TEXTURE[] = "uTexture";
static const char U_FADE[] = "uFade";
static const char U_CROP_AREA[] = "uCropArea";
+static const char U_START_COLOR_PREFIX[] = "uStartColor";
+static const char U_END_COLOR_PREFIX[] = "uEndColor";
+static const char U_COLOR_PROGRESS[] = "uColorProgress";
static const char A_UV[] = "aUv";
static const char A_POSITION[] = "aPosition";
static const char VERTEX_SHADER_SOURCE[] = R"(
@@ -121,6 +125,28 @@
gl_Position = aPosition;
vUv = aUv;
})";
+static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ uniform sampler2D uTexture;
+ uniform float uFade;
+ uniform float uColorProgress;
+ uniform vec4 uStartColor0;
+ uniform vec4 uStartColor1;
+ uniform vec4 uStartColor2;
+ uniform vec4 uStartColor3;
+ uniform vec4 uEndColor0;
+ uniform vec4 uEndColor1;
+ uniform vec4 uEndColor2;
+ uniform vec4 uEndColor3;
+ varying highp vec2 vUv;
+ void main() {
+ vec4 mask = texture2D(uTexture, vUv);
+ vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress)
+ + mask.g * mix(uStartColor1, uEndColor1, uColorProgress)
+ + mask.b * mix(uStartColor2, uEndColor2, uColorProgress)
+ + mask.a * mix(uStartColor3, uEndColor3, uColorProgress);
+ gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a;
+ })";
static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
precision mediump float;
uniform sampler2D uTexture;
@@ -128,7 +154,7 @@
varying highp vec2 vUv;
void main() {
vec4 color = texture2D(uTexture, vUv);
- gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade);
+ gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a;
})";
static const char TEXT_FRAG_SHADER_SOURCE[] = R"(
precision mediump float;
@@ -212,7 +238,8 @@
requestExit();
}
-static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo) {
+static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo,
+ bool premultiplyAlpha) {
AImageDecoder* decoder = nullptr;
AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder);
if (!decoder) {
@@ -226,6 +253,10 @@
outInfo->stride = AImageDecoder_getMinimumStride(decoder);
outInfo->flags = 0;
+ if (!premultiplyAlpha) {
+ AImageDecoder_setUnpremultipliedRequired(decoder, true);
+ }
+
const size_t size = outInfo->stride * outInfo->height;
void* pixels = malloc(size);
int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size);
@@ -239,13 +270,14 @@
}
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
- const char* name) {
+ const char* name, bool premultiplyAlpha) {
Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
if (asset == nullptr)
return NO_INIT;
AndroidBitmapInfo bitmapInfo;
- void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo);
+ void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo,
+ premultiplyAlpha);
auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free };
asset->close();
@@ -293,9 +325,11 @@
return NO_ERROR;
}
-status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
+status_t BootAnimation::initTexture(FileMap* map, int* width, int* height,
+ bool premultiplyAlpha) {
AndroidBitmapInfo bitmapInfo;
- void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo);
+ void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo,
+ premultiplyAlpha);
auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free };
// FileMap memory is never released until application exit.
@@ -675,9 +709,12 @@
}
void BootAnimation::initShaders() {
+ bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled;
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE);
GLuint imageFragmentShader =
- compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE);
+ compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled
+ ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE
+ : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE);
GLuint textFragmentShader =
compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE);
@@ -869,6 +906,20 @@
return true;
}
+// Parse a color represented as a signed decimal int string.
+// E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6).
+// If the input color string is empty, set color with values in defaultColor.
+static void parseColorDecimalString(const std::string& colorString,
+ float color[3], float defaultColor[3]) {
+ if (colorString == "") {
+ memcpy(color, defaultColor, sizeof(float) * 3);
+ return;
+ }
+ int colorInt = atoi(colorString.c_str());
+ color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r
+ color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g
+ color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b
+}
static bool readFile(ZipFileRO* zip, const char* name, String8& outString) {
ZipEntryRO entry = zip->findEntryByName(name);
@@ -1010,6 +1061,8 @@
return false;
}
char const* s = desString.string();
+ std::string dynamicColoringPartName = "";
+ bool postDynamicColoring = false;
// Parse the description file
for (;;) {
@@ -1028,7 +1081,13 @@
char color[7] = "000000"; // default to black if unspecified
char clockPos1[TEXT_POS_LEN_MAX + 1] = "";
char clockPos2[TEXT_POS_LEN_MAX + 1] = "";
+ char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX];
char pathType;
+ // start colors default to black if unspecified
+ char start_color_0[7] = "000000";
+ char start_color_1[7] = "000000";
+ char start_color_2[7] = "000000";
+ char start_color_3[7] = "000000";
int nextReadPos;
@@ -1043,6 +1102,15 @@
} else {
animation.progressEnabled = false;
}
+ } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s",
+ dynamicColoringPartNameBuffer,
+ start_color_0, start_color_1, start_color_2, start_color_3)) {
+ animation.dynamicColoringEnabled = true;
+ parseColor(start_color_0, animation.startColors[0]);
+ parseColor(start_color_1, animation.startColors[1]);
+ parseColor(start_color_2, animation.startColors[2]);
+ parseColor(start_color_3, animation.startColors[3]);
+ dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer);
} else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n",
&pathType, &count, &pause, path, &nextReadPos) >= 4) {
if (pathType == 'f') {
@@ -1055,6 +1123,16 @@
// "clockPos1=%s, clockPos2=%s",
// pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2);
Animation::Part part;
+ if (path == dynamicColoringPartName) {
+ // Part is specified to use dynamic coloring.
+ part.useDynamicColoring = true;
+ part.postDynamicColoring = false;
+ postDynamicColoring = true;
+ } else {
+ // Part does not use dynamic coloring.
+ part.useDynamicColoring = false;
+ part.postDynamicColoring = postDynamicColoring;
+ }
part.playUntilComplete = pathType == 'c';
part.framesToFadeCount = framesToFadeCount;
part.count = count;
@@ -1262,6 +1340,10 @@
mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);
}
+ if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) {
+ initDynamicColors();
+ }
+
playAnimation(*mAnimation);
if (mTimeCheckThread != nullptr) {
@@ -1315,6 +1397,27 @@
sizeof(quadPositions) / sizeof(quadPositions[0]) / 2);
}
+void BootAnimation::initDynamicColors() {
+ for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) {
+ parseColorDecimalString(
+ android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""),
+ mAnimation->endColors[i], mAnimation->startColors[i]);
+ }
+ glUseProgram(mImageShader);
+ SLOGI("[BootAnimation] Dynamically coloring boot animation.");
+ for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) {
+ float *startColor = mAnimation->startColors[i];
+ float *endColor = mAnimation->endColors[i];
+ glUniform4f(glGetUniformLocation(mImageShader,
+ (U_START_COLOR_PREFIX + std::to_string(i)).c_str()),
+ startColor[0], startColor[1], startColor[2], 1 /* alpha */);
+ glUniform4f(glGetUniformLocation(mImageShader,
+ (U_END_COLOR_PREFIX + std::to_string(i)).c_str()),
+ endColor[0], endColor[1], endColor[2], 1 /* alpha */);
+ }
+ mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS);
+}
+
bool BootAnimation::playAnimation(const Animation& animation) {
const size_t pcount = animation.parts.size();
nsecs_t frameDuration = s2ns(1) / animation.fps;
@@ -1357,6 +1460,14 @@
for (size_t j=0 ; j<fcount ; j++) {
if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;
+ // Color progress is
+ // - the normalized animation progress between [0, 1] for the dynamic coloring part,
+ // - 0 for parts that come before,
+ // - 1 for parts that come after.
+ float colorProgress = part.useDynamicColoring
+ ? (float)j / fcount
+ : (part.postDynamicColoring ? 1 : 0);
+
processDisplayEvents();
const int animationX = (mWidth - animation.width) / 2;
@@ -1371,24 +1482,14 @@
glGenTextures(1, &frame.tid);
glBindTexture(GL_TEXTURE_2D, frame.tid);
int w, h;
- initTexture(frame.map, &w, &h);
+ // Set decoding option to alpha unpremultiplied so that the R, G, B channels
+ // of transparent pixels are preserved.
+ initTexture(frame.map, &w, &h, false /* don't premultiply alpha */);
}
const int xc = animationX + frame.trimX;
const int yc = animationY + frame.trimY;
- Region clearReg(Rect(mWidth, mHeight));
- clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight));
- if (!clearReg.isEmpty()) {
- Region::const_iterator head(clearReg.begin());
- Region::const_iterator tail(clearReg.end());
- glEnable(GL_SCISSOR_TEST);
- while (head != tail) {
- const Rect& r2(*head++);
- glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height());
- glClear(GL_COLOR_BUFFER_BIT);
- }
- glDisable(GL_SCISSOR_TEST);
- }
+ 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 + frame.trimHeight);
@@ -1404,6 +1505,9 @@
glUseProgram(mImageShader);
glUniform1i(mImageTextureLocation, 0);
glUniform1f(mImageFadeLocation, fade);
+ if (animation.dynamicColoringEnabled) {
+ glUniform1f(mImageColorProgressLocation, colorProgress);
+ }
glEnable(GL_BLEND);
drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight);
glDisable(GL_BLEND);
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 7b616d9..0e29621 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -53,7 +53,7 @@
};
struct Font {
- FileMap* map;
+ FileMap* map = nullptr;
Texture texture;
int char_width;
int char_height;
@@ -62,7 +62,7 @@
struct Animation {
struct Frame {
String8 name;
- FileMap* map;
+ FileMap* map = nullptr;
int trimX;
int trimY;
int trimWidth;
@@ -90,6 +90,10 @@
uint8_t* audioData;
int audioLength;
Animation* animation;
+ // Controls if dynamic coloring is enabled for this part.
+ bool useDynamicColoring = false;
+ // Defines if this part is played after the dynamic coloring part.
+ bool postDynamicColoring = false;
bool hasFadingPhase() const {
return !playUntilComplete && framesToFadeCount > 0;
@@ -105,6 +109,10 @@
ZipFileRO* zip;
Font clockFont;
Font progressFont;
+ // Controls if dynamic coloring is enabled for the whole animation.
+ bool dynamicColoringEnabled = false;
+ float startColors[4][3]; // Start colors of dynamic color transition.
+ float endColors[4][3]; // End colors of dynamic color transition.
};
// All callbacks will be called from this class's internal thread.
@@ -163,8 +171,10 @@
int displayEventCallback(int fd, int events, void* data);
void processDisplayEvents();
- status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
- status_t initTexture(FileMap* map, int* width, int* height);
+ status_t initTexture(Texture* texture, AssetManager& asset, const char* name,
+ bool premultiplyAlpha = true);
+ status_t initTexture(FileMap* map, int* width, int* height,
+ bool premultiplyAlpha = true);
status_t initFont(Font* font, const char* fallback);
void initShaders();
bool android();
@@ -194,6 +204,7 @@
void checkExit();
void handleViewport(nsecs_t timestep);
+ void initDynamicColors();
sp<SurfaceComposerClient> mSession;
AssetManager mAssets;
@@ -226,6 +237,7 @@
GLuint mImageTextureLocation;
GLuint mTextCropAreaLocation;
GLuint mTextTextureLocation;
+ GLuint mImageColorProgressLocation;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/OWNERS b/cmds/bootanimation/OWNERS
new file mode 100644
index 0000000..b6fb007
--- /dev/null
+++ b/cmds/bootanimation/OWNERS
@@ -0,0 +1,3 @@
+dupin@google.com
+shanh@google.com
+jreck@google.com
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f6b4374..0732c61 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1133,10 +1133,10 @@
package android.hardware.devicestate {
public final class DeviceStateManager {
- method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
+ method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
method @NonNull public int[] getSupportedStates();
method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
- method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
+ method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
field public static final int MAXIMUM_DEVICE_STATE = 255; // 0xff
field public static final int MINIMUM_DEVICE_STATE = 0; // 0x0
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 2efdf51..db7ab1a 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -207,7 +207,8 @@
}
/**
- * Returns the activity token below in the same task if it belongs to the same process.
+ * Returns the non-finishing activity token below in the same task if it belongs to the same
+ * process.
*/
@Nullable
public IBinder getActivityTokenBelow(IBinder activityToken) {
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index dae565e..67f631f 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -281,6 +281,32 @@
}
/**
+ * Convenience method for callers who need to indicate that some other package or
+ * some other user needs a backup pass. This can be useful in the case of groups of
+ * packages that share a uid and/or have user-specific data.
+ * <p>
+ * This method requires that the application hold the "android.permission.BACKUP"
+ * permission if the package named in the package argument does not run under the
+ * same uid as the caller. This method also requires that the application hold the
+ * "android.permission.INTERACT_ACROSS_USERS_FULL" if the user argument is not the
+ * same as the user the caller is running under.
+ * @param userId The user to back up
+ * @param packageName The package name identifying the application to back up.
+ *
+ * @hide
+ */
+ public static void dataChangedForUser(int userId, String packageName) {
+ checkServiceBinder();
+ if (sService != null) {
+ try {
+ sService.dataChangedForUser(userId, packageName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "dataChanged(userId,pkg) couldn't connect");
+ }
+ }
+ }
+
+ /**
* @deprecated Applications shouldn't request a restore operation using this method. In Android
* P and later, this method is a no-op.
*
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 52dad3e..95892aa 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -75,23 +75,24 @@
/**
* Submits a {@link DeviceStateRequest request} to modify the device state.
* <p>
- * By default, the request is kept active until a call to
- * {@link #cancelRequest(DeviceStateRequest)} or until one of the following occurs:
+ * By default, the request is kept active until one of the following occurs:
* <ul>
+ * <li>The system deems the request can no longer be honored, for example if the requested
+ * state becomes unsupported.
+ * <li>A call to {@link #cancelRequest(DeviceStateRequest)}.
* <li>Another processes submits a request succeeding this request in which case the request
* will be suspended until the interrupting request is canceled.
- * <li>The requested state has become unsupported.
- * <li>The process submitting the request dies.
* </ul>
* However, this behavior can be changed by setting flags on the {@link DeviceStateRequest}.
*
* @throws IllegalArgumentException if the requested state is unsupported.
- * @throws SecurityException if the {@link android.Manifest.permission#CONTROL_DEVICE_STATE}
- * permission is not held.
+ * @throws SecurityException if the caller is neither the current top-focused activity nor if
+ * the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
*
* @see DeviceStateRequest
*/
- @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
+ @RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
+ conditional = true)
public void requestState(@NonNull DeviceStateRequest request,
@Nullable @CallbackExecutor Executor executor,
@Nullable DeviceStateRequest.Callback callback) {
@@ -105,10 +106,11 @@
* This method is noop if the {@code request} has not been submitted with a call to
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
*
- * @throws SecurityException if the {@link android.Manifest.permission#CONTROL_DEVICE_STATE}
- * permission is not held.
+ * @throws SecurityException if the caller is neither the current top-focused activity nor if
+ * the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
*/
- @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
+ @RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
+ conditional = true)
public void cancelRequest(@NonNull DeviceStateRequest request) {
mGlobal.cancelRequest(request);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dc4a747..94d19bc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14981,6 +14981,16 @@
"power_button_long_press";
/**
+ * Override internal R.integer.config_longPressOnPowerDurationMs. It determines the length
+ * of power button press to be considered a long press in milliseconds.
+ * Used by PhoneWindowManager.
+ * @hide
+ */
+ @Readable
+ public static final String POWER_BUTTON_LONG_PRESS_DURATION_MS =
+ "power_button_long_press_duration_ms";
+
+ /**
* Overrides internal R.integer.config_veryLongPressOnPowerBehavior.
* Allowable values detailed in frameworks/base/core/res/res/values/config.xml.
* Used by PhoneWindowManager.
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index e21d775..cca1799 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -44,6 +44,12 @@
// channel and the server input channel will both contain this token.
public IBinder token;
+ /**
+ * The {@link IWindow} handle if InputWindowHandle is associated with a window, null otherwise.
+ */
+ @Nullable
+ private IBinder windowToken;
+
// The window name.
public String name;
@@ -145,6 +151,7 @@
.append(", visible=").append(visible)
.append(", scaleFactor=").append(scaleFactor)
.append(", transform=").append(transform)
+ .append(", windowToken=").append(getWindow())
.toString();
}
@@ -176,4 +183,12 @@
public void setTouchableRegionCrop(@Nullable SurfaceControl bounds) {
touchableRegionSurfaceControl = new WeakReference<>(bounds);
}
+
+ public void setWindowToken(IWindow iwindow) {
+ windowToken = iwindow.asBinder();
+ }
+
+ public IWindow getWindow() {
+ return IWindow.Stub.asInterface(windowToken);
+ }
}
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index bbef3e6..e634d60 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -209,4 +209,41 @@
return Integer.toString(why);
}
}
+
+ /**
+ * How much to multiply the policy's type layer, to reserve room
+ * for multiple windows of the same type and Z-ordering adjustment
+ * with TYPE_LAYER_OFFSET.
+ */
+ int TYPE_LAYER_MULTIPLIER = 10000;
+
+ /**
+ * Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
+ * or below others in the same layer.
+ */
+ int TYPE_LAYER_OFFSET = 1000;
+
+ /**
+ * How much to increment the layer for each window, to reserve room
+ * for effect surfaces between them.
+ */
+ int WINDOW_LAYER_MULTIPLIER = 5;
+
+ /**
+ * Animation thumbnail is as far as possible below the window above
+ * the thumbnail (or in other words as far as possible above the window
+ * below it).
+ */
+ int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
+
+ int SPLIT_DIVIDER_LAYER = TYPE_LAYER_MULTIPLIER * 3;
+ int WATERMARK_LAYER = TYPE_LAYER_MULTIPLIER * 100;
+ int STRICT_MODE_LAYER = TYPE_LAYER_MULTIPLIER * 101;
+ int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
+
+ /**
+ * Layers for screen rotation animation. We put these layers above
+ * WINDOW_FREEZE_LAYER so that screen freeze will cover all windows.
+ */
+ int SCREEN_FREEZE_LAYER_BASE = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER;
}
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index a833591..442d099 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -356,7 +356,11 @@
}
for (int i = 0; i < translatedResult.size(); i++) {
final AutofillId autofillId = new AutofillId(translatedResult.keyAt(i));
- final View view = mViews.get(autofillId).get();
+ final WeakReference<View> viewRef = mViews.get(autofillId);
+ if (viewRef == null) {
+ continue;
+ }
+ final View view = viewRef.get();
if (view == null) {
Log.w(TAG, "onTranslationCompleted: the view for autofill id " + autofillId
+ " may be gone.");
@@ -416,7 +420,11 @@
Log.w(TAG, "No AutofillId is set in ViewTranslationResponse");
continue;
}
- final View view = mViews.get(autofillId).get();
+ final WeakReference<View> viewRef = mViews.get(autofillId);
+ if (viewRef == null) {
+ continue;
+ }
+ final View view = viewRef.get();
if (view == null) {
Log.w(TAG, "onTranslationCompleted: the view for autofill id " + autofillId
+ " may be gone.");
diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java
index b9ed32c..3012e93 100644
--- a/core/java/android/view/translation/UiTranslationManager.java
+++ b/core/java/android/view/translation/UiTranslationManager.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.view.View;
import android.view.autofill.AutofillId;
+import android.widget.TextView;
import com.android.internal.annotations.GuardedBy;
@@ -42,11 +43,50 @@
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
-// TODO(b/178044703): Describe what UI Translation is.
/**
- * The {@link UiTranslationManager} class provides ways for apps to use the ui translation
+ * <p>The {@link UiTranslationManager} class provides ways for apps to use the ui translation
* function in framework.
+ *
+ * <p> The UI translation provides ways for apps to support inline translation for the views. For
+ * example the system supports text translation for {@link TextView}. To support UI translation for
+ * your views, you should override the following methods to provide the content to be translated
+ * and deal with the translated result. Here is an example for {@link TextView}-like views:
+ *
+ * <pre><code>
+ * public class MyTextView extends View {
+ * public MyTextView(...) {
+ * // implements how to show the translated result in your View in
+ * // ViewTranslationCallback and set it by setViewTranslationCallback()
+ * setViewTranslationCallback(new MyViewTranslationCallback());
+ * }
+ *
+ * public void onCreateViewTranslationRequest(int[] supportedFormats,
+ * Consumer<ViewTranslationRequest> requestsCollector) {
+ * // collect the information that needs to be translated
+ * ViewTranslationRequest.Builder requestBuilder =
+ * new ViewTranslationRequest.Builder(getAutofillId());
+ * requestBuilder.setValue(ViewTranslationRequest.ID_TEXT,
+ * TranslationRequestValue.forText(etText()));
+ * requestsCollector.accept(requestBuilder.build());
+ * }
+ *
+ * public void onProvideContentCaptureStructure(
+ * ViewStructure structure, int flags) {
+ * // set ViewTranslationResponse
+ * super.onViewTranslationResponse(response);
+ * }
+ * }
+ * </code></pre>
+ *
+ * <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws the
+ * HTML using {@link android.graphics.Canvas} or native libraries in a different render process),
+ * you must override {@link View#onCreateVirtualViewTranslationRequests(long[], int[], Consumer)} to
+ * provide the content to be translated and implement
+ * {@link View#onVirtualViewTranslationResponses(android.util.LongSparseArray)} for the translated
+ * result. You also need to implement {@link android.view.translation.ViewTranslationCallback} to
+ * handle the translated information show or hide in your {@link View}.
*/
public final class UiTranslationManager {
@@ -248,14 +288,14 @@
}
}
- // TODO(b/178044703): Fix the View API link when it becomes public.
/**
* Register for notifications of UI Translation state changes on the foreground activity. This
* is available to the owning application itself and also the current input method.
* <p>
* The application whose UI is being translated can use this to customize the UI Translation
* behavior in ways that aren't made easy by methods like
- * View#onCreateTranslationRequest().
+ * {@link View#onCreateViewTranslationRequest(int[], Consumer)}.
+ *
* <p>
* Input methods can use this to offer complementary features to UI Translation; for example,
* enabling outgoing message translation when the system is translating incoming messages in a
diff --git a/core/java/android/view/translation/ViewTranslationCallback.java b/core/java/android/view/translation/ViewTranslationCallback.java
index 6efd621..a075662 100644
--- a/core/java/android/view/translation/ViewTranslationCallback.java
+++ b/core/java/android/view/translation/ViewTranslationCallback.java
@@ -19,9 +19,17 @@
import android.annotation.NonNull;
import android.annotation.UiThread;
import android.view.View;
+import android.view.contentcapture.ContentCaptureSession;
/**
- * Callback for handling the translated information show or hide in the {@link View}.
+ * <p> Callback for handling the translated information show or hide in the {@link View}.
+ *
+ * <p> When the platform intelligence starts translation of an app's ui, the system will call
+ * {@link View#dispatchCreateViewTranslationRequest} to collect the {@link ViewTranslationRequest}s
+ * for translation purpose by traversing the hierarchy then send to translation service. After
+ * receiving the {@link ViewTranslationResponse}, the system will call
+ * {@link ViewTranslationCallback#onShowTranslation(View)} to show the translated information for
+ * the {@link View}.
*/
@UiThread
public interface ViewTranslationCallback {
@@ -33,13 +41,19 @@
* method will not be called before {@link View#onViewTranslationResponse} or
* {@link View#onVirtualViewTranslationResponses}.
*
+ * <p> NOTE: For TextView implementation, {@link ContentCaptureSession#notifyViewTextChanged}
+ * shouldn't be called with the translated text, simply calling setText() here will trigger the
+ * method. You should either override {@code View#onProvideContentCaptureStructure()} to report
+ * the original text instead of the translated text or use a different approach to display the
+ * translated text.
+ *
* See {@link View#onViewTranslationResponse} for how to get the translated information.
*
* @return {@code true} if the View handles showing the translation.
*/
boolean onShowTranslation(@NonNull View view);
/**
- * Called when the user wants to show the original text instead of the translated text. This
+ * Called when user wants to view the original content instead of the translated content. This
* method will not be called before {@link View#onViewTranslationResponse} or
* {@link View#onViewTranslationResponse}.
*
@@ -47,7 +61,8 @@
*/
boolean onHideTranslation(@NonNull View view);
/**
- * Called when the user finish the Ui translation and no longer to show the translated text.
+ * Called when the translation state is no longer needed. It should restore the original content
+ * and clear all saved states.
*
* @return {@code true} if the View handles clearing the translation.
*/
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index 671d556..e4ef7d3 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -76,6 +76,7 @@
jfieldID replaceTouchableRegionWithCrop;
WeakRefHandleField touchableRegionSurfaceControl;
jfieldID transform;
+ jfieldID windowToken;
} gInputWindowHandleClassInfo;
static struct {
@@ -215,6 +216,14 @@
mInfo.touchableRegionCropHandle.clear();
}
+ jobject windowTokenObj = env->GetObjectField(obj, gInputWindowHandleClassInfo.windowToken);
+ if (windowTokenObj) {
+ mInfo.windowToken = ibinderForJavaObject(env, windowTokenObj);
+ env->DeleteLocalRef(windowTokenObj);
+ } else {
+ mInfo.windowToken.clear();
+ }
+
env->DeleteLocalRef(obj);
return true;
}
@@ -314,6 +323,9 @@
ScopedLocalRef<jobject> matrixObj(env, AMatrix_newInstance(env, transformVals));
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.transform, matrixObj.get());
+ env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.windowToken,
+ javaObjectForIBinder(env, windowInfo.windowToken));
+
return inputWindowHandle;
}
@@ -441,6 +453,9 @@
GET_FIELD_ID(gInputWindowHandleClassInfo.transform, clazz, "transform",
"Landroid/graphics/Matrix;");
+ GET_FIELD_ID(gInputWindowHandleClassInfo.windowToken, clazz, "windowToken",
+ "Landroid/os/IBinder;");
+
jclass weakRefClazz;
FIND_CLASS(weakRefClazz, "java/lang/ref/Reference");
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c3d1596..6bc00e2 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -771,6 +771,8 @@
optional SettingProto power_manager_constants = 93;
reserved 94; // Used to be priv_app_oob_enabled
+ optional SettingProto power_button_long_press_duration_ms = 154 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
message PrepaidSetup {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -1063,5 +1065,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 154;
+ // Next tag = 155;
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 1bba12f..ba4a5b0 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -79,7 +79,7 @@
optional SettingProto accessibility_magnification_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto button_targets = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_magnification_capability = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // Settings for accessibility button mode (navigation bar or floating action menu).
+ // Settings for accessibility button related config
optional SettingProto accessibility_button_mode = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_floating_menu_size = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_floating_menu_icon_type = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 0310b18..14221dc 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -341,7 +341,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"استرداد محتوى النافذة"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"فحص محتوى نافذة يتم التفاعل معها"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"تفعيل الاستكشاف باللمس"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم قول العناصر التي تم النقر عليها بصوت عال ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم قول العناصر التي تم النقر عليها بصوت عالٍ ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"ملاحظة النص الذي تكتبه"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"يتضمن بيانات شخصية مثل أرقام بطاقات الائتمان وكلمات المرور."</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"التحكم في تكبير الشاشة"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 61fb471..a8ae213 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1369,9 +1369,9 @@
<string name="sms_control_message" msgid="6574313876316388239">"Aplikace <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>odesílá velký počet SMS zpráv. Chcete aplikaci povolit, aby zprávy odesílala i nadále?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"Povolit"</string>
<string name="sms_control_no" msgid="4845717880040355570">"Odmítnout"</string>
- <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> chce odeslat zprávu na adresu <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
+ <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> chce odeslat zprávu na číslo <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
<string name="sms_short_code_details" msgid="2723725738333388351">"Tato akce "<b>"může vést k naúčtování poplatků"</b>" na váš účet u mobilního operátora."</string>
- <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Tato akce povede k naúčtování poplatku na váš účet u mobilního operátora."</b></string>
+ <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Tato akce může vést k naúčtování ceny služby třetí strany na vrub vašeho účtu u mobilního operátora."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Odeslat"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Zrušit"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Zapamatovat moji volbu"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 17382c4..8ae4bc7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -326,12 +326,12 @@
<string name="permgroupdesc_phone" msgid="270048070781478204">"melakukan dan mengelola panggilan telepon"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Sensor tubuh"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"mengakses data sensor tentang tanda-tanda vital"</string>
- <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Mengambil konten jendela"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Memeriksa konten jendela tempat Anda berinteraksi."</string>
+ <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Membaca konten di jendela"</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Memeriksa konten di jendela yang sedang Anda buka."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Mengaktifkan Jelajahi dengan Sentuhan"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Item yang diketuk akan diucapkan dengan jelas dan layar dapat dijelajahi menggunakan gestur."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Mengamati teks yang Anda ketik"</string>
- <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Meliputi data pribadi seperti nomor kartu kredit dan sandi."</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Termasuk data pribadi, seperti nomor kartu kredit dan sandi."</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"Mengontrol perbesaran layar"</string>
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Mengontrol tingkat zoom dan pemosisian layar."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Melakukan isyarat"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6919a3d..316514e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -327,13 +327,13 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Sensori del corpo"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"accedere ai dati dei sensori relativi ai tuoi parametri vitali"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperare contenuti della finestra"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Esaminare i contenuti di una finestra con cui interagisci."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Esamina i contenuti di una finestra con cui interagisci."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Attivare Esplora al tocco"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Gli elementi toccati verranno pronunciati ad alta voce e sarà possibile esplorare lo schermo utilizzando i gesti."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Gli elementi toccati verranno pronunciati ad alta voce e sarà possibile esplorare lo schermo con i gesti."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Osservare il testo digitato"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Sono inclusi dati personali come numeri di carte di credito e password."</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"Controllare l\'ingrandimento del display"</string>
- <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Controlla il livello di zoom e la posizione del display."</string>
+ <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Controlla la posizione e il livello di zoom del display."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Eseguire gesti"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesti con sensore di impronte"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 28522d7..1747bdb 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -471,7 +471,7 @@
<string name="permdesc_readPhoneState" msgid="7229063553502788058">"डिव्हाइस च्या फोन वैशिष्ट्यांवर अॅक्सेस करण्यास ॲपला अनुमती देते. ही परवानगी कॉल ॲक्टिव्हेट असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रिमोट नंबर निर्धारित करण्यासाठी ॲपला अनुमती देते."</string>
<string name="permlab_manageOwnCalls" msgid="9033349060307561370">"प्रणालीच्या माध्यमातून कॉल रूट करा"</string>
<string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"कॉल करण्याचा अनुभव सुधारण्यासाठी ॲपला त्याचे कॉल प्रणालीच्या माध्यमातून रूट करू देते."</string>
- <string name="permlab_callCompanionApp" msgid="3654373653014126884">"सिस्टम वापरून कॉल पाहा आणि नियंत्रण ठेवा."</string>
+ <string name="permlab_callCompanionApp" msgid="3654373653014126884">"सिस्टम वापरून कॉल पहा आणि नियंत्रण ठेवा."</string>
<string name="permdesc_callCompanionApp" msgid="8474168926184156261">"डिव्हाइसवर येणार कॉल पाहण्यासाठी आणि नियंत्रित करण्यासाठी ॲपला अनुमती देते. यामध्ये कॉल करण्यासाठी कॉलचा नंबर आणि कॉलची स्थिती यासारख्या माहितीचा समावेश असतो."</string>
<string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"ऑडिओ रेकॉर्ड प्रतिबंधांपासून मुक्त"</string>
<string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"ऑडिओ रेकॉर्ड करण्यासाठी प्रतिबंधांपासून ॲपला मुक्त करा."</string>
@@ -581,7 +581,7 @@
<string name="fingerprint_acquired_imager_dirty" msgid="5236744087471419479">"सेन्सर साफ करा"</string>
<string name="fingerprint_acquired_too_fast" msgid="6038375140739678098">"जरा जास्त वेळ धरून ठेवा"</string>
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"बोट खूप सावकाश हलविले. कृपया पुन्हा प्रयत्न करा."</string>
- <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"दुसरी फिंगरप्रिंट वापरून पाहा"</string>
+ <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"दुसरी फिंगरप्रिंट वापरून पहा"</string>
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"खूप प्रखर"</string>
<string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"अॅडजस्ट करण्याचा प्रयत्न करा"</string>
<string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"तुमच्या बोटाची स्थिती प्रत्येक वेळी थोडीशी बदला"</string>
@@ -629,7 +629,7 @@
<string name="face_acquired_too_low" msgid="1512237819632165945">"फोन आणखी खाली हलवा."</string>
<string name="face_acquired_too_right" msgid="2513391513020932655">"फोन डावीकडे हलवा."</string>
<string name="face_acquired_too_left" msgid="8882499346502714350">"फोन उजवीकडे हलवा."</string>
- <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"कृपया तुमच्या डिव्हाइसकडे थेट पाहा"</string>
+ <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"कृपया तुमच्या डिव्हाइसकडे थेट पहा"</string>
<string name="face_acquired_not_detected" msgid="2945945257956443257">"तुमचा चेहरा थेट फोन समोर आणा."</string>
<string name="face_acquired_too_much_motion" msgid="8199691445085189528">"खूप हलत आहे. फोन स्थिर धरून ठेवा."</string>
<string name="face_acquired_recalibrate" msgid="8724013080976469746">"कृपया तुमच्या चेहऱ्याची पुन्हा नोंदणी करा."</string>
@@ -1701,9 +1701,9 @@
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> ला तुमचे डिव्हाइसच संपूर्णपणे नियंत्रित करायची अनुमती द्यायची का?"</string>
<string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"तुम्ही <xliff:g id="SERVICE">%1$s</xliff:g> सुरू केल्यास, तुमचे डिव्हाइस डेटा एंक्रिप्शनमध्ये सुधारणा करण्यासाठी स्क्रीन लॉक वापरणार नाही."</string>
<string name="accessibility_service_warning_description" msgid="291674995220940133">"जी ॲप्स तुमच्या ॲक्सेसिबिलिटी गरजा पूर्ण करतात अशा ॲप्ससाठी संपूर्ण नियंत्रण योग्य आहे. पण ते सर्व ॲप्सना लागू होईल असे नाही."</string>
- <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रीन पाहा आणि नियंत्रित करा"</string>
+ <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रीन पहा आणि नियंत्रित करा"</string>
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"ते स्क्रीनवरील सर्व आशय वाचू शकते आणि इतर ॲप्सवर आशय प्रदर्शित करू शकते."</string>
- <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"पाहा आणि क्रिया करा"</string>
+ <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"पहा आणि क्रिया करा"</string>
<string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"तुम्ही ॲप किंवा हार्डवेअर सेन्सर कसे वापरता याचा हे मागोवा घेऊ शकते आणि इतर ॲप्ससोबत तुमच्या वतीने काम करू शकते."</string>
<string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"अनुमती द्या"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"नकार द्या"</string>
@@ -1982,7 +1982,7 @@
<string name="work_mode_turn_on" msgid="3662561662475962285">"सुरू करा"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string>
- <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string>
+ <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेटसाठी तपासा"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"आपल्याकडे नवीन मेसेज आहेत"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"पाहण्यासाठी SMS अॅप उघडा"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index c45ac41..b72b000 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -333,7 +333,7 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Czujniki na ciele"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"dostęp do danych czujnika podstawowych funkcji życiowych"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pobieranie zawartości okna"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Sprawdzanie zawartości okna, z którego korzystasz."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Sprawdzanie zawartości okna, z którego korzystasz."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Włączenie czytania dotykiem"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Klikane elementy będą wymawiane na głos, a ekran można przeglądać, używając gestów."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Obserwowanie wpisywanego tekstu"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 08bf970..3e4f65c 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -105,7 +105,7 @@
<string name="serviceClassFAX" msgid="2561653371698904118">"ఫ్యాక్స్"</string>
<string name="serviceClassSMS" msgid="1547664561704509004">"SMS"</string>
<string name="serviceClassDataAsync" msgid="2029856900898545984">"నిరర్థకం"</string>
- <string name="serviceClassDataSync" msgid="7895071363569133704">"సమకాలీకరణ"</string>
+ <string name="serviceClassDataSync" msgid="7895071363569133704">"సింక్"</string>
<string name="serviceClassPacket" msgid="1430642951399303804">"ప్యాకెట్"</string>
<string name="serviceClassPAD" msgid="6850244583416306321">"PAD"</string>
<string name="roamingText0" msgid="7793257871609854208">"రోమింగ్ సూచిక ఆన్లో ఉంది"</string>
@@ -171,9 +171,9 @@
<string name="httpErrorBadUrl" msgid="754447723314832538">"URL చెల్లనిది అయినందువలన పేజీని తెరవడం సాధ్యపడలేదు."</string>
<string name="httpErrorFile" msgid="3400658466057744084">"ఫైల్ను యాక్సెస్ చేయడం సాధ్యపడలేదు."</string>
<string name="httpErrorFileNotFound" msgid="5191433324871147386">"అభ్యర్థించిన ఫైల్ను కనుగొనడం సాధ్యపడలేదు."</string>
- <string name="httpErrorTooManyRequests" msgid="2149677715552037198">"చాలా ఎక్కువ అభ్యర్థనలు ప్రాసెస్ చేయబడుతున్నాయి. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
+ <string name="httpErrorTooManyRequests" msgid="2149677715552037198">"చాలా ఎక్కువ రిక్వెస్ట్లు ప్రాసెస్ చేయబడుతున్నాయి. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
<string name="notification_title" msgid="5783748077084481121">"<xliff:g id="ACCOUNT">%1$s</xliff:g>కు సైన్ఇన్ ఎర్రర్"</string>
- <string name="contentServiceSync" msgid="2341041749565687871">"సమకాలీకరణ"</string>
+ <string name="contentServiceSync" msgid="2341041749565687871">"సింక్"</string>
<string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"సమకాలీకరించడం సాధ్యపడదు"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"చాలా ఎక్కువ <xliff:g id="CONTENT_TYPE">%s</xliff:g> తొలగించడానికి ప్రయత్నించారు."</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"టాబ్లెట్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైళ్లను తొలగించండి."</string>
@@ -315,7 +315,7 @@
<string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"ఆడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ఫిజికల్ యాక్టివిటీ"</string>
- <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"భౌతిక కార్యకలాపాన్ని యాక్సెస్ చేయండి"</string>
+ <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"భౌతిక యాక్టివిటీని యాక్సెస్ చేయండి"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"కెమెరా"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"సమీపంలోని పరికరాలు"</string>
@@ -349,9 +349,9 @@
<string name="permlab_fullScreenIntent" msgid="4310888199502509104">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్ప్లే చేస్తుంది"</string>
<string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్ప్లే చేయడానికి యాప్ను అనుమతిస్తుంది"</string>
<string name="permlab_install_shortcut" msgid="7451554307502256221">"షార్ట్కట్లను ఇన్స్టాల్ చేయడం"</string>
- <string name="permdesc_install_shortcut" msgid="4476328467240212503">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్స్క్రీన్ సత్వరమార్గాలను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"సత్వరమార్గాలను అన్ఇన్స్టాల్ చేయడం"</string>
- <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్స్క్రీన్ సత్వరమార్గాలను తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permdesc_install_shortcut" msgid="4476328467240212503">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్స్క్రీన్ షార్ట్కట్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"షార్ట్కట్లను అన్ఇన్స్టాల్ చేయడం"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్స్క్రీన్ షార్ట్కట్లను తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"అవుట్గోయింగ్ కాల్స్ను దారి మళ్లించడం"</string>
<string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"కాల్ను వేరే నంబర్కు దారి మళ్లించే లేదా మొత్తంగా కాల్ను ఆపివేసే ఎంపిక సహాయంతో అవుట్గోయింగ్ కాల్ సమయంలో డయల్ చేయబడుతున్న నంబర్ను చూడటానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"ఫోన్ కాల్స్కు సమాధానమివ్వు"</string>
@@ -500,9 +500,9 @@
<string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"మీ Android TV పరికరం సమయ మండలిని మార్చడానికి యాప్ని అనుమతిస్తుంది."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"ఫోన్ యొక్క సమయ మండలిని మార్చడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"పరికరంలో ఖాతాలను కనుగొనడం"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"టాబ్లెట్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"మీ Android TV పరికరానికి తెలిసిన ఖాతాల జాబితాను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
- <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"ఫోన్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"టాబ్లెట్కు తెలిసిన ఖాతాల లిస్ట్ను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"మీ Android TV పరికరానికి తెలిసిన ఖాతాల లిస్ట్ను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"ఫోన్కు తెలిసిన ఖాతాల లిస్ట్ను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"నెట్వర్క్ కనెక్షన్లను వీక్షించడం"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"ఏ నెట్వర్క్లు ఉన్నాయి మరియు కనెక్ట్ చేయబడ్డాయి వంటి నెట్వర్క్ కనెక్షన్ల గురించి సమాచారాన్ని వీక్షించడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"నెట్వర్క్ను పూర్తిగా యాక్సెస్ చేయగలగడం"</string>
@@ -516,9 +516,9 @@
<string name="permlab_changeWifiState" msgid="7947824109713181554">"Wi-Fiకి కనెక్ట్ చేయడం మరియు దాని నుండి డిస్కనెక్ట్ చేయడం"</string>
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi యాక్సెస్ స్థానాలకు కనెక్ట్ చేయడానికి మరియు వాటి నుండి డిస్కనెక్ట్ చేయడానికి మరియు Wi-Fi నెట్వర్క్ల కోసం పరికర కాన్ఫిగరేషన్కు మార్పులు చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"Wi-Fi Multicast స్వీకరణను అనుమతించడం"</string>
- <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ టాబ్లెట్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి యాప్ను అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ Android TV పరికరానికి మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపిన ప్యాకెట్లను స్వీకరించడానికి యాప్ని అనుమతిస్తుంది. ఇది మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఎక్కువ పవర్ను ఉపయోగిస్తుంది."</string>
- <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ ఫోన్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి యాప్ను అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"మల్టీక్యాస్ట్ అడ్రస్లను ఉపయోగించి మీ టాబ్లెట్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి యాప్ను అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"మల్టీక్యాస్ట్ అడ్రస్లను ఉపయోగించి మీ Android TV పరికరానికి మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపిన ప్యాకెట్లను స్వీకరించడానికి యాప్ని అనుమతిస్తుంది. ఇది మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఎక్కువ పవర్ను ఉపయోగిస్తుంది."</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"మల్టీక్యాస్ట్ అడ్రస్లను ఉపయోగించి మీ ఫోన్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి యాప్ను అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"బ్లూటూత్ సెట్టింగ్లను యాక్సెస్ చేయడం"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"స్థానిక బ్లూటూత్ టాబ్లెట్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"మీ Android TV పరికరంలో బ్లూటూత్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొని, జత చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
@@ -547,7 +547,7 @@
<string name="permdesc_nfc" msgid="8352737680695296741">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్లు, కార్డులు మరియు రీడర్లతో కమ్యూనికేట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"మీ స్క్రీన్ లాక్ను నిలిపివేయడం"</string>
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"కీలాక్ మరియు ఏదైనా అనుబంధించబడిన పాస్వర్డ్ భద్రతను నిలిపివేయడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను నిలిపివేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ప్రారంభిస్తుంది."</string>
- <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"స్క్రీన్ లాక్ సంక్లిష్టత అభ్యర్థన"</string>
+ <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"స్క్రీన్ లాక్ సంక్లిష్టత రిక్వెస్ట్"</string>
<string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"ఇది మీ స్క్రీన్ లాక్ పాస్వర్డ్ సంక్లిష్టత స్థాయి (తీవ్రంగా ఉండాలా, ఓ మోస్తరుగా ఉండాలా, తక్కువ తీవ్రంగా ఉండాలా లేదా అస్సలు తీవ్రత ఉండకూడదా) తెలుసుకోవడానికి యాప్ను అనుమతిస్తుంది, అంటే పొడుగు ఎంత ఉండాలి, ఏ రకమైన స్క్రీన్ లాక్ పధ్ధతి అనుసరించాలో సూచిస్తుంది. అలాగే, స్క్రీన్ లాక్ పాస్వర్డ్ సంక్లిష్టతను ఏ స్థాయికి సెట్ చేసుకుంటే బాగుంటుందో కూడా వినియోగదారులకు యాప్ సూచించగలదు, కానీ వినియోగదారులు నిరభ్యంతరంగా ఆ సూచనలను పట్టించుకోకుండా వారి ఇష్టం మేరకు చక్కగా సెట్ చేసుకోవచ్చు. ఇంకో ముఖ్య విషయం, స్క్రీన్ లాక్ అన్నది సాదా వచన రూపంలో నిల్వ చేయబడదు, కనుక ఖచ్చితమైన పాస్వర్డ్ ఏమిటనేది యాప్కు తెలియదు."</string>
<string name="permlab_useBiometric" msgid="6314741124749633786">"బయోమెట్రిక్ హార్డ్వేర్ని ఉపయోగించు"</string>
<string name="permdesc_useBiometric" msgid="7502858732677143410">"ప్రమాణీకరణ కోసం బయోమెట్రిక్ హార్డ్వేర్ను ఉపయోగించడానికి యాప్ని అనుమతిస్తుంది"</string>
@@ -555,11 +555,11 @@
<string name="permdesc_manageFingerprint" msgid="2025616816437339865">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్లను జోడించే, తొలగించే పద్ధతులను అమలు చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_useFingerprint" msgid="1001421069766751922">"వేలిముద్ర హార్డ్వేర్ని ఉపయోగించడానికి అనుమతి"</string>
<string name="permdesc_useFingerprint" msgid="412463055059323742">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్వేర్ను ఉపయోగించడానికి యాప్ను అనుమతిస్తుంది"</string>
- <string name="permlab_audioWrite" msgid="8501705294265669405">"మీ సంగీత సేకరణను సవరించండి"</string>
+ <string name="permlab_audioWrite" msgid="8501705294265669405">"మీ సంగీత సేకరణను ఎడిట్ చేయండి"</string>
<string name="permdesc_audioWrite" msgid="8057399517013412431">"మీ సంగీత సేకరణని సవరించడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_videoWrite" msgid="5940738769586451318">"మీ వీడియో సేకరణను సవరించండి"</string>
+ <string name="permlab_videoWrite" msgid="5940738769586451318">"మీ వీడియో సేకరణను ఎడిట్ చేయండి"</string>
<string name="permdesc_videoWrite" msgid="6124731210613317051">"మీ వీడియో సేకరణను సవరించడానికి యాప్ని అనుమతిస్తుంది."</string>
- <string name="permlab_imagesWrite" msgid="1774555086984985578">"మీ ఫోటో సేకరణను సవరించండి"</string>
+ <string name="permlab_imagesWrite" msgid="1774555086984985578">"మీ ఫోటో సేకరణను ఎడిట్ చేయండి"</string>
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"మీ ఫోటో సేకరణను సవరించడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవండి"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
@@ -593,7 +593,7 @@
<string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"వేలిముద్ర హార్డ్వేర్ అందుబాటులో లేదు."</string>
<string name="fingerprint_error_no_space" msgid="7285481581905967580">"వేలిముద్రను సెటప్ చేయడం సాధ్యం కాదు"</string>
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
- <string name="fingerprint_error_canceled" msgid="540026881380070750">"వేలిముద్ర కార్యకలాపం రద్దయింది."</string>
+ <string name="fingerprint_error_canceled" msgid="540026881380070750">"వేలిముద్ర యాక్టివిటీ రద్దయింది."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"వేలిముద్ర చర్యని వినియోగదారు రద్దు చేశారు."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"చాలా ఎక్కువ ప్రయత్నాలు చేశారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
<string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"అనేకసార్లు ప్రయత్నించారు. వేలిముద్ర సెన్సార్ నిలిపివేయబడింది."</string>
@@ -645,7 +645,7 @@
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ముఖం ధృవీకరించలేరు. హార్డ్వేర్ అందుబాటులో లేదు."</string>
<string name="face_error_timeout" msgid="2598544068593889762">"ఫేస్ అన్లాక్ను మళ్లీ ట్రై చేయండి"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"కొత్త ముఖం డేటాను నిల్వ చేయడం కాదు. మొదట పాతది తొలిగించండి."</string>
- <string name="face_error_canceled" msgid="2164434737103802131">"ముఖ కార్యకలాపం రద్దయింది."</string>
+ <string name="face_error_canceled" msgid="2164434737103802131">"ముఖ యాక్టివిటీ రద్దయింది."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"ఫేస్ అన్లాక్ను యూజర్ రద్దు చేశారు"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"చాలా ఎక్కువ ప్రయత్నాలు చేశారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
<string name="face_error_lockout_permanent" msgid="3277134834042995260">"చాలా ఎక్కువ సార్లు ప్రయత్నించారు. ఫేస్ అన్లాక్ డిజేబుల్ చేయబడింది."</string>
@@ -663,14 +663,14 @@
</string-array>
<string name="face_icon_content_description" msgid="465030547475916280">"ముఖ చిహ్నం"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"సింక్ సెట్టింగ్లను చదవగలగడం"</string>
- <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల యాప్ ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
+ <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ఖాతా యొక్క సింక్ సెట్టింగ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల యాప్ ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"\'సింక్\'ను ఆన్, ఆఫ్ల మధ్య టోగుల్ చేయడం"</string>
- <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇది ఒక ఖాతాతో వ్యక్తుల యాప్ యొక్క సమకాలీకరణను ప్రారంభించడానికి ఉపయోగించబడవచ్చు."</string>
+ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"ఖాతా యొక్క సింక్ సెట్టింగ్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇది ఒక ఖాతాతో వ్యక్తుల యాప్ యొక్క సింక్ను ప్రారంభించడానికి ఉపయోగించబడవచ్చు."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"సింక్ గణాంకాలను చదవగలగడం"</string>
- <string name="permdesc_readSyncStats" msgid="3867809926567379434">"ఖాతా యొక్క సమకాలీకరణ గణాంకాలను అలాగే సమకాలీకరణ ఈవెంట్ల చరిత్రను మరియు ఎంత డేటా సమకాలీకరించబడింది అనేవాటిని చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permdesc_readSyncStats" msgid="3867809926567379434">"ఖాతా యొక్క సింక్ గణాంకాలను అలాగే సింక్ ఈవెంట్ల చరిత్రను మరియు ఎంత డేటా సమకాలీకరించబడింది అనేవాటిని చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_sdcardRead" msgid="5791467020950064920">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్లను చదువుతుంది"</string>
<string name="permdesc_sdcardRead" msgid="6872973242228240382">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_sdcardWrite" msgid="4863021819671416668">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్లను సవరించండి లేదా తొలగించండి"</string>
+ <string name="permlab_sdcardWrite" msgid="4863021819671416668">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్లను ఎడిట్ చేయండి లేదా తొలగించండి"</string>
<string name="permdesc_sdcardWrite" msgid="8376047679331387102">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్లను రాయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_use_sip" msgid="8250774565189337477">"SIP కాల్స్ను చేయడానికి/స్వీకరించడానికి"</string>
<string name="permdesc_use_sip" msgid="3590270893253204451">"SIP కాల్స్ను చేయడానికి మరియు స్వీకరించడానికి యాప్ను అనుమతిస్తుంది."</string>
@@ -1041,13 +1041,13 @@
<string name="search_go" msgid="2141477624421347086">"సెర్చ్"</string>
<string name="search_hint" msgid="455364685740251925">"వెతుకు..."</string>
<string name="searchview_description_search" msgid="1045552007537359343">"సెర్చ్"</string>
- <string name="searchview_description_query" msgid="7430242366971716338">"ప్రశ్నను శోధించండి"</string>
+ <string name="searchview_description_query" msgid="7430242366971716338">"ప్రశ్నను వెతకండి"</string>
<string name="searchview_description_clear" msgid="1989371719192982900">"ప్రశ్నను క్లియర్ చేయి"</string>
<string name="searchview_description_submit" msgid="6771060386117334686">"ప్రశ్నని సమర్పించండి"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"వాయిస్ శోధన"</string>
<string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"తాకడం ద్వారా విశ్లేషణను ప్రారంభించాలా?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> తాకడం ద్వారా విశ్లేషణను ప్రారంభించాలనుకుంటోంది. తాకడం ద్వారా విశ్లేషణను ఆన్ చేసినప్పుడు, మీరు మీ వేలి క్రింద ఉన్నవాటి యొక్క వివరణలను వినవచ్చు లేదా చూడవచ్చు లేదా టాబ్లెట్తో పరస్పర చర్య చేయడానికి సంజ్ఞలు చేయవచ్చు."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> తాకడం ద్వారా విశ్లేషణను ప్రారంభించాలనుకుంటోంది. తాకడం ద్వారా విశ్లేషణ ఆన్ చేయబడినప్పుడు, మీరు మీ వేలి క్రింద ఉన్నవాటి యొక్క వివరణలను వినవచ్చు లేదా చూడవచ్చు లేదా ఫోన్తో పరస్పర చర్య చేయడానికి సంజ్ఞలు చేయవచ్చు."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> తాకడం ద్వారా విశ్లేషణను ప్రారంభించాలనుకుంటోంది. తాకడం ద్వారా విశ్లేషణను ఆన్ చేసినప్పుడు, మీరు మీ వేలి కింద ఉన్నవాటి యొక్క వివరణలను వినవచ్చు లేదా చూడవచ్చు లేదా టాబ్లెట్తో పరస్పర చర్య చేయడానికి సంజ్ఞలు చేయవచ్చు."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> తాకడం ద్వారా విశ్లేషణను ప్రారంభించాలనుకుంటోంది. తాకడం ద్వారా విశ్లేషణ ఆన్ చేయబడినప్పుడు, మీరు మీ వేలి కింద ఉన్నవాటి యొక్క వివరణలను వినవచ్చు లేదా చూడవచ్చు లేదా ఫోన్తో పరస్పర చర్య చేయడానికి సంజ్ఞలు చేయవచ్చు."</string>
<string name="oneMonthDurationPast" msgid="4538030857114635777">"1 నెల క్రితం"</string>
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"1 నెలకు ముందు"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1474,10 +1474,10 @@
<string name="ime_action_previous" msgid="6548799326860401611">"మునుపటి"</string>
<string name="ime_action_default" msgid="8265027027659800121">"అమలు చేయి"</string>
<string name="dial_number_using" msgid="6060769078933953531">"<xliff:g id="NUMBER">%s</xliff:g>ని ఉపయోగించి\nనంబర్ డయల్ చేయండి"</string>
- <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g>ని ఉపయోగించి\nపరిచయాన్ని సృష్టించండి"</string>
- <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"క్రింది ఒకటి లేదా అంతకంటే ఎక్కువ యాప్లు మీ ఖాతాను యాక్సెస్ చేయడానికి ఇప్పుడు మరియు భవిష్యత్తులో అనుమతిని అభ్యర్థించవచ్చు."</string>
- <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"మీరు ఈ అభ్యర్థనను అనుమతించాలనుకుంటున్నారా?"</string>
- <string name="grant_permissions_header_text" msgid="3420736827804657201">"యాక్సెస్ అభ్యర్థన"</string>
+ <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g>ని ఉపయోగించి\nకాంటాక్ట్ను క్రియేట్ చేయండి"</string>
+ <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"కింది ఒకటి లేదా అంతకంటే ఎక్కువ యాప్లు మీ ఖాతాను యాక్సెస్ చేయడానికి ఇప్పుడు మరియు భవిష్యత్తులో అనుమతిని అభ్యర్థించవచ్చు."</string>
+ <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"మీరు ఈ రిక్వెస్ట్ను అనుమతించాలనుకుంటున్నారా?"</string>
+ <string name="grant_permissions_header_text" msgid="3420736827804657201">"యాక్సెస్ రిక్వెస్ట్"</string>
<string name="allow" msgid="6195617008611933762">"అనుమతించండి"</string>
<string name="deny" msgid="6632259981847676572">"తిరస్కరించండి"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"అనుమతి అభ్యర్థించబడింది"</string>
@@ -1486,7 +1486,7 @@
<string name="forward_intent_to_owner" msgid="4620359037192871015">"మీరు మీ కార్యాలయ ప్రొఫైల్కు వెలుపల ఈ యాప్ను ఉపయోగిస్తున్నారు"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"మీరు మీ కార్యాలయ ప్రొఫైల్లో ఈ యాప్ను ఉపయోగిస్తున్నారు"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"ఇన్పుట్ పద్ధతి"</string>
- <string name="sync_binding_label" msgid="469249309424662147">"సమకాలీకరణ"</string>
+ <string name="sync_binding_label" msgid="469249309424662147">"సింక్"</string>
<string name="accessibility_binding_label" msgid="1974602776545801715">"యాక్సెసిబిలిటీ"</string>
<string name="wallpaper_binding_label" msgid="1197440498000786738">"వాల్పేపర్"</string>
<string name="chooser_wallpaper" msgid="3082405680079923708">"వాల్పేపర్ను మార్చండి"</string>
@@ -1525,8 +1525,8 @@
<string name="websearch" msgid="5624340204512793290">"వెబ్ శోధన"</string>
<string name="find_next" msgid="5341217051549648153">"తదుపరిదాన్ని కనుగొను"</string>
<string name="find_previous" msgid="4405898398141275532">"మునుపటిదాన్ని కనుగొను"</string>
- <string name="gpsNotifTicker" msgid="3207361857637620780">"<xliff:g id="NAME">%s</xliff:g> నుండి స్థాన అభ్యర్థన"</string>
- <string name="gpsNotifTitle" msgid="1590033371665669570">"స్థాన అభ్యర్థన"</string>
+ <string name="gpsNotifTicker" msgid="3207361857637620780">"<xliff:g id="NAME">%s</xliff:g> నుండి స్థాన రిక్వెస్ట్"</string>
+ <string name="gpsNotifTitle" msgid="1590033371665669570">"స్థాన రిక్వెస్ట్"</string>
<string name="gpsNotifMessage" msgid="7346649122793758032">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) ద్వారా అభ్యర్థించబడింది"</string>
<string name="gpsVerifYes" msgid="3719843080744112940">"అవును"</string>
<string name="gpsVerifNo" msgid="1671201856091564741">"కాదు"</string>
@@ -1713,8 +1713,8 @@
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ఆఫ్ చేయబడింది"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్కట్లను ఎడిట్ చేయి"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"పూర్తయింది"</string>
- <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"సత్వరమార్గాన్ని ఆఫ్ చేయి"</string>
- <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
+ <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"షార్ట్కట్ను ఆఫ్ చేయి"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"షార్ట్కట్ను ఉపయోగించు"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"కలర్ మార్పిడి"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"కలర్ సరిచేయడం"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"వన్-హ్యాండెడ్ మోడ్"</string>
@@ -1926,14 +1926,14 @@
<string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> కొన్ని ధ్వనులను మ్యూట్ చేస్తోంది"</string>
<string name="system_error_wipe_data" msgid="5910572292172208493">"మీ పరికరంతో అంతర్గత సమస్య ఏర్పడింది మరియు మీరు ఫ్యాక్టరీ డేటా రీసెట్ చేసే వరకు అస్థిరంగా ఉంటుంది."</string>
<string name="system_error_manufacturer" msgid="703545241070116315">"మీ పరికరంతో అంతర్గత సమస్య ఏర్పడింది. వివరాల కోసం మీ తయారీదారుని సంప్రదించండి."</string>
- <string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"USSD అభ్యర్థన సాధారణ కాల్కు మార్చబడింది"</string>
- <string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"USSD అభ్యర్థన SS అభ్యర్థనకు మార్చబడింది"</string>
- <string name="stk_cc_ussd_to_ussd" msgid="8343001461299302472">"కొత్త USSD అభ్యర్థనకు మార్చబడింది"</string>
- <string name="stk_cc_ussd_to_dial_video" msgid="429118590323618623">"USSD అభ్యర్థన వీడియో కాల్కు మార్చబడింది"</string>
- <string name="stk_cc_ss_to_dial" msgid="4087396658768717077">"SS అభ్యర్థన సాధారణ కాల్కి మార్చబడింది"</string>
- <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS అభ్యర్థన వీడియో కాల్కి మార్చబడింది"</string>
- <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS అభ్యర్థన USSD అభ్యర్థనకు మార్చబడింది"</string>
- <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"కొత్త SS అభ్యర్థనకు మార్చబడింది"</string>
+ <string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"USSD రిక్వెస్ట్ సాధారణ కాల్కు మార్చబడింది"</string>
+ <string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"USSD రిక్వెస్ట్ SS రిక్వెస్ట్కు మార్చబడింది"</string>
+ <string name="stk_cc_ussd_to_ussd" msgid="8343001461299302472">"కొత్త USSD రిక్వెస్ట్కు మార్చబడింది"</string>
+ <string name="stk_cc_ussd_to_dial_video" msgid="429118590323618623">"USSD రిక్వెస్ట్ వీడియో కాల్కు మార్చబడింది"</string>
+ <string name="stk_cc_ss_to_dial" msgid="4087396658768717077">"SS రిక్వెస్ట్ సాధారణ కాల్కి మార్చబడింది"</string>
+ <string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS రిక్వెస్ట్ వీడియో కాల్కి మార్చబడింది"</string>
+ <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS రిక్వెస్ట్ USSD రిక్వెస్ట్కు మార్చబడింది"</string>
+ <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"కొత్త SS రిక్వెస్ట్కు మార్చబడింది"</string>
<string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ఫిషింగ్ అలర్ట్"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"హెచ్చరించబడింది"</string>
@@ -2041,15 +2041,15 @@
<string name="autofill_save_notnow" msgid="2853932672029024195">"ఇప్పుడు కాదు"</string>
<string name="autofill_save_never" msgid="6821841919831402526">"ఎప్పుడూ వద్దు"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"అప్డేట్ చేయి"</string>
- <string name="autofill_continue_yes" msgid="7914985605534510385">"కొనసాగించు"</string>
+ <string name="autofill_continue_yes" msgid="7914985605534510385">"కొనసాగించండి"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"పాస్వర్డ్"</string>
- <string name="autofill_save_type_address" msgid="3111006395818252885">"చిరునామా"</string>
+ <string name="autofill_save_type_address" msgid="3111006395818252885">"అడ్రస్"</string>
<string name="autofill_save_type_credit_card" msgid="3583795235862046693">"క్రెడిట్ కార్డ్"</string>
<string name="autofill_save_type_debit_card" msgid="3169397504133097468">"డెబిట్ కార్డ్"</string>
<string name="autofill_save_type_payment_card" msgid="6555012156728690856">"చెల్లింపు కార్డ్"</string>
<string name="autofill_save_type_generic_card" msgid="1019367283921448608">"కార్డ్"</string>
<string name="autofill_save_type_username" msgid="1018816929884640882">"వినియోగదారు పేరు"</string>
- <string name="autofill_save_type_email_address" msgid="1303262336895591924">"ఇమెయిల్ చిరునామా"</string>
+ <string name="autofill_save_type_email_address" msgid="1303262336895591924">"ఇమెయిల్ అడ్రస్"</string>
<string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
<string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"వెంటనే తీర ప్రాంతాలు మరియు నదీ పరీవాహక ప్రాంతాలను ఖాళీ చేసి మెట్ట ప్రాంతాలకు తరలి వెళ్లండి."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="4888224011071875068">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
@@ -2066,10 +2066,10 @@
<string name="mmcc_illegal_me_msim_template" msgid="4802735138861422802">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> అనుమతించబడదు"</string>
<string name="popup_window_default_title" msgid="6907717596694826919">"పాప్అప్ విండో"</string>
<string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
- <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"యాప్ వెర్షన్ డౌన్గ్రేడ్ చేయబడింది లేదా ఈ సత్వరమార్గంతో అనుకూలంగా లేదు"</string>
- <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"బ్యాకప్ మరియు పునరుద్ధరణకు యాప్ మద్దతు ఇవ్వని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
- <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"యాప్ సంతకం సరిపోలని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
- <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
+ <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"యాప్ వెర్షన్ డౌన్గ్రేడ్ చేయబడింది లేదా ఈ షార్ట్కట్తో అనుకూలంగా లేదు"</string>
+ <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"బ్యాకప్ మరియు పునరుద్ధరణకు యాప్ మద్దతు ఇవ్వని కారణంగా షార్ట్కట్ను పునరుద్ధరించడం సాధ్యపడలేదు"</string>
+ <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"యాప్ సంతకం సరిపోలని కారణంగా షార్ట్కట్ను పునరుద్ధరించడం సాధ్యపడలేదు"</string>
+ <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"షార్ట్కట్ను పునరుద్ధరించడం సాధ్యపడలేదు"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"షార్ట్కట్ నిలిపివేయబడింది"</string>
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"అన్ఇన్స్టాల్ చేయండి"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"ఏదేమైనా తెరువు"</string>
@@ -2133,7 +2133,7 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ఫైల్</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ఎవరికి షేర్ చేయాలనే దానికి సంబంధించి సిఫార్సులేవీ లేవు"</string>
- <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"యాప్ల జాబితా"</string>
+ <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"యాప్ల లిస్ట్"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ఈ యాప్కు రికార్డ్ చేసే అనుమతి మంజూరు కాలేదు, అయినా ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"హోమ్"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"వెనుకకు"</string>
@@ -2225,17 +2225,17 @@
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK అన్లాక్ను అభ్యర్థిస్తోంది…"</string>
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK అన్లాక్ను అభ్యర్థిస్తోంది…"</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK అన్లాక్ను అభ్యర్థిస్తోంది…"</string>
- <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM నెట్వర్క్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM నెట్వర్క్ సబ్సెట్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM సర్వీస్ ప్రొవైడర్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM కార్పొరేట్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM నెట్వర్క్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM నెట్వర్క్2 అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM కార్పొరేట్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM సర్వీస్ ప్రొవైడర్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM నెట్వర్క్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM నెట్వర్క్ సబ్సెట్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM సర్వీస్ ప్రొవైడర్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM కార్పొరేట్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM నెట్వర్క్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM నెట్వర్క్2 అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM కార్పొరేట్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM సర్వీస్ ప్రొవైడర్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
<string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
@@ -2247,11 +2247,11 @@
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK అన్లాక్ విజయవంతం కాలేదు."</string>
- <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI నెట్వర్క్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
- <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"నెట్వర్క్ సబ్సెట్ సర్వీస్ ప్రొవైడర్ అన్లాక్ అభ్యర్థన విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI నెట్వర్క్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
+ <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"నెట్వర్క్ సబ్సెట్ సర్వీస్ ప్రొవైడర్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM నెట్వర్క్ అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM నెట్వర్క్ సబ్సెట్ అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM సర్వీస్ ప్రొవైడర్ అన్లాక్ విజయవంతమైంది."</string>
@@ -2259,9 +2259,9 @@
<string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM నెట్వర్క్1 అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM నెట్వర్క్2 అన్లాక్ విజయవంతమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd అన్లాక్ అభ్యర్థన విజయవంతమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd అన్లాక్ రిక్వెస్ట్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM సర్వీస్ ప్రొవైడర్ అన్లాక్ విజయవంతమైంది."</string>
- <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM కార్పొరేట్ అన్లాక్ అభ్యర్థన విజయవంతమైంది."</string>
+ <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM కార్పొరేట్ అన్లాక్ రిక్వెస్ట్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK అన్లాక్ విజయవంతమైంది."</string>
<string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK అన్లాక్ విజయవంతమైంది."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 68a5ce7..cc38de2 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -327,17 +327,17 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"身体传感器"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"访问与您的生命体征相关的传感器数据"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"检索窗口内容"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"检测您正访问的窗口的内容。"</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"检测您与之互动的窗口的内容。"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"启用触摸浏览"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"设备将大声读出您点按的内容,同时您可以通过手势来浏览屏幕。"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"监测您输入的文字"</string>
- <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"包含个人数据,例如信用卡号和密码。"</string>
- <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"控制显示内容放大功能"</string>
- <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"控制显示内容的缩放级别和位置。"</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"包括信用卡号和密码等个人数据。"</string>
+ <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"控制屏幕内容放大功能"</string>
+ <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"控制屏幕内容的缩放级别和位置。"</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"执行手势"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可执行点按、滑动、双指张合等手势。"</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指纹手势"</string>
- <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕获在设备指纹传感器上执行的手势。"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕捉在设备指纹传感器上执行的手势。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 798e06c..1c02c6b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -246,7 +246,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"關機"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"電源"</string>
<string name="global_action_restart" msgid="4678451019561687074">"重新啟動"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"緊急電話"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"緊急撥號"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"錯誤報告"</string>
<string name="global_action_logout" msgid="6093581310002476511">"結束"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"螢幕截圖"</string>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 55ed83b..b191584 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -248,37 +248,37 @@
<color name="system_accent1_0">#ffffff</color>
<!-- Shade of the accent system color at 99% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_10">#F1FFFC</color>
+ <color name="system_accent1_10">#F9FCFF</color>
<!-- Shade of the accent system color at 95% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_50">#9CFFF2</color>
+ <color name="system_accent1_50">#E0F3FF</color>
<!-- Shade of the accent system color at 90% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_100">#8DF5E3</color>
+ <color name="system_accent1_100">#C1E8FF</color>
<!-- Shade of the accent system color at 80% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_200">#71D8C7</color>
+ <color name="system_accent1_200">#76D1FF</color>
<!-- Shade of the accent system color at 70% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_300">#53BCAC</color>
+ <color name="system_accent1_300">#4BB6E8</color>
<!-- Shade of the accent system color at 60% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_400">#34A192</color>
+ <color name="system_accent1_400">#219BCC</color>
<!-- Shade of the accent system color at 49% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_500">#008375</color>
+ <color name="system_accent1_500">#007FAC</color>
<!-- Shade of the accent system color at 40% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_600">#006C5F</color>
+ <color name="system_accent1_600">#00668B</color>
<!-- Shade of the accent system color at 30% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_700">#005747</color>
+ <color name="system_accent1_700">#004C69</color>
<!-- Shade of the accent system color at 20% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_800">#003E31</color>
+ <color name="system_accent1_800">#003549</color>
<!-- Shade of the accent system color at 10% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent1_900">#002214</color>
+ <color name="system_accent1_900">#001E2C</color>
<!-- Darkest shade of the accent color used by the system. Black.
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_accent1_1000">#000000</color>
@@ -288,37 +288,37 @@
<color name="system_accent2_0">#ffffff</color>
<!-- Shade of the secondary accent system color at 99% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_10">#F0FFFC</color>
+ <color name="system_accent2_10">#F9FCFF</color>
<!-- Shade of the secondary accent system color at 95% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_50">#CDFAF1</color>
+ <color name="system_accent2_50">#E0F3FF</color>
<!-- Shade of the secondary accent system color at 90% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_100">#BFEBE3</color>
+ <color name="system_accent2_100">#D1E5F4</color>
<!-- Shade of the secondary accent system color at 80% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_200">#A4CFC7</color>
+ <color name="system_accent2_200">#B5CAD7</color>
<!-- Shade of the secondary accent system color at 70% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_300">#89B4AC</color>
+ <color name="system_accent2_300">#9AAEBB</color>
<!-- Shade of the secondary accent system color at 60% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_400">#6F9991</color>
+ <color name="system_accent2_400">#8094A0</color>
<!-- Shade of the secondary accent system color at 49% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_500">#537C75</color>
+ <color name="system_accent2_500">#657985</color>
<!-- Shade of the secondary accent system color at 40% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_600">#3D665F</color>
+ <color name="system_accent2_600">#4E616C</color>
<!-- Shade of the secondary accent system color at 30% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_700">#254E47</color>
+ <color name="system_accent2_700">#374955</color>
<!-- Shade of the secondary accent system color at 20% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_800">#0C3731</color>
+ <color name="system_accent2_800">#20333D</color>
<!-- Shade of the secondary accent system color at 10% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent2_900">#00211C</color>
+ <color name="system_accent2_900">#091E28</color>
<!-- Darkest shade of the secondary accent color used by the system. Black.
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_accent2_1000">#000000</color>
@@ -331,34 +331,34 @@
<color name="system_accent3_10">#FFFBFF</color>
<!-- Shade of the tertiary accent system color at 95% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_50">#F9EAFF</color>
+ <color name="system_accent3_50">#F5EEFF</color>
<!-- Shade of the tertiary accent system color at 90% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_100">#ECDBFF</color>
+ <color name="system_accent3_100">#E6DEFF</color>
<!-- Shade of the tertiary accent system color at 80% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_200">#CFBFEB</color>
+ <color name="system_accent3_200">#CAC1EA</color>
<!-- Shade of the tertiary accent system color at 70% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_300">#B3A4CF</color>
+ <color name="system_accent3_300">#AEA6CE</color>
<!-- Shade of the tertiary accent system color at 60% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_400">#988AB3</color>
+ <color name="system_accent3_400">#938CB1</color>
<!-- Shade of the tertiary accent system color at 49% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_500">#7B6E96</color>
+ <color name="system_accent3_500">#787296</color>
<!-- Shade of the tertiary accent system color at 40% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_600">#64587F</color>
+ <color name="system_accent3_600">#605A7C</color>
<!-- Shade of the tertiary accent system color at 30% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_700">#4C4165</color>
+ <color name="system_accent3_700">#484264</color>
<!-- Shade of the tertiary accent system color at 20% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_800">#352B4D</color>
+ <color name="system_accent3_800">#322C4C</color>
<!-- Shade of the tertiary accent system color at 10% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_accent3_900">#1E1636</color>
+ <color name="system_accent3_900">#1D1736</color>
<!-- Darkest shade of the tertiary accent color used by the system. Black.
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_accent3_1000">#000000</color>
@@ -368,37 +368,37 @@
<color name="system_neutral1_0">#ffffff</color>
<!-- Shade of the neutral system color at 99% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_10">#fbfbfb</color>
+ <color name="system_neutral1_10">#FCFCFF</color>
<!-- Shade of the neutral system color at 95% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_50">#f0f0f0</color>
+ <color name="system_neutral1_50">#F0F0F3</color>
<!-- Shade of the neutral system color at 90% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_100">#e2e2e2</color>
+ <color name="system_neutral1_100">#E1E3E5</color>
<!-- Shade of the neutral system color at 80% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_200">#c6c6c6</color>
+ <color name="system_neutral1_200">#C5C7C9</color>
<!-- Shade of the neutral system color at 70% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_300">#ababab</color>
+ <color name="system_neutral1_300">#AAABAE</color>
<!-- Shade of the neutral system color at 60% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_400">#909090</color>
+ <color name="system_neutral1_400">#8F9193</color>
<!-- Shade of the neutral system color at 49% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_500">#757575</color>
+ <color name="system_neutral1_500">#747679</color>
<!-- Shade of the neutral system color at 40% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_600">#5e5e5e</color>
+ <color name="system_neutral1_600">#5C5F61</color>
<!-- Shade of the neutral system color at 30% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_700">#464646</color>
+ <color name="system_neutral1_700">#454749</color>
<!-- Shade of the neutral system color at 20% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_800">#303030</color>
+ <color name="system_neutral1_800">#2E3133</color>
<!-- Shade of the neutral system color at 10% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral1_900">#1b1b1b</color>
+ <color name="system_neutral1_900">#191C1E</color>
<!-- Darkest shade of the neutral color used by the system. Black.
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_neutral1_1000">#000000</color>
@@ -408,37 +408,37 @@
<color name="system_neutral2_0">#ffffff</color>
<!-- Shade of the secondary neutral system color at 99% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_10">#fbfbfb</color>
+ <color name="system_neutral2_10">#F9FCFF</color>
<!-- Shade of the secondary neutral system color at 95% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_50">#f0f0f0</color>
+ <color name="system_neutral2_50">#EBF1F8</color>
<!-- Shade of the secondary neutral system color at 90% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_100">#e2e2e2</color>
+ <color name="system_neutral2_100">#DCE3E9</color>
<!-- Shade of the secondary neutral system color at 80% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_200">#c6c6c6</color>
+ <color name="system_neutral2_200">#C0C7CD</color>
<!-- Shade of the secondary neutral system color at 70% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_300">#ababab</color>
+ <color name="system_neutral2_300">#A5ACB2</color>
<!-- Shade of the secondary neutral system color at 60% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_400">#909090</color>
+ <color name="system_neutral2_400">#8A9297</color>
<!-- Shade of the secondary neutral system color at 49% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_500">#757575</color>
+ <color name="system_neutral2_500">#70777C</color>
<!-- Shade of the secondary neutral system color at 40% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_600">#5e5e5e</color>
+ <color name="system_neutral2_600">#585F65</color>
<!-- Shade of the secondary neutral system color at 30% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_700">#464646</color>
+ <color name="system_neutral2_700">#40484D</color>
<!-- Shade of the secondary neutral system color at 20% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_800">#303030</color>
+ <color name="system_neutral2_800">#2A3136</color>
<!-- Shade of the secondary neutral system color at 10% lightness.
This value can be overlaid at runtime by OverlayManager RROs. -->
- <color name="system_neutral2_900">#1b1b1b</color>
+ <color name="system_neutral2_900">#161C20</color>
<!-- Darkest shade of the secondary neutral color used by the system. Black.
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_neutral2_1000">#000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5d87f84..89c5a8d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -971,6 +971,20 @@
-->
<integer name="config_longPressOnPowerBehavior">5</integer>
+ <!-- The time in milliseconds after which a press on power button is considered "long". -->
+ <integer name="config_longPressOnPowerDurationMs">500</integer>
+
+ <!-- The possible UI options to be surfaced for configuring long press power on duration
+ action. Value set in config_longPressOnPowerDurationMs should be one of the available
+ options to allow users to restore default. -->
+ <integer-array name="config_longPressOnPowerDurationSettings">
+ <item>250</item>
+ <item>350</item>
+ <item>500</item>
+ <item>650</item>
+ <item>750</item>
+ </integer-array>
+
<!-- Whether the setting to change long press on power behaviour from default to assistant (5)
is available in Settings.
-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 289439f..77a45f9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -439,6 +439,8 @@
<java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
<java-symbol type="integer" name="config_immersive_mode_confirmation_panic" />
<java-symbol type="integer" name="config_longPressOnPowerBehavior" />
+ <java-symbol type="integer" name="config_longPressOnPowerDurationMs" />
+ <java-symbol type="array" name="config_longPressOnPowerDurationSettings" />
<java-symbol type="bool" name="config_longPressOnPowerForAssistantSettingAvailable" />
<java-symbol type="integer" name="config_veryLongPressOnPowerBehavior" />
<java-symbol type="integer" name="config_veryLongPressTimeout" />
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
index 7c6271c..c194989 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java
@@ -65,6 +65,7 @@
@Mock ITunerSession mHalTunerSessionMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
+ private final Object mLock = new Object();
// RadioModule under test
private RadioModule mRadioModule;
@@ -96,7 +97,7 @@
mRadioModule = new RadioModule(mBroadcastRadioMock, new RadioManager.ModuleProperties(0, "",
0, "", "", "", "", 0, 0, false, false, null, false, new int[] {}, new int[] {},
- null, null));
+ null, null), mLock);
doAnswer((Answer) invocation -> {
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index ab8a21c..b5dffba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -31,6 +31,7 @@
import android.app.TaskInfo;
import android.content.Context;
import android.content.LocusId;
+import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
@@ -46,6 +47,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
@@ -488,14 +490,40 @@
}
@Override
+ public void onSizeCompatRestartButtonAppeared(int taskId) {
+ final TaskAppearedInfo info;
+ synchronized (mLock) {
+ info = mTasks.get(taskId);
+ }
+ if (info == null) {
+ return;
+ }
+ logSizeCompatRestartButtonEventReported(info,
+ FrameworkStatsLog.SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED__EVENT__APPEARED);
+ }
+
+ @Override
public void onSizeCompatRestartButtonClicked(int taskId) {
final TaskAppearedInfo info;
synchronized (mLock) {
info = mTasks.get(taskId);
}
- if (info != null) {
- restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token);
+ if (info == null) {
+ return;
}
+ logSizeCompatRestartButtonEventReported(info,
+ FrameworkStatsLog.SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED__EVENT__CLICKED);
+ restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token);
+ }
+
+ private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
+ int event) {
+ ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;
+ if (topActivityInfo == null) {
+ return;
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED,
+ topActivityInfo.applicationInfo.uid, event);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index 8405385..3800b8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -19,6 +19,7 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
@@ -181,7 +182,7 @@
// TODO: Is there more we need to do here?
mSyncQueue.runInSync(t -> {
- t.setLayer(dividerLeash, Integer.MAX_VALUE)
+ t.setLayer(dividerLeash, SPLIT_DIVIDER_LAYER)
.setPosition(mTaskLeash1, mTaskInfo1.positionInParent.x,
mTaskInfo1.positionInParent.y)
.setPosition(mTaskLeash2, mTaskInfo2.positionInParent.x,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 4ac7dcf..7d7bfb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -696,8 +696,10 @@
? mPointerHeight - mPointerOverlap
: 0;
final float paddingRight = (showVertically && !onLeft)
- ? mPointerHeight - mPointerOverlap : 0;
- final float paddingTop = showVertically ? 0
+ ? mPointerHeight - mPointerOverlap
+ : 0;
+ final float paddingTop = showVertically
+ ? 0
: mPointerHeight - mPointerOverlap;
setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 7d4fb21..306224b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -79,14 +79,18 @@
private int mBubbleSize;
private int mSpacingBetweenBubbles;
- private float mExpandedViewLargeScreenWidth;
+
+ private int mExpandedViewMinHeight;
+ private int mExpandedViewLargeScreenWidth;
+ private int mExpandedViewLargeScreenInset;
+
private int mOverflowWidth;
private int mExpandedViewPadding;
private int mPointerMargin;
private int mPointerWidth;
private int mPointerHeight;
+ private int mPointerOverlap;
private int mManageButtonHeight;
- private int mExpandedViewMinHeight;
private int mOverflowHeight;
private int mMinimumFlyoutWidthLargeScreen;
@@ -168,15 +172,20 @@
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
- mExpandedViewLargeScreenWidth = bounds.width() * EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT;
+ mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
+ mExpandedViewLargeScreenWidth = (int) (bounds.width()
+ * EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT);
+ mExpandedViewLargeScreenInset = mIsLargeScreen
+ ? (bounds.width() - mExpandedViewLargeScreenWidth) / 2
+ : mExpandedViewPadding;
mOverflowWidth = mIsLargeScreen
- ? (int) mExpandedViewLargeScreenWidth
+ ? mExpandedViewLargeScreenWidth
: res.getDimensionPixelSize(
R.dimen.bubble_expanded_view_phone_landscape_overflow_width);
- mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
+ mPointerOverlap = res.getDimensionPixelSize(R.dimen.bubble_pointer_overlap);
mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_total_height);
mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
@@ -294,66 +303,93 @@
}
/**
- * Calculates the left & right padding for the bubble expanded view.
+ * Calculates the padding for the bubble expanded view.
*
- * On larger screens the width of the expanded view is restricted via this padding.
- * On landscape the bubble overflow expanded view is also restricted via this padding.
+ * Some specifics:
+ * On large screens the width of the expanded view is restricted via this padding.
+ * On phone landscape the bubble overflow expanded view is also restricted via this padding.
+ * On large screens & landscape no top padding is set, the top position is set via translation.
+ * On phone portrait top padding is set as the space between the tip of the pointer and the
+ * bubble.
+ * When the overflow is shown it doesn't have the manage button to pad out the bottom so
+ * padding is added.
*/
- public int[] getExpandedViewPadding(boolean onLeft, boolean isOverflow) {
- int leftPadding = mInsets.left + mExpandedViewPadding;
- int rightPadding = mInsets.right + mExpandedViewPadding;
- final boolean isLargeOrOverflow = mIsLargeScreen || isOverflow;
- final float expandedViewWidth = isOverflow
- ? mOverflowWidth
- : mExpandedViewLargeScreenWidth;
- if (showBubblesVertically()) {
- if (!onLeft) {
- rightPadding += mBubbleSize - mPointerHeight;
- leftPadding += isLargeOrOverflow
- ? (mPositionRect.width() - rightPadding - expandedViewWidth)
- : 0;
- } else {
- leftPadding += mBubbleSize - mPointerHeight;
- rightPadding += isLargeOrOverflow
- ? (mPositionRect.width() - leftPadding - expandedViewWidth)
- : 0;
+ public int[] getExpandedViewContainerPadding(boolean onLeft, boolean isOverflow) {
+ final int pointerTotalHeight = mPointerHeight - mPointerOverlap;
+ if (mIsLargeScreen) {
+ // [left, top, right, bottom]
+ mPaddings[0] = onLeft
+ ? mExpandedViewLargeScreenInset - pointerTotalHeight
+ : mExpandedViewLargeScreenInset;
+ mPaddings[1] = 0;
+ mPaddings[2] = onLeft
+ ? mExpandedViewLargeScreenInset
+ : mExpandedViewLargeScreenInset - pointerTotalHeight;
+ // Overflow doesn't show manage button / get padding from it so add padding here for it
+ mPaddings[3] = isOverflow ? mExpandedViewPadding : 0;
+ return mPaddings;
+ } else {
+ int leftPadding = mInsets.left + mExpandedViewPadding;
+ int rightPadding = mInsets.right + mExpandedViewPadding;
+ final float expandedViewWidth = isOverflow
+ ? mOverflowWidth
+ : mExpandedViewLargeScreenWidth;
+ if (showBubblesVertically()) {
+ if (!onLeft) {
+ rightPadding += mBubbleSize - pointerTotalHeight;
+ leftPadding += isOverflow
+ ? (mPositionRect.width() - rightPadding - expandedViewWidth)
+ : 0;
+ } else {
+ leftPadding += mBubbleSize - pointerTotalHeight;
+ rightPadding += isOverflow
+ ? (mPositionRect.width() - leftPadding - expandedViewWidth)
+ : 0;
+ }
}
+ // [left, top, right, bottom]
+ mPaddings[0] = leftPadding;
+ mPaddings[1] = showBubblesVertically() ? 0 : mPointerMargin;
+ mPaddings[2] = rightPadding;
+ mPaddings[3] = 0;
+ return mPaddings;
}
- // [left, top, right, bottom]
- mPaddings[0] = leftPadding;
- mPaddings[1] = showBubblesVertically() ? 0 : mPointerMargin;
- mPaddings[2] = rightPadding;
- mPaddings[3] = 0;
- return mPaddings;
}
/** Gets the y position of the expanded view if it was top-aligned. */
private float getExpandedViewYTopAligned() {
final int top = getAvailableRect().top;
if (showBubblesVertically()) {
- return top - mPointerWidth;
+ return top - mPointerWidth + mExpandedViewPadding;
} else {
return top + mBubbleSize + mPointerMargin;
}
}
- /** The maximum height the expanded view can be. */
+ public float getExpandedBubblesY() {
+ return getAvailableRect().top + mExpandedViewPadding;
+ }
+
+ /**
+ * Calculate the maximum height the expanded view can be depending on where it's placed on
+ * the screen and the size of the elements around it (e.g. padding, pointer, manage button).
+ */
public int getMaxExpandedViewHeight(boolean isOverflow) {
+ // Subtract top insets because availableRect.height would account for that
+ int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
int paddingTop = showBubblesVertically()
? 0
: mPointerHeight;
- int settingsHeight = isOverflow ? 0 : mManageButtonHeight;
// Subtract pointer size because it's laid out in LinearLayout with the expanded view.
int pointerSize = showBubblesVertically()
? mPointerWidth
: (mPointerHeight + mPointerMargin);
- // Subtract top insets because availableRect.height would account for that
- int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
+ int bottomPadding = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
return getAvailableRect().height()
- expandedContainerY
- paddingTop
- - settingsHeight
- - pointerSize;
+ - pointerSize
+ - bottomPadding;
}
/**
@@ -362,11 +398,14 @@
*/
public float getExpandedViewHeight(BubbleViewProvider bubble) {
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
+ if (isOverflow && showBubblesVertically() && !mIsLargeScreen) {
+ // overflow in landscape on phone is max
+ return MAX_HEIGHT;
+ }
float desiredHeight = isOverflow
? mOverflowHeight
: ((Bubble) bubble).getDesiredHeight(mContext);
- int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
- desiredHeight = Math.max(manageButtonHeight + desiredHeight, mExpandedViewMinHeight);
+ desiredHeight = Math.max(desiredHeight, mExpandedViewMinHeight);
if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) {
return MAX_HEIGHT;
}
@@ -391,7 +430,7 @@
return topAlignment;
}
// If we're here, we're showing vertically & developer has made height less than maximum.
- int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
+ int manageButtonHeight = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
float pointerPosition = getPointerPosition(bubblePosition);
float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
float topIfCentered = pointerPosition - (expandedViewHeight / 2);
@@ -426,25 +465,40 @@
}
/**
- * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
- * row. When in landscape or on a large screen, they show at the left or right side in a
- * vertical row. This method accounts for screen orientation and will return an x or y value
- * for the position of the bubble in the row.
+ * Returns the position of the bubble on-screen when the stack is expanded.
*
- * @param index bubble index in the row.
- * @param numberOfBubbles the number of bubbles (including the overflow) in the row.
- * @return the y position of the bubble if showing vertically and the x position if showing
- * horizontally.
+ * @param index the index of the bubble in the stack.
+ * @param numberOfBubbles the total number of bubbles in the stack.
+ * @param onLeftEdge whether the stack would rest on the left edge of the screen when collapsed.
+ * @return the x, y position of the bubble on-screen when the stack is expanded.
*/
- public float getBubbleXOrYForOrientation(int index, int numberOfBubbles) {
- final float positionInBar = index * (mBubbleSize + mSpacingBetweenBubbles);
+ public PointF getExpandedBubbleXY(int index, int numberOfBubbles, boolean onLeftEdge) {
+ final float positionInRow = index * (mBubbleSize + mSpacingBetweenBubbles);
final float expandedStackSize = (numberOfBubbles * mBubbleSize)
+ ((numberOfBubbles - 1) * mSpacingBetweenBubbles);
final float centerPosition = showBubblesVertically()
? mPositionRect.centerY()
: mPositionRect.centerX();
+ // alignment - centered on the edge
final float rowStart = centerPosition - (expandedStackSize / 2f);
- return rowStart + positionInBar;
+ float x;
+ float y;
+ if (showBubblesVertically()) {
+ y = rowStart + positionInRow;
+ int left = mIsLargeScreen
+ ? mExpandedViewLargeScreenInset - mExpandedViewPadding - mBubbleSize
+ : mPositionRect.left;
+ int right = mIsLargeScreen
+ ? mPositionRect.right - mExpandedViewLargeScreenInset + mExpandedViewPadding
+ : mPositionRect.right - mBubbleSize;
+ x = onLeftEdge
+ ? left
+ : right;
+ } else {
+ y = mPositionRect.top + mExpandedViewPadding;
+ x = rowStart + positionInRow;
+ }
+ return new PointF(x, y);
}
/**
@@ -459,6 +513,17 @@
}
/**
+ * @return whether the stack is considered on the left side of the screen.
+ */
+ public boolean isStackOnLeft(PointF currentStackPosition) {
+ if (currentStackPosition == null) {
+ currentStackPosition = getRestingPosition();
+ }
+ final int stackCenter = (int) currentStackPosition.x + mBubbleSize / 2;
+ return stackCenter < mScreenRect.width() / 2;
+ }
+
+ /**
* Sets the stack's most recent position along the edge of the screen. This is saved when the
* last bubble is removed, so that the stack can be restored in its previous position.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 3d2505e..5a51eed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -778,8 +778,8 @@
floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut,
this::animateShadows /* onStackAnimationFinished */, mPositioner);
- mExpandedAnimationController = new ExpandedAnimationController(
- mPositioner, mExpandedViewPadding, onBubbleAnimatedOut);
+ mExpandedAnimationController = new ExpandedAnimationController(mPositioner,
+ onBubbleAnimatedOut);
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
// Force LTR by default since most of the Bubbles UI is positioned manually by the user, or
@@ -1869,28 +1869,28 @@
maybeShowManageEdu();
}
} /* after */);
-
- final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
- getBubbleIndex(mExpandedBubble));
- mExpandedViewContainer.setTranslationX(0f);
- mExpandedViewContainer.setTranslationY(translationY);
- mExpandedViewContainer.setAlpha(1f);
-
int index;
if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
index = mBubbleData.getBubbles().size();
} else {
index = getBubbleIndex(mExpandedBubble);
}
- // Position of the bubble we're expanding, once it's settled in its row.
- final float bubbleWillBeAt =
- mExpandedAnimationController.getBubbleXOrYForOrientation(index);
+ PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleContainer.getChildCount(),
+ mStackOnLeftOrWillBe);
+ final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
+ mPositioner.showBubblesVertically() ? p.y : p.x);
+ mExpandedViewContainer.setTranslationX(0f);
+ mExpandedViewContainer.setTranslationY(translationY);
+ mExpandedViewContainer.setAlpha(1f);
// How far horizontally the bubble will be animating. We'll wait a bit longer for bubbles
// that are animating farther, so that the expanded view doesn't move as much.
final float relevantStackPosition = showVertically
? mStackAnimationController.getStackPosition().y
: mStackAnimationController.getStackPosition().x;
+ final float bubbleWillBeAt = showVertically
+ ? p.y
+ : p.x;
final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
// Wait for the path animation target to reach its end, and add a small amount of extra time
@@ -1907,22 +1907,22 @@
// Set the pivot point for the scale, so the expanded view animates out from the bubble.
if (showVertically) {
float pivotX;
- float pivotY = bubbleWillBeAt + mBubbleSize / 2f;
if (mStackOnLeftOrWillBe) {
- pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+ pivotX = p.x + mBubbleSize + mExpandedViewPadding;
} else {
- pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+ pivotX = p.x - mExpandedViewPadding;
}
mExpandedViewContainerMatrix.setScale(
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
- pivotX, pivotY);
+ pivotX,
+ p.y + mBubbleSize / 2f);
} else {
mExpandedViewContainerMatrix.setScale(
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
- bubbleWillBeAt + mBubbleSize / 2f,
- translationY);
+ p.x + mBubbleSize / 2f,
+ p.y + mBubbleSize + mExpandedViewPadding);
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -1959,6 +1959,7 @@
mExpandedViewContainerMatrix);
})
.withEndActions(() -> {
+ mExpandedViewContainer.setAnimationMatrix(null);
afterExpandedViewAnimation();
if (mExpandedBubble != null
&& mExpandedBubble.getExpandedView() != null) {
@@ -2009,12 +2010,11 @@
index = mBubbleData.getBubbles().indexOf(mExpandedBubble);
}
// Value the bubble is animating from (back into the stack).
- final float expandingFromBubbleAt =
- mExpandedAnimationController.getBubbleXOrYForOrientation(index);
- final boolean showVertically = mPositioner.showBubblesVertically();
+ final PointF p = mPositioner.getExpandedBubbleXY(index,
+ mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
if (mPositioner.showBubblesVertically()) {
float pivotX;
- float pivotY = expandingFromBubbleAt + mBubbleSize / 2f;
+ float pivotY = p.y + mBubbleSize / 2f;
if (mStackOnLeftOrWillBe) {
pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
} else {
@@ -2026,8 +2026,8 @@
} else {
mExpandedViewContainerMatrix.setScale(
1f, 1f,
- expandingFromBubbleAt + mBubbleSize / 2f,
- mPositioner.getExpandedViewY(mExpandedBubble, index));
+ p.x + mBubbleSize / 2f,
+ p.y + mBubbleSize + mExpandedViewPadding);
}
mExpandedViewAlphaAnimator.reverse();
@@ -2105,32 +2105,31 @@
boolean isOverflow = mExpandedBubble != null
&& mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
- float expandingFromBubbleDestination =
- mExpandedAnimationController.getBubbleXOrYForOrientation(isOverflow
- ? getBubbleCount()
- : mBubbleData.getBubbles().indexOf(mExpandedBubble));
-
+ PointF p = mPositioner.getExpandedBubbleXY(isOverflow
+ ? mBubbleContainer.getChildCount() - 1
+ : mBubbleData.getBubbles().indexOf(mExpandedBubble),
+ mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
mExpandedViewContainer.setAlpha(1f);
mExpandedViewContainer.setVisibility(View.VISIBLE);
if (mPositioner.showBubblesVertically()) {
float pivotX;
- float pivotY = expandingFromBubbleDestination + mBubbleSize / 2f;
+ float pivotY = p.y + mBubbleSize / 2f;
if (mStackOnLeftOrWillBe) {
- pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+ pivotX = p.x + mBubbleSize + mExpandedViewPadding;
} else {
- pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
-
+ pivotX = p.x - mExpandedViewPadding;
}
mExpandedViewContainerMatrix.setScale(
- 0f, 0f,
+ 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
+ 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
pivotX, pivotY);
} else {
mExpandedViewContainerMatrix.setScale(
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
- expandingFromBubbleDestination + mBubbleSize / 2f,
- mPositioner.getExpandedViewY(mExpandedBubble, expandingFromBubbleDestination));
+ p.x + mBubbleSize / 2f,
+ p.y + mBubbleSize + mExpandedViewPadding);
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -2155,6 +2154,7 @@
.withEndActions(() -> {
mExpandedViewTemporarilyHidden = false;
mIsBubbleSwitchAnimating = false;
+ mExpandedViewContainer.setAnimationMatrix(null);
})
.start();
}, 25);
@@ -2764,16 +2764,17 @@
}
boolean isOverflowExpanded = mExpandedBubble != null
&& BubbleOverflow.KEY.equals(mExpandedBubble.getKey());
- int[] paddings = mPositioner.getExpandedViewPadding(
+ int[] paddings = mPositioner.getExpandedViewContainerPadding(
mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded);
mExpandedViewContainer.setPadding(paddings[0], paddings[1], paddings[2], paddings[3]);
if (mIsExpansionAnimating) {
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
}
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
+ PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble),
+ mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble,
- mExpandedAnimationController.getBubbleXOrYForOrientation(
- getBubbleIndex(mExpandedBubble))));
+ mPositioner.showBubblesVertically() ? p.y : p.x));
mExpandedViewContainer.setTranslationX(0f);
mExpandedBubble.getExpandedView().updateView(
mExpandedViewContainer.getLocationOnScreen());
@@ -2856,8 +2857,13 @@
if (index == -1) {
return;
}
- float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index);
- mExpandedBubble.getExpandedView().setPointerPosition(bubblePosition, mStackOnLeftOrWillBe);
+ PointF bubblePosition = mPositioner.getExpandedBubbleXY(index,
+ mBubbleContainer.getChildCount(),
+ mStackOnLeftOrWillBe);
+ mExpandedBubble.getExpandedView().setPointerPosition(mPositioner.showBubblesVertically()
+ ? bubblePosition.y
+ : bubblePosition.x,
+ mStackOnLeftOrWillBe);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 007ddbf..c32be98 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -76,8 +76,6 @@
/** Horizontal offset between bubbles, which we need to know to re-stack them. */
private float mStackOffsetPx;
- /** Space between status bar and bubbles in the expanded state. */
- private float mBubblePaddingTop;
/** Size of each bubble. */
private float mBubbleSizePx;
/** Whether the expand / collapse animation is running. */
@@ -118,8 +116,6 @@
/** The bubble currently being dragged out of the row (to potentially be dismissed). */
private MagnetizedObject<View> mMagnetizedBubbleDraggingOut;
- private int mExpandedViewPadding;
-
/**
* Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
* end of this animation means we have no bubbles left, and notify the BubbleController.
@@ -128,11 +124,10 @@
private BubblePositioner mPositioner;
- public ExpandedAnimationController(BubblePositioner positioner, int expandedViewPadding,
+ public ExpandedAnimationController(BubblePositioner positioner,
Runnable onBubbleAnimatedOutAction) {
mPositioner = positioner;
updateResources();
- mExpandedViewPadding = expandedViewPadding;
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
mCollapsePoint = mPositioner.getDefaultStartPosition();
}
@@ -199,7 +194,6 @@
return;
}
Resources res = mLayout.getContext().getResources();
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
mBubbleSizePx = mPositioner.getBubbleSize();
}
@@ -245,31 +239,22 @@
final Path path = new Path();
path.moveTo(bubble.getTranslationX(), bubble.getTranslationY());
- final float expandedY = mPositioner.showBubblesVertically()
- ? getBubbleXOrYForOrientation(index)
- : getExpandedY();
+ boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
+ final PointF p = mPositioner.getExpandedBubbleXY(index,
+ mLayout.getChildCount(),
+ onLeft);
if (expanding) {
- // If we're expanding, first draw a line from the bubble's current position to the
- // top of the screen.
- path.lineTo(bubble.getTranslationX(), expandedY);
+ // If we're expanding, first draw a line from the bubble's current position to where
+ // it'll end up
+ path.lineTo(bubble.getTranslationX(), p.y);
// Then, draw a line across the screen to the bubble's resting position.
- if (mPositioner.showBubblesVertically()) {
- Rect availableRect = mPositioner.getAvailableRect();
- boolean onLeft = mCollapsePoint != null
- && mCollapsePoint.x < (availableRect.width() / 2f);
- float translationX = onLeft
- ? availableRect.left
- : availableRect.right - mBubbleSizePx;
- path.lineTo(translationX, getBubbleXOrYForOrientation(index));
- } else {
- path.lineTo(getBubbleXOrYForOrientation(index), expandedY);
- }
+ path.lineTo(p.x, p.y);
} else {
final float stackedX = mCollapsePoint.x;
// If we're collapsing, draw a line from the bubble's current position to the side
// of the screen where the bubble will be stacked.
- path.lineTo(stackedX, expandedY);
+ path.lineTo(stackedX, p.y);
// Then, draw a line down to the stack position.
path.lineTo(stackedX, mCollapsePoint.y
@@ -379,8 +364,9 @@
bubbleView.setTranslationY(y);
}
+ final float expandedY = mPositioner.getExpandedBubblesY();
final boolean draggedOutEnough =
- y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx;
+ y > expandedY + mBubbleSizePx || y < expandedY - mBubbleSizePx;
if (draggedOutEnough != mBubbleDraggedOutEnough) {
updateBubblePositions();
mBubbleDraggedOutEnough = draggedOutEnough;
@@ -424,9 +410,10 @@
return;
}
final int index = mLayout.indexOfChild(bubbleView);
-
+ final PointF p = mPositioner.getExpandedBubbleXY(index, mLayout.getChildCount(),
+ mPositioner.isStackOnLeft(mCollapsePoint));
animationForChildAtIndex(index)
- .position(getBubbleXOrYForOrientation(index), getExpandedY())
+ .position(p.x, p.y)
.withPositionStartVelocities(velX, velY)
.start(() -> bubbleView.setTranslationZ(0f) /* after */);
@@ -443,17 +430,13 @@
}
/**
- * Animates the bubbles to {@link #getExpandedY()} position. Used in response to IME showing.
+ * Animates the bubbles to the y position. Used in response to IME showing.
*/
public void updateYPosition(Runnable after) {
if (mLayout == null) return;
animationsForChildrenFromIndex(
- 0, (i, anim) -> anim.translationY(getExpandedY())).startAll(after);
- }
-
- /** The Y value of the row of expanded bubbles. */
- public float getExpandedY() {
- return mPositioner.getAvailableRect().top + mBubblePaddingTop;
+ 0, (i, anim) -> anim.translationY(mPositioner.getExpandedBubblesY()))
+ .startAll(after);
}
/** Description of current animation controller state. */
@@ -511,35 +494,36 @@
startOrUpdatePathAnimation(true /* expanding */);
} else if (mAnimatingCollapse) {
startOrUpdatePathAnimation(false /* expanding */);
- } else if (mPositioner.showBubblesVertically()) {
- child.setTranslationY(getBubbleXOrYForOrientation(index));
- if (!mPreparingToCollapse) {
- // Only animate if we're not collapsing as that animation will handle placing the
- // new bubble in the stacked position.
- Rect availableRect = mPositioner.getAvailableRect();
- boolean onLeft = mCollapsePoint != null
- && mCollapsePoint.x < (availableRect.width() / 2f);
- float fromX = onLeft
- ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR
- : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
- float toX = onLeft
- ? availableRect.left + mExpandedViewPadding
- : availableRect.right - mBubbleSizePx - mExpandedViewPadding;
- animationForChild(child)
- .translationX(fromX, toX)
- .start();
- updateBubblePositions();
- }
} else {
- child.setTranslationX(getBubbleXOrYForOrientation(index));
+ boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
+ final PointF p = mPositioner.getExpandedBubbleXY(index,
+ mLayout.getChildCount(),
+ onLeft);
+ if (mPositioner.showBubblesVertically()) {
+ child.setTranslationY(p.y);
+ } else {
+ child.setTranslationX(p.x);
+ }
if (!mPreparingToCollapse) {
// Only animate if we're not collapsing as that animation will handle placing the
// new bubble in the stacked position.
- float toY = getExpandedY();
- float fromY = getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
- animationForChild(child)
- .translationY(fromY, toY)
- .start();
+ if (mPositioner.showBubblesVertically()) {
+ Rect availableRect = mPositioner.getAvailableRect();
+ float fromX = onLeft
+ ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR
+ : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
+ animationForChild(child)
+ .translationX(fromX, p.y)
+ .start();
+ } else {
+ // Only animate if we're not collapsing as that animation will handle placing
+ // the new bubble in the stacked position.
+ float fromY = mPositioner.getExpandedBubblesY() - mBubbleSizePx
+ * ANIMATE_TRANSLATION_FACTOR;
+ animationForChild(child)
+ .translationY(fromY, p.y)
+ .start();
+ }
updateBubblePositions();
}
}
@@ -588,7 +572,7 @@
if (mAnimatingExpand || mAnimatingCollapse) {
return;
}
-
+ boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
for (int i = 0; i < mLayout.getChildCount(); i++) {
final View bubble = mLayout.getChildAt(i);
@@ -598,39 +582,11 @@
return;
}
- if (mPositioner.showBubblesVertically()) {
- Rect availableRect = mPositioner.getAvailableRect();
- boolean onLeft = mCollapsePoint != null
- && mCollapsePoint.x < (availableRect.width() / 2f);
- animationForChild(bubble)
- .translationX(onLeft
- ? availableRect.left
- : availableRect.right - mBubbleSizePx)
- .translationY(getBubbleXOrYForOrientation(i))
- .start();
- } else {
- animationForChild(bubble)
- .translationX(getBubbleXOrYForOrientation(i))
- .translationY(getExpandedY())
- .start();
- }
+ final PointF p = mPositioner.getExpandedBubbleXY(i, mLayout.getChildCount(), onLeft);
+ animationForChild(bubble)
+ .translationX(p.x)
+ .translationY(p.y)
+ .start();
}
}
-
- /**
- * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
- * row. When in landscape or on a large screen, they show at the left or right side in a
- * vertical row. This method accounts for screen orientation and will return an x or y value
- * for the position of the bubble in the row.
- *
- * @param index bubble index in the row.
- * @return the y position of the bubble if showing vertically and the x position if showing
- * horizontally.
- */
- public float getBubbleXOrYForOrientation(int index) {
- if (mLayout == null) {
- return 0;
- }
- return mPositioner.getBubbleXOrYForOrientation(index, mLayout.getChildCount());
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 636e145..9a08190 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -305,10 +305,7 @@
if (mLayout == null || !isStackPositionSet()) {
return true; // Default to left, which is where it starts by default.
}
-
- float stackCenter = mStackPosition.x + mBubbleSize / 2;
- float screenCenter = mLayout.getWidth() / 2;
- return stackCenter < screenCenter;
+ return mPositioner.isStackOnLeft(mStackPosition);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index bb40f67..c32dddf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
@@ -158,6 +159,15 @@
return mDividePosition;
}
+ /**
+ * Returns the divider position as a fraction from 0 to 1.
+ */
+ public float getDividerPositionAsFraction() {
+ return Math.min(1f, Math.max(0f, isLandscape()
+ ? (float) ((mBounds1.right + mBounds2.left) / 2f) / mBounds2.right
+ : (float) ((mBounds1.bottom + mBounds2.top) / 2f) / mBounds2.bottom));
+ }
+
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) {
boolean affectsLayout = false;
@@ -342,6 +352,13 @@
return bounds.width() > bounds.height();
}
+ /**
+ * Return if this layout is landscape.
+ */
+ public boolean isLandscape() {
+ return isLandscape(mRootBounds);
+ }
+
/** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
@@ -349,7 +366,7 @@
if (dividerLeash != null) {
t.setPosition(dividerLeash, mDividerBounds.left, mDividerBounds.top);
// Resets layer of divider bar to make sure it is always on top.
- t.setLayer(dividerLeash, Integer.MAX_VALUE);
+ t.setLayer(dividerLeash, SPLIT_DIVIDER_LAYER);
}
t.setPosition(leash1, mBounds1.left, mBounds1.top)
.setWindowCrop(leash1, mBounds1.width(), mBounds1.height());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index d8a7f61d..0c12d6c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -49,6 +49,7 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
@@ -180,11 +181,11 @@
Slog.w(TAG, "Unexpected drag start during an active drag");
return false;
}
+ InstanceId loggerSessionId = mLogger.logStart(event);
pd.activeDragCount++;
pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId),
- event.getClipData());
+ event.getClipData(), loggerSessionId);
setDropTargetWindowVisibility(pd, View.VISIBLE);
- mLogger.logStart(event);
break;
case ACTION_DRAG_ENTERED:
pd.dragLayout.show();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java
index 2d3f395..6e4b815 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java
@@ -51,7 +51,7 @@
/**
* Logs the start of a drag.
*/
- public void logStart(DragEvent event) {
+ public InstanceId logStart(DragEvent event) {
final ClipDescription description = event.getClipDescription();
final ClipData data = event.getClipData();
final ClipData.Item item = data.getItemAt(0);
@@ -64,6 +64,7 @@
mUiEventLogger.logWithInstanceId(getStartEnum(description),
mActivityInfo.applicationInfo.uid,
mActivityInfo.applicationInfo.packageName, mInstanceId);
+ return mInstanceId;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 5b9d7b80..102b90f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -63,6 +63,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.internal.logging.InstanceId;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
@@ -86,6 +87,7 @@
private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
+ private InstanceId mLoggerSessionId;
private DragSession mSession;
public DragAndDropPolicy(Context context, SplitScreenController splitScreen) {
@@ -104,7 +106,8 @@
/**
* Starts a new drag session with the given initial drag data.
*/
- void start(DisplayLayout displayLayout, ClipData data) {
+ void start(DisplayLayout displayLayout, ClipData data, InstanceId loggerSessionId) {
+ mLoggerSessionId = loggerSessionId;
mSession = new DragSession(mContext, mActivityTaskManager, displayLayout, data);
// TODO(b/169894807): Also update the session data with task stack changes
mSession.update();
@@ -207,6 +210,8 @@
// Launch in the side stage if we are not in split-screen already.
stage = STAGE_TYPE_SIDE;
}
+ // Add some data for logging splitscreen once it is invoked
+ mSplitScreen.logOnDroppedToSplit(position, mLoggerSessionId);
}
final ClipDescription description = data.getDescription();
@@ -294,7 +299,12 @@
@StageType int stage, @SplitPosition int position,
@Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop);
- void exitSplitScreen();
+
+ /**
+ * Exits splitscreen, with an associated exit trigger from the SplitscreenUIChanged proto
+ * for logging.
+ */
+ void exitSplitScreen(int exitTrigger);
}
/**
@@ -347,7 +357,7 @@
}
@Override
- public void exitSplitScreen() {
+ public void exitSplitScreen(int exitTrigger) {
throw new UnsupportedOperationException("exitSplitScreen not implemented by starter");
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index b342336..efc9ed0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -38,6 +38,7 @@
import androidx.annotation.NonNull;
+import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
@@ -98,8 +99,9 @@
return mHasDropped;
}
- public void prepare(DisplayLayout displayLayout, ClipData initialData) {
- mPolicy.start(displayLayout, initialData);
+ public void prepare(DisplayLayout displayLayout, ClipData initialData,
+ InstanceId loggerSessionId) {
+ mPolicy.start(displayLayout, initialData, loggerSessionId);
mHasDropped = false;
mCurrentTarget = null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 92c0099..ac02075 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -27,6 +27,7 @@
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
+import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SNAP_AFTER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE;
@@ -84,6 +85,7 @@
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipUtils;
+import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter;
import java.util.Objects;
@@ -455,11 +457,18 @@
return;
}
Runnable updateDisplayLayout = () -> {
+ final boolean fromRotation = Transitions.ENABLE_SHELL_TRANSITIONS
+ && mPipBoundsState.getDisplayLayout().rotation() != layout.rotation();
mPipBoundsState.setDisplayLayout(layout);
+ final WindowContainerTransaction wct =
+ fromRotation ? new WindowContainerTransaction() : null;
updateMovementBounds(null /* toBounds */,
- false /* fromRotation */, false /* fromImeAdjustment */,
+ fromRotation, false /* fromImeAdjustment */,
false /* fromShelfAdjustment */,
- null /* windowContainerTransaction */);
+ wct /* windowContainerTransaction */);
+ if (wct != null) {
+ mPipTaskOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_SAME);
+ }
};
if (mPipTaskOrganizer.isInPip() && saveRestoreSnapFraction) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
index 1fc4d12..ab3cbd6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
@@ -47,6 +47,8 @@
/** Callback for size compat UI interaction. */
public interface SizeCompatUICallback {
+ /** Called when the size compat restart button appears. */
+ void onSizeCompatRestartButtonAppeared(int taskId);
/** Called when the size compat restart button is clicked. */
void onSizeCompatRestartButtonClicked(int taskId);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
index a5e96d1..7cf9559 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
@@ -28,6 +28,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
+import android.util.Log;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
@@ -45,7 +46,7 @@
class SizeCompatUILayout {
private static final String TAG = "SizeCompatUILayout";
- private final SyncTransactionQueue mSyncQueue;
+ final SyncTransactionQueue mSyncQueue;
private final SizeCompatUIController.SizeCompatUICallback mCallback;
private Context mContext;
private Configuration mTaskConfig;
@@ -105,6 +106,8 @@
mShouldShowHint = false;
createSizeCompatHint();
}
+
+ mCallback.onSizeCompatRestartButtonAppeared(mTaskId);
}
/** Creates the restart button hint window. */
@@ -306,6 +309,10 @@
private void updateSurfacePosition(SurfaceControl leash, int positionX, int positionY) {
mSyncQueue.runInSync(t -> {
+ if (!leash.isValid()) {
+ Log.w(TAG, "The leash has been released.");
+ return;
+ }
t.setPosition(leash, positionX, positionY);
// The size compat UI should be the topmost child of the Task in case there can be more
// than one children.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
index f634c45..82f69c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
@@ -110,7 +110,8 @@
}
if (mLeash != null) {
- new SurfaceControl.Transaction().remove(mLeash).apply();
+ final SurfaceControl leash = mLeash;
+ mLayout.mSyncQueue.runInSync(t -> t.remove(leash));
mLeash = null;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index e2eb41a..67223c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -51,6 +51,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.logging.InstanceId;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
@@ -61,7 +63,6 @@
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
-import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;
@@ -86,6 +87,7 @@
private final DisplayImeController mDisplayImeController;
private final Transitions mTransitions;
private final TransactionPool mTransactionPool;
+ private final SplitscreenEventLogger mLogger;
private StageCoordinator mStageCoordinator;
@@ -102,6 +104,7 @@
mDisplayImeController = displayImeController;
mTransitions = transitions;
mTransactionPool = transactionPool;
+ mLogger = new SplitscreenEventLogger();
}
public SplitScreen asSplitScreen() {
@@ -123,7 +126,7 @@
// TODO: Multi-display
mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController, mTransitions,
- mTransactionPool);
+ mTransactionPool, mLogger);
}
}
@@ -165,8 +168,8 @@
leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
}
- public void exitSplitScreen() {
- mStageCoordinator.exitSplitScreen();
+ public void exitSplitScreen(int exitReason) {
+ mStageCoordinator.exitSplitScreen(exitReason);
}
public void onKeyguardOccludedChanged(boolean occluded) {
@@ -303,6 +306,13 @@
return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
}
+ /**
+ * Sets drag info to be logged when splitscreen is entered.
+ */
+ public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
+ mStageCoordinator.logOnDroppedToSplit(position, dragSessionId);
+ }
+
public void dump(@NonNull PrintWriter pw, String prefix) {
pw.println(prefix + TAG);
if (mStageCoordinator != null) {
@@ -495,7 +505,8 @@
public void exitSplitScreen() {
executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
(controller) -> {
- controller.exitSplitScreen();
+ controller.exitSplitScreen(
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
new file mode 100644
index 0000000..319079b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2021 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.splitscreen;
+
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
+
+import com.android.internal.logging.InstanceId;
+import com.android.internal.logging.InstanceIdSequence;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
+
+/**
+ * Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent
+ */
+public class SplitscreenEventLogger {
+
+ // Used to generate instance ids for this drag if one is not provided
+ private final InstanceIdSequence mIdSequence;
+
+ // The instance id for the current splitscreen session (from start to end)
+ private InstanceId mLoggerSessionId;
+
+ // Drag info
+ private @SplitPosition int mDragEnterPosition;
+ private InstanceId mDragEnterSessionId;
+
+ // For deduping async events
+ private int mLastMainStagePosition = -1;
+ private int mLastMainStageUid = -1;
+ private int mLastSideStagePosition = -1;
+ private int mLastSideStageUid = -1;
+ private float mLastSplitRatio = -1f;
+
+ public SplitscreenEventLogger() {
+ mIdSequence = new InstanceIdSequence(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Return whether a splitscreen session has started.
+ */
+ public boolean hasStartedSession() {
+ return mLoggerSessionId != null;
+ }
+
+ /**
+ * May be called before logEnter() to indicate that the session was started from a drag.
+ */
+ public void enterRequestedByDrag(@SplitPosition int position, InstanceId dragSessionId) {
+ mDragEnterPosition = position;
+ mDragEnterSessionId = dragSessionId;
+ }
+
+ /**
+ * Logs when the user enters splitscreen.
+ */
+ public void logEnter(float splitRatio,
+ @SplitPosition int mainStagePosition, int mainStageUid,
+ @SplitPosition int sideStagePosition, int sideStageUid,
+ boolean isLandscape) {
+ mLoggerSessionId = mIdSequence.newInstanceId();
+ int enterReason = mDragEnterPosition != SPLIT_POSITION_UNDEFINED
+ ? getDragEnterReasonFromSplitPosition(mDragEnterPosition, isLandscape)
+ : SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
+ updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
+ mainStageUid);
+ updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
+ sideStageUid);
+ updateSplitRatioState(splitRatio);
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__ENTER,
+ enterReason,
+ 0 /* exitReason */,
+ splitRatio,
+ mLastMainStagePosition,
+ mLastMainStageUid,
+ mLastSideStagePosition,
+ mLastSideStageUid,
+ mDragEnterSessionId != null ? mDragEnterSessionId.getId() : 0,
+ mLoggerSessionId.getId());
+ }
+
+ /**
+ * Logs when the user exits splitscreen. Only one of the main or side stages should be
+ * specified to indicate which position was focused as a part of exiting (both can be unset).
+ */
+ public void logExit(int exitReason, @SplitPosition int mainStagePosition, int mainStageUid,
+ @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
+ if (mLoggerSessionId == null) {
+ // Ignore changes until we've started logging the session
+ return;
+ }
+ if ((mainStagePosition != SPLIT_POSITION_UNDEFINED
+ && sideStagePosition != SPLIT_POSITION_UNDEFINED)
+ || (mainStageUid != 0 && sideStageUid != 0)) {
+ throw new IllegalArgumentException("Only main or side stage should be set");
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
+ 0 /* enterReason */,
+ exitReason,
+ 0f /* splitRatio */,
+ getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
+ mainStageUid,
+ getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
+ sideStageUid,
+ 0 /* dragInstanceId */,
+ mLoggerSessionId.getId());
+
+ // Reset states
+ mLoggerSessionId = null;
+ mDragEnterPosition = SPLIT_POSITION_UNDEFINED;
+ mDragEnterSessionId = null;
+ mLastMainStagePosition = -1;
+ mLastMainStageUid = -1;
+ mLastSideStagePosition = -1;
+ mLastSideStageUid = -1;
+ }
+
+ /**
+ * Logs when an app in the main stage changes.
+ */
+ public void logMainStageAppChange(@SplitPosition int mainStagePosition, int mainStageUid,
+ boolean isLandscape) {
+ if (mLoggerSessionId == null) {
+ // Ignore changes until we've started logging the session
+ return;
+ }
+ if (!updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition,
+ isLandscape), mainStageUid)) {
+ // Ignore if there are no user perceived changes
+ return;
+ }
+
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE,
+ 0 /* enterReason */,
+ 0 /* exitReason */,
+ 0f /* splitRatio */,
+ mLastMainStagePosition,
+ mLastMainStageUid,
+ 0 /* sideStagePosition */,
+ 0 /* sideStageUid */,
+ 0 /* dragInstanceId */,
+ mLoggerSessionId.getId());
+ }
+
+ /**
+ * Logs when an app in the side stage changes.
+ */
+ public void logSideStageAppChange(@SplitPosition int sideStagePosition, int sideStageUid,
+ boolean isLandscape) {
+ if (mLoggerSessionId == null) {
+ // Ignore changes until we've started logging the session
+ return;
+ }
+ if (!updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition,
+ isLandscape), sideStageUid)) {
+ // Ignore if there are no user perceived changes
+ return;
+ }
+
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE,
+ 0 /* enterReason */,
+ 0 /* exitReason */,
+ 0f /* splitRatio */,
+ 0 /* mainStagePosition */,
+ 0 /* mainStageUid */,
+ mLastSideStagePosition,
+ mLastSideStageUid,
+ 0 /* dragInstanceId */,
+ mLoggerSessionId.getId());
+ }
+
+ /**
+ * Logs when the splitscreen ratio changes.
+ */
+ public void logResize(float splitRatio) {
+ if (mLoggerSessionId == null) {
+ // Ignore changes until we've started logging the session
+ return;
+ }
+ if (splitRatio <= 0f || splitRatio >= 1f) {
+ // Don't bother reporting resizes that end up dismissing the split, that will be logged
+ // via the exit event
+ return;
+ }
+ if (!updateSplitRatioState(splitRatio)) {
+ // Ignore if there are no user perceived changes
+ return;
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__RESIZE,
+ 0 /* enterReason */,
+ 0 /* exitReason */,
+ mLastSplitRatio,
+ 0 /* mainStagePosition */, 0 /* mainStageUid */,
+ 0 /* sideStagePosition */, 0 /* sideStageUid */,
+ 0 /* dragInstanceId */,
+ mLoggerSessionId.getId());
+ }
+
+ /**
+ * Logs when the apps in splitscreen are swapped.
+ */
+ public void logSwap(@SplitPosition int mainStagePosition, int mainStageUid,
+ @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
+ if (mLoggerSessionId == null) {
+ // Ignore changes until we've started logging the session
+ return;
+ }
+
+ updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
+ mainStageUid);
+ updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
+ sideStageUid);
+ FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__SWAP,
+ 0 /* enterReason */,
+ 0 /* exitReason */,
+ 0f /* splitRatio */,
+ mLastMainStagePosition,
+ mLastMainStageUid,
+ mLastSideStagePosition,
+ mLastSideStageUid,
+ 0 /* dragInstanceId */,
+ mLoggerSessionId.getId());
+ }
+
+ private boolean updateMainStageState(int mainStagePosition, int mainStageUid) {
+ boolean changed = (mLastMainStagePosition != mainStagePosition)
+ || (mLastMainStageUid != mainStageUid);
+ if (!changed) {
+ return false;
+ }
+
+ mLastMainStagePosition = mainStagePosition;
+ mLastMainStageUid = mainStageUid;
+ return true;
+ }
+
+ private boolean updateSideStageState(int sideStagePosition, int sideStageUid) {
+ boolean changed = (mLastSideStagePosition != sideStagePosition)
+ || (mLastSideStageUid != sideStageUid);
+ if (!changed) {
+ return false;
+ }
+
+ mLastSideStagePosition = sideStagePosition;
+ mLastSideStageUid = sideStageUid;
+ return true;
+ }
+
+ private boolean updateSplitRatioState(float splitRatio) {
+ boolean changed = Float.compare(mLastSplitRatio, splitRatio) != 0;
+ if (!changed) {
+ return false;
+ }
+
+ mLastSplitRatio = splitRatio;
+ return true;
+ }
+
+ public int getDragEnterReasonFromSplitPosition(@SplitPosition int position,
+ boolean isLandscape) {
+ if (isLandscape) {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_LEFT
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_RIGHT;
+ } else {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_TOP
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_BOTTOM;
+ }
+ }
+
+ private int getMainStagePositionFromSplitPosition(@SplitPosition int position,
+ boolean isLandscape) {
+ if (position == SPLIT_POSITION_UNDEFINED) {
+ return 0;
+ }
+ if (isLandscape) {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__LEFT
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__RIGHT;
+ } else {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__TOP
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__BOTTOM;
+ }
+ }
+
+ private int getSideStagePositionFromSplitPosition(@SplitPosition int position,
+ boolean isLandscape) {
+ if (position == SPLIT_POSITION_UNDEFINED) {
+ return 0;
+ }
+ if (isLandscape) {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__LEFT
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__RIGHT;
+ } else {
+ return position == SPLIT_POSITION_TOP_OR_LEFT
+ ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__TOP
+ : FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__BOTTOM;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 54e7a52f..736fae4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -25,7 +25,14 @@
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
@@ -73,6 +80,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -81,7 +89,6 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitLayout;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
-import com.android.wm.shell.common.split.SplitWindowManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.Transitions;
@@ -130,6 +137,7 @@
private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
private final DisplayImeController mDisplayImeController;
private final SplitScreenTransitions mSplitTransitions;
+ private final SplitscreenEventLogger mLogger;
private boolean mExitSplitScreenOnHide;
private boolean mKeyguardOccluded;
@@ -156,12 +164,13 @@
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
DisplayImeController displayImeController, Transitions transitions,
- TransactionPool transactionPool) {
+ TransactionPool transactionPool, SplitscreenEventLogger logger) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
mRootTDAOrganizer = rootTDAOrganizer;
mTaskOrganizer = taskOrganizer;
+ mLogger = logger;
mMainStage = new MainStage(
mTaskOrganizer,
mDisplayId,
@@ -190,7 +199,8 @@
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController,
- SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool) {
+ SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
+ SplitscreenEventLogger logger) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
@@ -203,6 +213,7 @@
mSplitLayout = splitLayout;
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
mOnTransitionAnimationComplete);
+ mLogger = logger;
transitions.addHandler(this);
}
@@ -450,19 +461,20 @@
void onKeyguardVisibilityChanged(boolean showing) {
if (!showing && mMainStage.isActive()
&& mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) {
- exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage);
+ exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage,
+ SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED);
}
}
- void exitSplitScreen() {
- exitSplitScreen(null /* childrenToTop */);
+ void exitSplitScreen(int exitReason) {
+ exitSplitScreen(null /* childrenToTop */, exitReason);
}
void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
mExitSplitScreenOnHide = exitSplitScreenOnHide;
}
- private void exitSplitScreen(StageTaskListener childrenToTop) {
+ private void exitSplitScreen(StageTaskListener childrenToTop, int exitReason) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
mMainStage.deactivate(wct, childrenToTop == mMainStage);
@@ -470,6 +482,11 @@
// Reset divider position.
mSplitLayout.resetDividerPosition();
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
+ if (childrenToTop != null) {
+ logExitToStage(exitReason, childrenToTop == mMainStage);
+ } else {
+ logExit(exitReason);
+ }
}
/**
@@ -522,9 +539,8 @@
}
}
- private void onStageChildTaskStatusChanged(
- StageListenerImpl stageListener, int taskId, boolean present, boolean visible) {
-
+ private void onStageChildTaskStatusChanged(StageListenerImpl stageListener, int taskId,
+ boolean present, boolean visible) {
int stage;
if (present) {
stage = stageListener == mSideStageListener ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
@@ -532,6 +548,13 @@
// No longer on any stage
stage = STAGE_TYPE_UNDEFINED;
}
+ if (stage == STAGE_TYPE_MAIN) {
+ mLogger.logMainStageAppChange(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ mSplitLayout.isLandscape());
+ } else {
+ mLogger.logSideStageAppChange(getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLandscape());
+ }
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onTaskStageChanged(taskId, stage, visible);
@@ -598,7 +621,7 @@
// Don't dismiss staged split when both stages are not visible due to sleeping display,
// like the cases keyguard showing or screen off.
|| (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) {
- exitSplitScreen();
+ exitSplitScreen(SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
}
} else if (mKeyguardOccluded) {
// At least one of the stages is visible while keyguard occluded. Dismiss split because
@@ -606,7 +629,7 @@
// task contains show-when-locked activity remains on top after split dismissed.
final StageTaskListener toTop =
mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null);
- exitSplitScreen(toTop);
+ exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
}
// When both stage's visibility changed to visible, main stage might receives visibility
@@ -673,7 +696,7 @@
if (mDividerVisible) {
t.show(dividerLeash)
- .setLayer(dividerLeash, Integer.MAX_VALUE)
+ .setLayer(dividerLeash, SPLIT_DIVIDER_LAYER)
.setPosition(dividerLeash,
mSplitLayout.getDividerBounds().left,
mSplitLayout.getDividerBounds().top);
@@ -683,17 +706,16 @@
}
-
private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener;
if (!hasChildren) {
if (isSideStage && mMainStageListener.mVisible) {
// Exit to main stage if side stage no longer has children.
- exitSplitScreen(mMainStage);
+ exitSplitScreen(mMainStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
} else if (!isSideStage && mSideStageListener.mVisible) {
// Exit to side stage if main stage no longer has children.
- exitSplitScreen(mSideStage);
+ exitSplitScreen(mSideStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
}
} else if (isSideStage) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -702,6 +724,13 @@
mSideStage.setBounds(getSideStageBounds(), wct);
mTaskOrganizer.applyTransaction(wct);
}
+ if (!mLogger.hasStartedSession() && mMainStageListener.mHasChildren
+ && mSideStageListener.mHasChildren) {
+ mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
+ getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLandscape());
+ }
}
@VisibleForTesting
@@ -720,13 +749,17 @@
onSnappedToDismissTransition(mainStageToTop);
return;
}
- exitSplitScreen(mainStageToTop ? mMainStage : mSideStage);
+ exitSplitScreen(mainStageToTop ? mMainStage : mSideStage,
+ SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER);
}
@Override
public void onDoubleTappedDivider() {
setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */);
+ mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLandscape());
}
@Override
@@ -740,6 +773,7 @@
updateWindowBounds(layout, wct);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
+ mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
}
/**
@@ -1099,7 +1133,7 @@
// Be default, make it visible. The remote animator can adjust alpha if it plans to animate.
if (show) {
t.setAlpha(leash, 1.f);
- t.setLayer(leash, Integer.MAX_VALUE);
+ t.setLayer(leash, SPLIT_DIVIDER_LAYER);
t.setPosition(leash, bounds.left, bounds.top);
t.show(leash);
}
@@ -1139,6 +1173,36 @@
mMainStageListener.mHasChildren = mSideStageListener.mHasChildren = visible;
}
+ /**
+ * Sets drag info to be logged when splitscreen is next entered.
+ */
+ public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
+ mLogger.enterRequestedByDrag(position, dragSessionId);
+ }
+
+ /**
+ * Logs the exit of splitscreen.
+ */
+ private void logExit(int exitReason) {
+ mLogger.logExit(exitReason,
+ SPLIT_POSITION_UNDEFINED, 0 /* mainStageUid */,
+ SPLIT_POSITION_UNDEFINED, 0 /* sideStageUid */,
+ mSplitLayout.isLandscape());
+ }
+
+ /**
+ * Logs the exit of splitscreen to a specific stage. This must be called before the exit is
+ * executed.
+ */
+ private void logExitToStage(int exitReason, boolean toMainStage) {
+ mLogger.logExit(exitReason,
+ toMainStage ? getMainStagePosition() : SPLIT_POSITION_UNDEFINED,
+ toMainStage ? mMainStage.getTopChildTaskUid() : 0 /* mainStageUid */,
+ !toMainStage ? getSideStagePosition() : SPLIT_POSITION_UNDEFINED,
+ !toMainStage ? mSideStage.getTopChildTaskUid() : 0 /* sideStageUid */,
+ mSplitLayout.isLandscape());
+ }
+
class StageListenerImpl implements StageTaskListener.StageListenerCallbacks {
boolean mHasRootTask = false;
boolean mVisible = false;
@@ -1178,7 +1242,8 @@
@Override
public void onNoLongerSupportMultiWindow() {
if (mMainStage.isActive()) {
- StageCoordinator.this.exitSplitScreen();
+ StageCoordinator.this.exitSplitScreen(
+ SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index c47353a..3512a0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -97,6 +97,20 @@
return mChildrenTaskInfo.contains(taskId);
}
+ /**
+ * Returns the top activity uid for the top child task.
+ */
+ int getTopChildTaskUid() {
+ for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
+ final ActivityManager.RunningTaskInfo info = mChildrenTaskInfo.valueAt(i);
+ if (info.topActivityInfo == null) {
+ continue;
+ }
+ return info.topActivityInfo.applicationInfo.uid;
+ }
+ return 0;
+ }
+
/** @return {@code true} if this listener contains the currently focused task. */
boolean isFocused() {
if (mRootTaskInfo.isFocused) return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index a13b03d..ada2ed2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -19,6 +19,7 @@
import static android.hardware.HardwareBuffer.RGBA_8888;
import static android.hardware.HardwareBuffer.USAGE_PROTECTED_CONTENT;
import static android.util.RotationUtils.deltaRotation;
+import static android.view.WindowManagerPolicyConstants.SCREEN_FREEZE_LAYER_BASE;
import static com.android.wm.shell.transition.DefaultTransitionHandler.startSurfaceAnimation;
import static com.android.wm.shell.transition.Transitions.TAG;
@@ -81,19 +82,6 @@
* </ul>
*/
class ScreenRotationAnimation {
-
- /** How much to multiply the policy's type layer, to reserve room
- * for multiple windows of the same type and Z-ordering adjustment
- * with TYPE_LAYER_OFFSET. */
- static final int TYPE_LAYER_MULTIPLIER = 10000;
- static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
-
- /*
- * Layers for screen rotation animation. We put these layers above
- * WINDOW_FREEZE_LAYER so that screen freeze will cover all windows.
- */
- private static final int SCREEN_FREEZE_LAYER_BASE = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER;
-
static final int MAX_ANIMATION_DURATION = 10 * 1000;
private final Context mContext;
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index 901b7a3..2d996ca 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -18,6 +18,7 @@
import android.app.Instrumentation
import android.content.ComponentName
+import android.content.res.Resources
import com.android.wm.shell.flicker.testapp.Components
class SplitScreenHelper(
@@ -30,6 +31,11 @@
const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
+ // TODO: remove all legacy split screen flicker tests when legacy split screen is fully
+ // deprecated.
+ fun isUsingLegacySplit(): Boolean =
+ Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useLegacySplit)
+
fun getPrimary(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(instrumentation,
Components.SplitScreenActivity.LABEL,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
index 666d259..3117693 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
@@ -39,6 +39,7 @@
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import org.junit.After
import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
@@ -56,6 +57,8 @@
@Before
open fun setup() {
+ // Only run legacy split tests when the system is using legacy split screen.
+ assumeTrue(SplitScreenHelper.isUsingLegacySplit())
// Legacy split is having some issue with Shell transition, and will be deprecated soon.
assumeFalse(isShellTransitionsEnabled())
prevDevEnableNonResizableMultiWindow = getDevEnableNonResizableMultiWindow(context)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index e0ec757..45cb152 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -32,6 +32,8 @@
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.traces.common.Region
+import com.android.server.wm.traces.parser.minus
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
@@ -94,7 +96,10 @@
@Test
fun appLayerRotates_StartingBounds() {
testSpec.assertLayersStart {
- visibleRegion(fixedApp.component).coversExactly(startingBounds)
+ val pipRegion = visibleRegion(pipApp.component).region
+ val expectedWithoutPip = Region(startingBounds.bounds.left, startingBounds.bounds.top,
+ startingBounds.bounds.right, startingBounds.bounds.bottom).minus(pipRegion)
+ visibleRegion(fixedApp.component).coversExactly(expectedWithoutPip)
visibleRegion(pipApp.component).coversAtMost(startingBounds)
}
}
@@ -103,7 +108,10 @@
@Test
fun appLayerRotates_EndingBounds() {
testSpec.assertLayersEnd {
- visibleRegion(fixedApp.component).coversExactly(endingBounds)
+ val pipRegion = visibleRegion(pipApp.component).region
+ val expectedWithoutPip = Region(endingBounds.bounds.left, endingBounds.bounds.top,
+ endingBounds.bounds.right, endingBounds.bounds.bottom).minus(pipRegion)
+ visibleRegion(fixedApp.component).coversExactly(expectedWithoutPip)
visibleRegion(pipApp.component).coversAtMost(endingBounds)
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java
index 1eba3c2..9732a88 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import android.annotation.SuppressLint;
import android.content.res.Configuration;
@@ -41,7 +42,6 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Spy;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -49,26 +49,26 @@
private int mDisplayWidth = 500;
private int mDisplayHeight = 1000;
- private int mExpandedViewPadding = 10;
private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class);
- @Spy
ExpandedAnimationController mExpandedController;
private int mStackOffset;
private PointF mExpansionPoint;
+ private BubblePositioner mPositioner;
@SuppressLint("VisibleForTests")
@Before
public void setUp() throws Exception {
super.setUp();
- BubblePositioner positioner = new BubblePositioner(getContext(), mock(WindowManager.class));
- positioner.updateInternal(Configuration.ORIENTATION_PORTRAIT,
+ mPositioner = new BubblePositioner(getContext(), mock(WindowManager.class));
+ mPositioner.updateInternal(Configuration.ORIENTATION_PORTRAIT,
Insets.of(0, 0, 0, 0),
new Rect(0, 0, mDisplayWidth, mDisplayHeight));
- mExpandedController = new ExpandedAnimationController(positioner, mExpandedViewPadding,
+ mExpandedController = new ExpandedAnimationController(mPositioner,
mOnBubbleAnimatedOutAction);
+ spyOn(mExpandedController);
addOneMoreThanBubbleLimitBubbles();
mLayout.setActiveController(mExpandedController);
@@ -141,13 +141,16 @@
/** Check that children are in the correct positions for being expanded. */
private void testBubblesInCorrectExpandedPositions() {
+ boolean onLeft = mPositioner.isStackOnLeft(mExpansionPoint);
// Check all the visible bubbles to see if they're in the right place.
for (int i = 0; i < mLayout.getChildCount(); i++) {
- float expectedPosition = mExpandedController.getBubbleXOrYForOrientation(i);
- assertEquals(expectedPosition,
+ PointF expectedPosition = mPositioner.getExpandedBubbleXY(i,
+ mLayout.getChildCount(),
+ onLeft);
+ assertEquals(expectedPosition.x,
mLayout.getChildAt(i).getTranslationX(),
2f);
- assertEquals(expectedPosition,
+ assertEquals(expectedPosition.y,
mLayout.getChildAt(i).getTranslationY(), 2f);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index 1a70f76..734b97b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -65,6 +65,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.InstanceId;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -96,6 +97,9 @@
@Mock
private SplitScreenController mSplitScreenStarter;
+ @Mock
+ private InstanceId mLoggerSessionId;
+
private DisplayLayout mLandscapeDisplayLayout;
private DisplayLayout mPortraitDisplayLayout;
private Insets mInsets;
@@ -201,7 +205,7 @@
@Test
public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() {
setRunningTask(mHomeTask);
- mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
@@ -213,7 +217,7 @@
@Test
public void testDragAppOverFullscreenApp_expectSplitScreenTargets() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -230,7 +234,7 @@
@Test
public void testDragAppOverFullscreenAppPhone_expectVerticalSplitScreenTargets() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mPortraitDisplayLayout, mActivityClipData);
+ mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -248,7 +252,7 @@
public void testDragAppOverSplitApp_expectSplitTargets_DropLeft() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -261,7 +265,7 @@
public void testDragAppOverSplitApp_expectSplitTargets_DropRight() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -274,7 +278,7 @@
public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropTop() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mPortraitDisplayLayout, mActivityClipData);
+ mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -287,7 +291,7 @@
public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropBottom() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mPortraitDisplayLayout, mActivityClipData);
+ mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -299,7 +303,7 @@
@Test
public void testTargetHitRects() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = mPolicy.getTargets(mInsets);
for (Target t : targets) {
assertTrue(mPolicy.getTargetAtLocation(t.hitRegion.left, t.hitRegion.top) == t);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index ab6f7699..b0a39d6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -65,9 +65,10 @@
TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
MainStage mainStage, SideStage sideStage, DisplayImeController imeController,
- SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool) {
+ SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
+ SplitscreenEventLogger logger) {
super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage,
- sideStage, imeController, splitLayout, transitions, transactionPool);
+ sideStage, imeController, splitLayout, transitions, transactionPool, logger);
// Prepare default TaskDisplayArea for testing.
mDisplayAreaInfo = new DisplayAreaInfo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index b6da868..cb759dc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -82,6 +82,7 @@
@Mock private TransactionPool mTransactionPool;
@Mock private Transitions mTransitions;
@Mock private SurfaceSession mSurfaceSession;
+ @Mock private SplitscreenEventLogger mLogger;
private SplitLayout mSplitLayout;
private MainStage mMainStage;
private SideStage mSideStage;
@@ -107,7 +108,8 @@
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
- mDisplayImeController, mSplitLayout, mTransitions, mTransactionPool);
+ mDisplayImeController, mSplitLayout, mTransitions, mTransactionPool,
+ mLogger);
mSplitScreenTransitions = mStageCoordinator.getSplitTransitions();
doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class))
.when(mTransitions).startTransition(anyInt(), any(), any());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 06b0868..a4b76fb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -59,6 +59,7 @@
@Mock private DisplayImeController mDisplayImeController;
@Mock private Transitions mTransitions;
@Mock private TransactionPool mTransactionPool;
+ @Mock private SplitscreenEventLogger mLogger;
private StageCoordinator mStageCoordinator;
@Before
@@ -66,7 +67,8 @@
MockitoAnnotations.initMocks(this);
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
- mDisplayImeController, null /* splitLayout */, mTransitions, mTransactionPool);
+ mDisplayImeController, null /* splitLayout */, mTransitions, mTransactionPool,
+ mLogger);
}
@Test
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c1a0a9a..b4cafd8 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -93,9 +93,9 @@
final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
setTitle(Html.fromHtml(getString(
R.string.confirmation_title,
- getCallingAppName(),
- profileName,
- selectedDevice.getDisplayName()), 0));
+ Html.escapeHtml(getCallingAppName()),
+ Html.escapeHtml(selectedDevice.getDisplayName())), 0));
+
mPairButton = findViewById(R.id.button_pair);
mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice));
getService().mSelectedDevice = selectedDevice;
@@ -108,8 +108,8 @@
mPairButton = findViewById(R.id.button_pair);
mPairButton.setVisibility(View.GONE);
setTitle(Html.fromHtml(getString(R.string.chooser_title,
- profileName,
- getCallingAppName()), 0));
+ Html.escapeHtml(profileName),
+ Html.escapeHtml(getCallingAppName())), 0));
mDeviceListView = findViewById(R.id.device_list);
mDevicesAdapter = new DevicesAdapter();
mDeviceListView.setAdapter(mDevicesAdapter);
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 48cdf16..197b7b2 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -31,7 +31,7 @@
android:directBootAware="true">
<receiver android:name=".TemporaryFileManager"
- android:exported="true">
+ android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
@@ -76,7 +76,7 @@
<receiver android:name=".InstallEventReceiver"
android:permission="android.permission.INSTALL_PACKAGES"
- android:exported="true">
+ android:exported="false">
<intent-filter android:priority="1">
<action android:name="com.android.packageinstaller.ACTION_INSTALL_COMMIT" />
</intent-filter>
@@ -106,14 +106,14 @@
<receiver android:name=".UninstallEventReceiver"
android:permission="android.permission.INSTALL_PACKAGES"
- android:exported="true">
+ android:exported="false">
<intent-filter android:priority="1">
<action android:name="com.android.packageinstaller.ACTION_UNINSTALL_COMMIT" />
</intent-filter>
</receiver>
<receiver android:name=".PackageInstalledReceiver"
- android:exported="true">
+ android:exported="false">
<intent-filter android:priority="1">
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
diff --git a/packages/PackageInstaller/TEST_MAPPING b/packages/PackageInstaller/TEST_MAPPING
index 5d7b9bb..cef9014 100644
--- a/packages/PackageInstaller/TEST_MAPPING
+++ b/packages/PackageInstaller/TEST_MAPPING
@@ -19,6 +19,9 @@
},
{
"name": "CtsPackageUninstallTestCases"
+ },
+ {
+ "name": "PackageInstallerTests"
}
]
-}
\ No newline at end of file
+}
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index 9cb4416..806734f 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -52,7 +52,7 @@
<string name="generic_error_dlg_text" msgid="5287861443265795232">"యాప్ను అన్ఇన్స్టాల్ చేయడం సాధ్యపడలేదు."</string>
<string name="uninstall_application_title" msgid="4045420072401428123">"యాప్ను అన్ఇన్స్టాల్ చేయి"</string>
<string name="uninstall_update_title" msgid="824411791011583031">"అప్డేట్ అన్ఇన్స్టాల్ చేయి"</string>
- <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> అనేది క్రింది యాప్లో ఒక భాగం:"</string>
+ <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> అనేది కింది యాప్లో ఒక భాగం:"</string>
<string name="uninstall_application_text" msgid="3816830743706143980">"మీరు ఈ యాప్ను అన్ఇన్స్టాల్ చేయాలనుకుంటున్నారా?"</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"మీరు ఈ యాప్ను "<b>"అందరు"</b>" వినియోగదారులకు అన్ఇన్స్టాల్ చేయాలనుకుంటున్నారా? అప్లికేషన్, దాని డేటా పరికరంలోని "<b>"అందరు"</b>" వినియోగదారుల నుండి తీసివేయబడుతుంది."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"మీరు వినియోగదారు <xliff:g id="USERNAME">%1$s</xliff:g> కోసం ఈ యాప్ను అన్ఇన్స్టాల్ చేయాలనుకుంటున్నారా?"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b503fdb..693a6d2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -155,7 +155,7 @@
<string name="running_process_item_user_label" msgid="3988506293099805796">"Utilisateur : <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"Certaines préférences par défaut définies"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"Aucune préférence par défaut définie"</string>
- <string name="tts_settings" msgid="8130616705989351312">"Synthèse vocale"</string>
+ <string name="tts_settings" msgid="8130616705989351312">"Paramètres de synthèse vocale"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"Synthèse vocale"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"Cadence"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"Vitesse à laquelle le texte est énoncé"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 8903f14..1c03e22 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -88,7 +88,7 @@
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ఇన్పుట్ పరికరం"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ఇంటర్నెట్ యాక్సెస్"</string>
<string name="bluetooth_profile_pbap" msgid="7064307749579335765">"కాంటాక్ట్ షేరింగ్"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"పరిచయ భాగస్వామ్యం కోసం ఉపయోగించు"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"కాంటాక్ట్ షేరింగ్ కోసం ఉపయోగించండి"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ భాగస్వామ్యం"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"వచన మెసేజ్లు"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM యాక్సెస్"</string>
@@ -172,7 +172,7 @@
<string name="tts_engine_security_warning" msgid="3372432853837988146">"ఈ ప్రసంగ సమన్వయ ఇంజిన్ చదివి వినిపించబడే మొత్తం వచనాన్ని అలాగే పాస్వర్డలు మరియు క్రెడిట్ కార్డు నంబర్ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ఇంజిన్లో అందించబడుతుంది. ఈ ప్రసంగ సమన్వయ ఇంజిన్ యొక్క వినియోగాన్ని ప్రారంభించాలా?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"వచనం నుండి ప్రసంగం అవుట్పుట్ కోసం ఈ భాషకు పని చేస్తున్న నెట్వర్క్ కనెక్షన్ కావాలి."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"ఇది ప్రసంగ సమన్వయానికి ఉదాహరణ"</string>
- <string name="tts_status_title" msgid="8190784181389278640">"డిఫాల్ట్ భాష స్థితి"</string>
+ <string name="tts_status_title" msgid="8190784181389278640">"ఆటోమేటిక్ భాష స్టేటస్"</string>
<string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g>కి పూర్తి మద్దతు ఉంది"</string>
<string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g>కి నెట్వర్క్ కనెక్షన్ అవసరం"</string>
<string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g>కు మద్దతు లేదు"</string>
@@ -182,7 +182,7 @@
<string name="tts_engine_preference_section_title" msgid="3861562305498624904">"ప్రాధాన్య ఇంజిన్"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"సాధారణం"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"ప్రసంగ స్వర స్థాయిని రీసెట్ చేయండి"</string>
- <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"వచనాన్ని చదివి వినిపించే స్వర స్థాయిని డిఫాల్ట్కి రీసెట్ చేస్తుంది."</string>
+ <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"టెక్స్ట్ను చదివి వినిపించే స్వర స్థాయిని ఆటోమేటిక్కు రీసెట్ చేస్తుంది."</string>
<string-array name="tts_rate_entries">
<item msgid="9004239613505400644">"చాలా నెమ్మది"</item>
<item msgid="1815382991399815061">"నెమ్మది"</item>
@@ -388,7 +388,7 @@
<string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"బ్యాకప్ పాస్వర్డ్ను సెట్ చేయడంలో వైఫల్యం"</string>
<string name="loading_injected_setting_summary" msgid="8394446285689070348">"లోడ్ చేస్తోంది…"</string>
<string-array name="color_mode_names">
- <item msgid="3836559907767149216">"సచేతనం (డిఫాల్ట్)"</item>
+ <item msgid="3836559907767149216">"వైబ్రంట్ (ఆటోమేటిక్)"</item>
<item msgid="9112200311983078311">"సహజం"</item>
<item msgid="6564241960833766170">"స్టాండర్డ్"</item>
</string-array>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 72fa25f..bf0dc7b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -157,7 +157,6 @@
private Network mDefaultNetwork = null;
private NetworkCapabilities mDefaultNetworkCapabilities = null;
private final Runnable mCallback;
- private final boolean mSupportMergedUi;
private WifiInfo mWifiInfo;
public boolean enabled;
@@ -181,7 +180,6 @@
mNetworkScoreManager = networkScoreManager;
mConnectivityManager = connectivityManager;
mCallback = callback;
- mSupportMergedUi = false;
}
public void setListening(boolean listening) {
@@ -223,10 +221,8 @@
} else {
ssid = getValidSsid(mWifiInfo);
}
- if (mSupportMergedUi) {
- isCarrierMerged = mWifiInfo.isCarrierMerged();
- subId = mWifiInfo.getSubscriptionId();
- }
+ isCarrierMerged = mWifiInfo.isCarrierMerged();
+ subId = mWifiInfo.getSubscriptionId();
updateRssi(mWifiInfo.getRssi());
maybeRequestNetworkScore();
}
@@ -255,10 +251,8 @@
} else {
ssid = getValidSsid(mWifiInfo);
}
- if (mSupportMergedUi) {
- isCarrierMerged = mWifiInfo.isCarrierMerged();
- subId = mWifiInfo.getSubscriptionId();
- }
+ isCarrierMerged = mWifiInfo.isCarrierMerged();
+ subId = mWifiInfo.getSubscriptionId();
updateRssi(mWifiInfo.getRssi());
maybeRequestNetworkScore();
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 01ae1e9..db33c3f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -78,5 +78,6 @@
Settings.Global.POWER_BUTTON_LONG_PRESS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT,
+ Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 6022608..96f127b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -101,6 +101,7 @@
Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
Settings.Secure.QS_TILES,
+ Settings.Secure.QS_AUTO_ADDED_TILES,
Settings.Secure.CONTROLS_ENABLED,
Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT,
Settings.Secure.DOZE_ENABLED,
@@ -118,7 +119,6 @@
Settings.Secure.VR_DISPLAY_MODE,
Settings.Secure.NOTIFICATION_BADGING,
Settings.Secure.NOTIFICATION_DISMISS_RTL,
- Settings.Secure.QS_AUTO_ADDED_TILES,
Settings.Secure.SCREENSAVER_ENABLED,
Settings.Secure.SCREENSAVER_COMPONENTS,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 3c7d7a8..d0448ef 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -20,6 +20,7 @@
import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
import static android.view.Display.HdrCapabilities.HDR_TYPES;
@@ -142,6 +143,7 @@
VALIDATORS.put(Global.DEVICE_CONFIG_SYNC_DISABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.AUTOMATIC_POWER_SAVE_MODE, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Global.ADVANCED_BATTERY_USAGE_AMOUNT, PERCENTAGE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, NONE_NEGATIVE_LONG_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index c577868..6cfcb51 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -72,8 +72,9 @@
* {@hide}
*/
private static final ArraySet<String> sBroadcastOnRestore;
+ private static final ArraySet<String> sBroadcastOnRestoreSystemUI;
static {
- sBroadcastOnRestore = new ArraySet<String>(4);
+ sBroadcastOnRestore = new ArraySet<String>(9);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
@@ -83,6 +84,9 @@
sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME);
sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+ sBroadcastOnRestoreSystemUI = new ArraySet<String>(2);
+ sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_TILES);
+ sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_AUTO_ADDED_TILES);
}
private interface SettingsLookup {
@@ -133,6 +137,7 @@
// Will we need a post-restore broadcast for this element?
String oldValue = null;
boolean sendBroadcast = false;
+ boolean sendBroadcastSystemUI = false;
final SettingsLookup table;
if (destination.equals(Settings.Secure.CONTENT_URI)) {
@@ -143,10 +148,12 @@
table = sGlobalLookup;
}
- if (sBroadcastOnRestore.contains(name)) {
+ sendBroadcast = sBroadcastOnRestore.contains(name);
+ sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name);
+
+ if (sendBroadcast || sendBroadcastSystemUI) {
// TODO: http://b/22388012
oldValue = table.lookup(cr, name, UserHandle.USER_SYSTEM);
- sendBroadcast = true;
}
try {
@@ -193,18 +200,28 @@
} catch (Exception e) {
// If we fail to apply the setting, by definition nothing happened
sendBroadcast = false;
+ sendBroadcastSystemUI = false;
} finally {
// If this was an element of interest, send the "we just restored it"
// broadcast with the historical value now that the new value has
// been committed and observers kicked off.
- if (sendBroadcast) {
+ if (sendBroadcast || sendBroadcastSystemUI) {
Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED)
- .setPackage("android").addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
.putExtra(Intent.EXTRA_SETTING_NAME, name)
.putExtra(Intent.EXTRA_SETTING_NEW_VALUE, value)
.putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, oldValue)
.putExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, restoredFromSdkInt);
- context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
+
+ if (sendBroadcast) {
+ intent.setPackage("android");
+ context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
+ }
+ if (sendBroadcastSystemUI) {
+ intent.setPackage(
+ context.getString(com.android.internal.R.string.config_systemUi));
+ context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
+ }
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 073b4d0..90cec3f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1195,6 +1195,9 @@
dumpSetting(s, p,
Settings.Global.POWER_MANAGER_CONSTANTS,
GlobalSettingsProto.POWER_MANAGER_CONSTANTS);
+ dumpSetting(s, p,
+ Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
+ GlobalSettingsProto.POWER_BUTTON_LONG_PRESS_DURATION_MS);
final long prepaidSetupToken = p.start(GlobalSettingsProto.PREPAID_SETUP);
dumpSetting(s, p,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index a50efd7..3cbe435 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -5,7 +5,6 @@
import android.animation.ValueAnimator
import android.app.ActivityManager
import android.app.ActivityTaskManager
-import android.app.AppGlobals
import android.app.PendingIntent
import android.app.TaskInfo
import android.content.Context
@@ -44,6 +43,7 @@
context: Context
) {
companion object {
+ private const val DEBUG = false
const val ANIMATION_DURATION = 500L
private const val ANIMATION_DURATION_FADE_OUT_CONTENT = 150L
private const val ANIMATION_DURATION_FADE_IN_WINDOW = 183L
@@ -75,8 +75,6 @@
}
}
- private val packageManager = AppGlobals.getPackageManager()
-
/** The interpolator used for the width, height, Y position and corner radius. */
private val animationInterpolator = AnimationUtils.loadInterpolator(context,
R.interpolator.launch_animation_interpolator_y)
@@ -100,6 +98,10 @@
* If possible, you should pass the [packageName] of the intent that will be started so that
* trampoline activity launches will also be animated.
*
+ * If the device is currently locked, the user will have to unlock it before the intent is
+ * started unless [showOverLockscreen] is true. In that case, the activity will be started
+ * directly over the lockscreen.
+ *
* This method will throw any exception thrown by [intentStarter].
*/
@JvmOverloads
@@ -107,21 +109,22 @@
controller: Controller?,
animate: Boolean = true,
packageName: String? = null,
+ showOverLockscreen: Boolean = false,
intentStarter: (RemoteAnimationAdapter?) -> Int
) {
if (controller == null || !animate) {
- Log.d(TAG, "Starting intent with no animation")
+ Log.i(TAG, "Starting intent with no animation")
intentStarter(null)
controller?.callOnIntentStartedOnMainThread(willAnimate = false)
return
}
- Log.d(TAG, "Starting intent with a launch animation")
val runner = Runner(controller)
- val isOnKeyguard = callback.isOnKeyguard()
+ val hideKeyguardWithAnimation = callback.isOnKeyguard() && !showOverLockscreen
- // Pass the RemoteAnimationAdapter to the intent starter only if we are not on the keyguard.
- val animationAdapter = if (!isOnKeyguard) {
+ // Pass the RemoteAnimationAdapter to the intent starter only if we are not hiding the
+ // keyguard with the animation
+ val animationAdapter = if (!hideKeyguardWithAnimation) {
RemoteAnimationAdapter(
runner,
ANIMATION_DURATION,
@@ -149,9 +152,11 @@
val willAnimate =
launchResult == ActivityManager.START_TASK_TO_FRONT ||
launchResult == ActivityManager.START_SUCCESS ||
- (launchResult == ActivityManager.START_DELIVERED_TO_TOP && isOnKeyguard)
+ (launchResult == ActivityManager.START_DELIVERED_TO_TOP &&
+ hideKeyguardWithAnimation)
- Log.d(TAG, "launchResult=$launchResult willAnimate=$willAnimate isOnKeyguard=$isOnKeyguard")
+ Log.i(TAG, "launchResult=$launchResult willAnimate=$willAnimate " +
+ "hideKeyguardWithAnimation=$hideKeyguardWithAnimation")
controller.callOnIntentStartedOnMainThread(willAnimate)
// If we expect an animation, post a timeout to cancel it in case the remote animation is
@@ -160,7 +165,7 @@
runner.postTimeout()
// Hide the keyguard using the launch animation instead of the default unlock animation.
- if (isOnKeyguard) {
+ if (hideKeyguardWithAnimation) {
callback.hideKeyguardWithAnimation(runner)
}
}
@@ -424,13 +429,16 @@
nonApps: Array<out RemoteAnimationTarget>?,
iCallback: IRemoteAnimationFinishedCallback?
) {
- Log.d(TAG, "Remote animation started")
+ if (DEBUG) {
+ Log.d(TAG, "Remote animation started")
+ }
+
val window = apps?.firstOrNull {
it.mode == RemoteAnimationTarget.MODE_OPENING
}
if (window == null) {
- Log.d(TAG, "Aborting the animation as no window is opening")
+ Log.i(TAG, "Aborting the animation as no window is opening")
removeTimeout()
iCallback?.invoke()
controller.onLaunchAnimationCancelled()
@@ -500,7 +508,10 @@
val launchContainerOverlay = launchContainer.overlay
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
- Log.d(TAG, "Animation started")
+ if (DEBUG) {
+ Log.d(TAG, "Animation started")
+ }
+
callback.setBlursDisabledForAppLaunch(true)
controller.onLaunchAnimationStart(isExpandingFullyAbove)
@@ -511,7 +522,10 @@
}
override fun onAnimationEnd(animation: Animator?) {
- Log.d(TAG, "Animation ended")
+ if (DEBUG) {
+ Log.d(TAG, "Animation ended")
+ }
+
callback.setBlursDisabledForAppLaunch(false)
iCallback?.invoke()
controller.onLaunchAnimationEnd(isExpandingFullyAbove)
@@ -686,7 +700,7 @@
return
}
- Log.d(TAG, "Remote animation timed out")
+ Log.i(TAG, "Remote animation timed out")
timedOut = true
controller.onLaunchAnimationCancelled()
}
@@ -696,7 +710,7 @@
return
}
- Log.d(TAG, "Remote animation was cancelled")
+ Log.i(TAG, "Remote animation was cancelled")
cancelled = true
removeTimeout()
context.mainExecutor.execute {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index 7c81325..6d088f0 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -60,8 +60,16 @@
*/
void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags);
void startActivity(Intent intent, boolean dismissShade);
+
+ default void startActivity(Intent intent, boolean dismissShade,
+ @Nullable ActivityLaunchAnimator.Controller animationController) {
+ startActivity(intent, dismissShade, animationController,
+ false /* showOverLockscreenWhenLocked */);
+ }
+
void startActivity(Intent intent, boolean dismissShade,
- @Nullable ActivityLaunchAnimator.Controller animationController);
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ boolean showOverLockscreenWhenLocked);
void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade);
void startActivity(Intent intent, boolean dismissShade, Callback callback);
void postStartActivityDismissingKeyguard(Intent intent, int delay);
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 967d5cb..2908bae 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ সাময়িকভাবে বন্ধ করা আছে"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ করা সাময়িকভাবে বন্ধ রাখা হয়েছে"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index ac5a58e..5be92983 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aufladen vorübergehend eingeschränkt"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laden vorübergehend eingeschränkt"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 38a7139..f8c8cad 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • recharge temporairement limitée"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge temporairement limitée"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index a41cce7..e87ee92 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ હંગામીરૂપે પ્રતિબંધિત કરવામાં આવ્યું છે"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જ કરવાનું થોડા સમય માટે મર્યાદિત કરવામાં આવ્યું છે"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 6237075..edf8ab2 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dibatasi untuk sementara"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dibatasi sementara"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 4e7ac49..bbc5aa0 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה מוגבלת זמנית"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה מוגבלת באופן זמני"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"כדאי לחבר את המטען."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index a1d58b7..60b52ea 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電は一時的に制限されています"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電を一時的に制限しています"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index a0ae88a..eca4957 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយឺត"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានដាក់កម្រិតការសាកថ្មជាបណ្ដោះអាសន្ន"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានដាក់កំហិតលើការសាកថ្មជាបណ្ដោះអាសន្ន"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាកថ្មរបស់អ្នក។"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ដើម្បីដោះសោ។"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញជាប់សោ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 98b1af6..5cbe02e 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತವಾಗಿದೆ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 65b0409..b6fd676 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ຈຳກັດການສາກໄຟຊົ່ວຄາວ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ຈຳກັດການສາກໄຟຊົ່ວຄາວແລ້ວ"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 110b711..b4f709d 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэхийг түр зуур хязгаарласан"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэхийг түр хязгаарласан"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 82579d4..6092cc7 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan terhad buat sementara waktu"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan terhad sementara"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 371d993..bb388ea 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Začasno omejeno polnjenje"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje začasno omejeno"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index adec7fe..ef36fdd 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாவது தற்காலிகமாக வரம்பிடப்பட்டுள்ளது"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜிங் தற்காலிகமாக வரம்பிடப்பட்டுள்ளது"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"அன்லாக் செய்ய மெனுவை அழுத்தவும்."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 3c3972c..be10a50 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Khả năng sạc tạm thời bị hạn chế"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Chức năng sạc tạm thời bị hạn chế"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index d950d40..621fe49 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -38,7 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電功能暫時受到限制"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 已暫時限制充電"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
diff --git a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
index 1535e72..3a08a71 100644
--- a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
+++ b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
@@ -22,11 +22,12 @@
android:color="?android:attr/textColorPrimary">
<item>
<shape
- android:shape="oval">
+ android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface"/>
<size
android:width="@dimen/keyguard_affordance_width"
android:height="@dimen/keyguard_affordance_height"/>
+ <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/>
</shape>
</item>
</ripple>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_lite.xml b/packages/SystemUI/res/layout/global_actions_grid_lite.xml
index 2430eec..5588fd3 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_lite.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_lite.xml
@@ -13,13 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
+<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/global_actions_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center">
<com.android.systemui.globalactions.GlobalActionsLayoutLite
@@ -29,8 +28,11 @@
android:orientation="vertical"
android:clipChildren="false"
android:clipToPadding="false"
- android:background="@drawable/global_actions_lite_background"
- android:padding="@dimen/global_actions_lite_padding">
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:layout_weight="1">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -38,6 +40,8 @@
android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
android:orientation="horizontal"
+ android:background="@drawable/global_actions_lite_background"
+ android:padding="@dimen/global_actions_lite_padding"
android:layoutDirection="ltr">
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/list_flow"
@@ -53,4 +57,4 @@
app:flow_horizontalStyle="packed"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.android.systemui.globalactions.GlobalActionsLayoutLite>
-</LinearLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_toast.xml b/packages/SystemUI/res/layout/global_actions_toast.xml
new file mode 100644
index 0000000..1f08996
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_toast.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
+ android:gravity="center"
+ android:layout_marginBottom="@dimen/global_actions_info_margin"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintWidth_max="382dp"
+ android:layout_weight="0"
+ android:background="@drawable/global_actions_lite_background"
+ android:theme="@style/Theme.SystemUI.QuickSettings"
+ android:paddingTop="14dp"
+ android:paddingBottom="14dp"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textSize="14sp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/global_action_smart_lock_disabled" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 59e1a75..78655c0 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -20,9 +20,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qs_detail_background"
+ android:layout_marginTop="@dimen/qs_detail_margin_top"
android:clickable="true"
android:orientation="vertical"
- android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
android:paddingBottom="8dp"
android:visibility="invisible"
android:elevation="4dp"
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index da80633..d1ab054 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -28,7 +28,7 @@
<com.android.systemui.ResizingSpace
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_detail_margin_top" />
+ android:layout_height="@dimen/qs_detail_header_margin_top" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8229661..b88962d 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoem om skerm te vul"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Strek om skerm te vul"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock is gedeaktiveer"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"het \'n prent gestuur"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Stoor tans skermkiekie..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7f101d7..1110c99 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ተሰናክሏል"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ምስል ተልኳል"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 8f230246..6d66748 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"تكبير/تصغير لملء الشاشة"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"توسيع بملء الشاشة"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"لقطة شاشة"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"تم إيقاف Smart Lock."</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"أرسَل صورة"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"جارٍ حفظ لقطة الشاشة..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c4438fc..ee9ae88 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock অক্ষম কৰা হৈছে"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 7e50b19..6779834 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ekranı doldurmaq üçün uzat"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skrinşot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock deaktivdir"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"şəkil göndərdi"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinşot yadda saxlanılır..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 701765f..607391a 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj na celom ekranu"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Razvuci na ceo ekran"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock je onemogućen"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Čuvanje snimka ekrana..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 5da6cf8..d4954c1 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Павял. на ўвесь экран"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Расцягн. на ўвесь экран"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функцыя \"Smart Lock\" адключана"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"адпраўлены відарыс"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Захаванне скрыншота..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 742de25..b938880 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Мащаб – запълва екрана"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Разпъване – запълва екрана"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функцията Smart Lock е деактивирана"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"изпратено изображение"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Екранната снимка се запазва..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b35ae1f..811b6a5 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ফুল স্ক্রিন করুন"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট নিন"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"একটি ছবি পাঠানো হয়েছে"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index b877397..d326a51 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Uvećaj prikaz na ekran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Razvuci prikaz na ekran"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock je onemogućen"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spašavanje snimka ekrana..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a5504f0..4315057 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom per omplir pantalla"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estira per omplir pant."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock desactivat"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviat una imatge"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"S\'està desant captura de pantalla..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f48c9fb..1cac5f7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Přiblížit na celou obrazovku"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Na celou obrazovku"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funkce Smart Lock je deaktivována"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odesílá obrázek"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index cbef464..48f8086 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom til fuld skærm"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stræk til fuld skærm"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock er deaktiveret"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendte et billede"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gemmer screenshot..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 50fcdfb..4c4a876 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom auf Bildschirmgröße"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Auf Bildschirmgröße anpassen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock deaktiviert"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"Bild gesendet"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot wird gespeichert..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b8d357f..0b37ed8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Ζουμ σε πλήρη οθόνη"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Προβoλή σε πλήρη οθ."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Το Smart Lock έχει απενεργοποιηθεί"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"έστειλε μια εικόνα"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index d69a95b..e50c00e 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 3666069..fba313e 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index d69a95b..e50c00e 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index d69a95b..e50c00e 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 030c588..a42a531 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bb43d81..9929020 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ocupar la pantalla"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estirar p/ ocupar la pantalla"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Se inhabilitó Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"envió una imagen"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura de pantalla"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index fd0f865..6a42460 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ajustar"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Expandir para ajustar"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock inhabilitado"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviado una imagen"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6cd609f..10becfb 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Suumi ekraani täitmiseks"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Venita ekraani täitmiseks"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock on keelatud"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"saatis kujutise"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Kuvatõmmise salvestamine ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b6162a8..3dbbc07 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Handiagotu pantaila betetzeko"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Luzatu pantaila betetzeko"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Desgaitu da Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"erabiltzaileak irudi bat bidali du"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Pantaila-argazkia gordetzen…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d1ddd8c..4606ae7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"بزرگنمایی برای پر کردن صفحه"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"گسترده کردن برای پر کردن صفحه"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"نماگرفت"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock غیرفعال شد"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"تصویری ارسال کرد"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"در حال ذخیره نماگرفت..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره نماگرفت…"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 652acf7..9d9b152 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomaa koko näyttöön"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Venytä koko näyttöön"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock poistettu käytöstä"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"lähetti kuvan"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Tallennetaan kuvakaappausta..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1ec1f91..22e77a0 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 6a08d87..5510ef1 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock désactivé"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 15678e4..a9f0593 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Ampliar ata ocupar todo"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estirar ata ocupar todo"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Facer captura"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock está desactivado"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou unha imaxe"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gardando captura de pantalla…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 9255827..9f05de5 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"સ્ક્રીનશૉટ"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"છબી મોકલી"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1ebb517..ffe3a5b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरने के लिए ज़ूम करें"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरने के लिए खींचें"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock की सुविधा बंद कर दी गई है"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"एक इमेज भेजी गई"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9ec657d..260dba9 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj i ispuni zaslon"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rastegni i ispuni zaslon"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock onemogućen"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"šalje sliku"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spremanje snimke zaslona..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d9d8148..4a71826 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Nagyítás a kitöltéshez"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Nyújtás kitöltéshez"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock kikapcsolva"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"képet küldött"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Képernyőkép mentése..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1d8094a..bdebdad 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Խոշորացնել` էկրանը լցնելու համար"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ձգել` էկրանը լցնելու համար"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock-ն անջատված է"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"պատկեր է ուղարկվել"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Սքրինշոթը պահվում է…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 76ee722..15b64c6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Perbesar utk mengisi layar"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rentangkn utk mngisi layar"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dinonaktifkan"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"mengirim gambar"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan screenshot..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 0190554..e0ff373 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Fylla skjá með aðdrætti"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Teygja yfir allan skjáinn"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Slökkt á Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendi mynd"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Vistar skjámynd…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0efab5c..3d26cbb 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom per riempire schermo"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estendi per riemp. schermo"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funzionalità Smart Lock disattivata"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"è stata inviata un\'immagine"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvataggio screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot…"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 1e4c9d6..ed1ea36 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"הגדלת התצוגה למילוי המסך"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"מתיחה למילוי של המסך"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"נשלחה תמונה"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"צילום המסך נשמר..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"המערכת שומרת את צילום המסך..."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2725979..502f962 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"画面サイズに合わせて拡大"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"画面サイズに合わせて拡大"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock は無効です"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"画像を送信しました"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"スクリーンショットを保存中..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 21e1c52..38c59bf 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"გაწიეთ ეკრანის შესავსებად."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock გათიშულია"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"გაიგზავნა სურათი"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"სკრინშოტის შენახვა…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 6a9a9b5..afb46e8 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Экранды толтыру үшін ұлғайту"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтыру үшін созу"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock өшірілді"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сурет жіберілді"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншотты сақтауда…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 080ba19..9f4ddf3 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ពង្រីកដើម្បីឲ្យពេញអេក្រង់"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ទាញដើម្បីឲ្យពេញអេក្រង់"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"បានបិទ Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"បានផ្ញើរូបភាព"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"កំពុងរក្សាទុករូបថតអេក្រង់…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុងរក្សាទុករូបថតអេក្រង់..."</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index f63d02f..36d3d7d 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ಚಿತ್ರವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 371b7de..a846bc1 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"전체화면 모드로 확대"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"전체화면 모드로 확대"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 사용 중지됨"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"이미지 보냄"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"캡쳐화면 저장 중..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 404b9ac..124dc53 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Экрнд тлтр ү. чен өлч өзг"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтуруу ү-н чоюу"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock өчүрүлдү"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сүрөт жөнөттү"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншот сакталууда…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index ee0e4b3..fc5edf3 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -41,7 +41,7 @@
<dimen name="battery_detail_graph_space_top">9dp</dimen>
<dimen name="battery_detail_graph_space_bottom">9dp</dimen>
- <dimen name="qs_detail_margin_top">14dp</dimen>
+ <dimen name="qs_detail_header_margin_top">14dp</dimen>
<dimen name="volume_tool_tip_top_margin">12dp</dimen>
<dimen name="volume_row_slider_height">128dp</dimen>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 33fddef..c27394c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"ປິດການນຳໃຊ້ Smart Lock ແລ້ວ"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ສົ່ງຮູບແລ້ວ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 94faaf4..a1cd602 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Keisti mast., kad atit. ekr."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ištempti, kad atit. ekr."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"„Smart Lock“ išjungta"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"išsiuntė vaizdą"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Išsaugoma ekrano kopija..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0d14405..b0da7f7 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Tālumm., lai aizp. ekr."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stiepiet, lai aizp. ekr."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Sistēma Smart Lock ir atspējota"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nosūtīts attēls"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saglabā ekrānuzņēmumu…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 5fda8b2..bee9bff 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Зумирај да се исполни екранот"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Растегни да се исполни екранот"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Слика од екранот"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Оневозможено е Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"испрати слика"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сликата на екранот се зачувува..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 6956934..061f43c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ചിത്രം അയച്ചു"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0d1ad4b..8bf0dbc 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Дэлгэц дүүргэх бол татна уу"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Ухаалаг түгжээг идэвхгүй болгосон"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"зураг илгээсэн"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Дэлгэцийн агшинг хадгалж байна…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1fa1a3e..7d23729 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरण्यासाठी झूम करा"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरण्यासाठी ताणा"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"इमेज पाठवली आहे"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b7d0246..b662271 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zum untuk memenuhi skrin"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Regang utk memenuhi skrin"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dilumpuhkan"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"menghantar imej"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan tangkapan skrin..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 81d168b..900b98a 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ပိတ်ထားသည်"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ပုံပို့ထားသည်"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 360c58b..938234d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom for å fylle skjermen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Strekk for å fylle skjerm"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock er slått av"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har sendt et bilde"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Lagrer skjermdumpen …"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index e5787b5..440e8af 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्क्रिन भर्न तन्काउनुहोस्"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"कुनै छवि पठाइयो"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रिनसट बचत गर्दै…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7d75b6e..66ec98a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom om scherm te vullen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rek uit v. schermvulling"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock staat uit"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"heeft een afbeelding gestuurd"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot opslaan..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index ee524bf..f76adfa 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ସ୍କ୍ରୀନ ଭରିବା ପାଇଁ ଜୁମ୍ କରନ୍ତୁ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ସ୍କ୍ରୀନ୍କୁ ଭରିବା ପାଇଁ ଟାଣନ୍ତୁ"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ସ୍କ୍ରିନ୍ସଟ୍ ନିଅନ୍ତୁ"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ଏକ ଛବି ପଠାଯାଇଛି"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ କରାଯାଉଛି…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ କରାଯାଉଛି…"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index d68ab4f..9d1edfa 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ਚਿੱਤਰ ਭੇਜਿਆ ਗਿਆ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 9aade18..b6412e7 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Powiększ, aby wypełnić ekran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rozciągnij, aby wypełnić ekran"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Wyłączono Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"wysłano obraz"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Zapisywanie zrzutu ekranu..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index cab482a..7c3f864 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"O Smart Lock foi desativado"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index eec3468..df48773 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para preencher o ecrã"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Esticar p. caber em ec. int."</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock desativado"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"A guardar captura de ecrã..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index cab482a..7c3f864 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"O Smart Lock foi desativado"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 1e30ea7..c36f7e7 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom pt. a umple ecranul"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Înt. pt. a umple ecranul"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dezactivat"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a trimis o imagine"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Se salv. captura de ecran..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 99465d5..cc63a91 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Подогнать по размерам экрана"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Растянуть на весь экран"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функция Smart Lock отключена."</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"отправлено изображение"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сохранение..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 6ea2a0d..c08d6f7 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"තිරය පිරවීමට විශාලනය කරන්න"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"තිරය පිරවීමට අදින්න"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock අබලයි"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"රූපයක් එවන ලදී"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"තිර රුව සුරකිමින්…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 399b979..0aabf7c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Priblížiť na celú obrazovku"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Na celú obrazovku"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funkcia Smart Lock je deaktivovaná"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odoslal(a) obrázok"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Prebieha ukladanie snímky obrazovky..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 0c93bce..ecf5ca7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Povečava čez cel zaslon"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Raztegnitev čez zaslon"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Storitev Smart Lock je onemogočena."</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslal(-a) sliko"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Shranjev. posnetka zaslona ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 7f101db..86bd5a1 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zmadho për të mbushur ekranin"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Shtrije për të mbushur ekranin"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"dërgoi një imazh"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Po ruan pamjen e ekranit..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 1da42cf..83317d2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Зумирај на целом екрану"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Развуци на цео екран"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock је онемогућен"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"је послао/ла слику"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Чување снимка екрана..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 05aeffb..86b0fc7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Zooma för att fylla skärm"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Dra för att fylla skärmen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skärmbild"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock har inaktiverats"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har skickat en bild"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skärmbilden sparas ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmbilden sparas ..."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7f51e826..58401b5 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Kuza ili kujaza skrini"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Tanua ili kujaza skrini"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Kipengele cha Smart Lock kimezimwa"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"imetuma picha"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Inahifadhi picha ya skrini..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 527537b..c2aad2d 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -100,4 +100,7 @@
same as phones in portrait -->
<dimen name="qs_security_footer_single_line_height">48dp</dimen>
<dimen name="qs_security_footer_background_inset">0dp</dimen>
+
+ <!-- When split shade is used, this panel should be aligned to the top -->
+ <dimen name="qs_detail_margin_top">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a16355e..efb704f 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"திரையை நிரப்ப அளவை மாற்று"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"திரையை நிரப்ப இழு"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock முடக்கப்பட்டது"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"படம் அனுப்பப்பட்டது"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index eeeaf0d..6546059 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -77,6 +77,8 @@
<string name="compat_mode_on" msgid="4963711187149440884">"స్క్రీన్కు నింపేలా జూమ్ చేయండి"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"స్క్రీన్కు నింపేలా విస్తరించండి"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్షాట్"</string>
+ <!-- no translation found for global_action_smart_lock_disabled (9097102067802412936) -->
+ <skip />
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ఇమేజ్ను పంపారు"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"స్క్రీన్షాట్ను సేవ్ చేస్తోంది…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్షాట్ను సేవ్ చేస్తోంది…"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 1fd1313..df358a3 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"ขยายจนเต็มหน้าจอ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ยืดจนเต็มหน้าจอ"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"ปิดใช้ Smart Lock แล้ว"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ส่งรูปภาพ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"กำลังบันทึกภาพหน้าจอ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3837364..a74345d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"I-zoom upang punan screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"I-stretch upang mapuno screen"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Naka-disable ang Smart Lock"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nagpadala ng larawan"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Sine-save ang screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 1cd547c..51e32458 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Yakınlaştır (ekranı kaplasın)"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Genişlet (ekran kapansın)"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock devre dışı"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"bir resim gönderildi"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ekran görüntüsü kaydediliyor..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 70922aa..b1febf5 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Масштабув. на весь екран"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Розтягнути на весь екран"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock вимкнено"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"надіслане зображення"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Збереження знімка екрана..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 7ef0149..fcb53a4 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"پوری سکرین پر زوم کریں"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"پوری سکرین پر پھیلائیں"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock کو غیر فعال کیا گیا"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ایک تصویر بھیجی"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 08ac980..7822b84 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Ekranga moslashtirish"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ekran hajmida cho‘zish"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock faolsizlantirildi"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"rasm yuborildi"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinshot saqlanmoqda…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 60b1232..5a1ea4c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"T.phóng để lấp đầy m.hình"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Giãn ra để lấp đầy m.hình"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Tính năng Smart Lock đã tắt"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"đã gửi hình ảnh"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Đang lưu ảnh chụp màn hình..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 357e59e..b1968ee 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"缩放以填满屏幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"拉伸以填满屏幕"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"发送了一张图片"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在保存屏幕截图..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
@@ -1058,7 +1059,7 @@
<string name="accessibility_control_change_favorite" msgid="2943178027582253261">"收藏"</string>
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"取消收藏"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"移至位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
- <string name="controls_favorite_default_title" msgid="967742178688938137">"控件"</string>
+ <string name="controls_favorite_default_title" msgid="967742178688938137">"控制"</string>
<string name="controls_favorite_subtitle" msgid="6481675111056961083">"选择要从“快捷设置”菜单访问的控制项"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住并拖动即可重新排列控制器"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"已移除所有控制器"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f8ede3a..7c048ea 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"已傳送圖片"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕擷取畫面..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index df84fb0..8647aed 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"傳送了一張圖片"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index fe97daa..b0c8121 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -77,6 +77,7 @@
<string name="compat_mode_on" msgid="4963711187149440884">"Sondeza ukugcwalisa isikrini"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Nweba ukugcwalisa isikrini"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
+ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Ukhiye oSmathi ukhutshaziwe"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"uthumele isithombe"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ilondoloz umfanekiso weskrini..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e412548..689f8f7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -608,7 +608,7 @@
<dimen name="qs_detail_item_primary_text_size">16sp</dimen>
<dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
<dimen name="qs_detail_empty_text_size">14sp</dimen>
- <dimen name="qs_detail_margin_top">28dp</dimen>
+ <dimen name="qs_detail_header_margin_top">28dp</dimen>
<dimen name="qs_detail_back_margin_end">16dp</dimen>
<dimen name="qs_detail_header_text_padding">16dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
@@ -659,6 +659,8 @@
<!-- Padding between subtitles and the following text in the QSFooter dialog -->
<dimen name="qs_footer_dialog_subtitle_padding">20dp</dimen>
+ <dimen name="qs_detail_margin_top">@*android:dimen/quick_qs_offset_height</dimen>
+
<dimen name="seek_bar_height">3dp</dimen>
<dimen name="seek_bar_corner_radius">3dp</dimen>
@@ -916,6 +918,7 @@
<dimen name="keyguard_affordance_fixed_height">48dp</dimen>
<dimen name="keyguard_affordance_fixed_width">48dp</dimen>
+ <dimen name="keyguard_affordance_fixed_radius">24dp</dimen>
<dimen name="keyguard_affordance_horizontal_offset">32dp</dimen>
<dimen name="keyguard_affordance_vertical_offset">32dp</dimen>
@@ -1133,6 +1136,7 @@
<dimen name="global_actions_button_padding">38dp</dimen>
<dimen name="global_actions_corner_radius">28dp</dimen>
<dimen name="global_actions_lite_padding">24dp</dimen>
+ <dimen name="global_actions_info_margin">32dp</dimen>
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 47f4740..a93eaab 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -211,6 +211,8 @@
<!-- Power menu item for taking a screenshot [CHAR LIMIT=20]-->
<string name="global_action_screenshot">Screenshot</string>
+ <!-- Message shown in power menu when smart lock has been disabled [CHAR_LIMIT=NONE] -->
+ <string name="global_action_smart_lock_disabled">Smart Lock disabled</string>
<!-- text to show in place of RemoteInput images when they cannot be shown.
[CHAR LIMIT=50] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
index 4bb4eb9..915e7f6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
@@ -20,7 +20,7 @@
import android.view.Surface
import android.view.View
import android.view.WindowManager
-import com.android.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import java.lang.ref.WeakReference
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 4663a9a..b827356 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -116,6 +116,8 @@
public static final int SYSUI_STATE_IME_SWITCHER_SHOWING = 1 << 20;
// Device dozing/AOD state
public static final int SYSUI_STATE_DEVICE_DOZING = 1 << 21;
+ // The home feature is disabled (either by SUW/SysUI/device policy)
+ public static final int SYSUI_STATE_BACK_DISABLED = 1 << 22;
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -139,7 +141,8 @@
SYSUI_STATE_IME_SHOWING,
SYSUI_STATE_MAGNIFICATION_OVERLAP,
SYSUI_STATE_IME_SWITCHER_SHOWING,
- SYSUI_STATE_DEVICE_DOZING
+ SYSUI_STATE_DEVICE_DOZING,
+ SYSUI_STATE_BACK_DISABLED
})
public @interface SystemUiStateFlags {}
@@ -170,6 +173,7 @@
str.add((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0 ? "magnification_overlap" : "");
str.add((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0 ? "ime_switcher_showing" : "");
str.add((flags & SYSUI_STATE_DEVICE_DOZING) != 0 ? "device_dozing" : "");
+ str.add((flags & SYSUI_STATE_BACK_DISABLED) != 0 ? "back_disabled" : "");
return str.toString();
}
diff --git a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
similarity index 75%
rename from packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionFactory.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index 7594f50..9b5eae8 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -15,21 +15,21 @@
*/
@file:JvmName("UnfoldTransitionFactory")
-package com.android.unfold
+package com.android.systemui.unfold
import android.content.Context
import android.hardware.SensorManager
import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
-import com.android.unfold.updates.screen.ScreenStatusProvider
-import com.android.unfold.config.ANIMATION_MODE_HINGE_ANGLE
-import com.android.unfold.config.ResourceUnfoldTransitionConfig
-import com.android.unfold.config.UnfoldTransitionConfig
-import com.android.unfold.progress.FixedTimingTransitionProgressProvider
-import com.android.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
-import com.android.unfold.updates.DeviceFoldStateProvider
-import com.android.unfold.updates.hinge.EmptyHingeAngleProvider
-import com.android.unfold.updates.hinge.RotationSensorHingeAngleProvider
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.config.ANIMATION_MODE_HINGE_ANGLE
+import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
+import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
+import com.android.systemui.unfold.updates.DeviceFoldStateProvider
+import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
+import com.android.systemui.unfold.updates.hinge.RotationSensorHingeAngleProvider
import java.lang.IllegalStateException
import java.util.concurrent.Executor
diff --git a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
similarity index 91%
rename from packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
index 4a6a9ac..e17f43e 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold
+package com.android.systemui.unfold
import android.annotation.FloatRange
-import com.android.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.statusbar.policy.CallbackController
/**
diff --git a/packages/SystemUI/shared/src/com/android/unfold/config/ResourceUnfoldTransitionConfig.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
similarity index 96%
rename from packages/SystemUI/shared/src/com/android/unfold/config/ResourceUnfoldTransitionConfig.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
index bde87a5..fa6b5de 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/config/ResourceUnfoldTransitionConfig.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.config
+package com.android.systemui.unfold.config
import android.content.Context
import android.os.SystemProperties
diff --git a/packages/SystemUI/shared/src/com/android/unfold/config/UnfoldTransitionConfig.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
similarity index 95%
rename from packages/SystemUI/shared/src/com/android/unfold/config/UnfoldTransitionConfig.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
index f000c69..75d9dc3 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/config/UnfoldTransitionConfig.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.config
+package com.android.systemui.unfold.config
import android.annotation.IntDef
diff --git a/packages/SystemUI/shared/src/com/android/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
similarity index 86%
rename from packages/SystemUI/shared/src/com/android/unfold/progress/FixedTimingTransitionProgressProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index acfe073..732882e 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.progress
+package com.android.systemui.unfold.progress
import android.animation.Animator
import android.animation.ObjectAnimator
import android.util.FloatProperty
-import com.android.unfold.UnfoldTransitionProgressProvider
-import com.android.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
-import com.android.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
-import com.android.unfold.updates.FoldStateProvider
-import com.android.unfold.updates.FoldStateProvider.FoldUpdate
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
+import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
+import com.android.systemui.unfold.updates.FoldStateProvider
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
/**
* Emits animation progress with fixed timing after unfolding
diff --git a/packages/SystemUI/shared/src/com/android/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
similarity index 89%
rename from packages/SystemUI/shared/src/com/android/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index d9d037f..b111892 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -13,21 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.progress
+package com.android.systemui.unfold.progress
import android.os.Handler
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
-import com.android.unfold.UnfoldTransitionProgressProvider
-import com.android.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
-import com.android.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
-import com.android.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
-import com.android.unfold.updates.FoldStateProvider
-import com.android.unfold.updates.FoldStateProvider.FoldUpdate
-import com.android.unfold.updates.FoldStateProvider.FoldUpdatesListener
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
+import com.android.systemui.unfold.updates.FoldStateProvider
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
/**
* Maps fold updates to unfold transition progress using DynamicAnimation.
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
similarity index 90%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/DeviceFoldStateProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 3a21b80..949652b 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.updates
+package com.android.systemui.unfold.updates
import android.content.Context
import android.hardware.devicestate.DeviceStateManager
import androidx.core.util.Consumer
-import com.android.unfold.updates.screen.ScreenStatusProvider
-import com.android.unfold.updates.FoldStateProvider.FoldUpdate
-import com.android.unfold.updates.FoldStateProvider.FoldUpdatesListener
-import com.android.unfold.updates.hinge.FULLY_OPEN_DEGREES
-import com.android.unfold.updates.hinge.HingeAngleProvider
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
+import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import java.util.concurrent.Executor
internal class DeviceFoldStateProvider(
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
similarity index 93%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/FoldStateProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index 2c3a6ec..4c6d241 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.updates
+package com.android.systemui.unfold.updates
import android.annotation.FloatRange
import android.annotation.IntDef
-import com.android.unfold.updates.FoldStateProvider.FoldUpdatesListener
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
import com.android.systemui.statusbar.policy.CallbackController
/**
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/EmptyHingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
similarity index 85%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/hinge/EmptyHingeAngleProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
index 905b086..9b58b1f 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/EmptyHingeAngleProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
@@ -1,4 +1,4 @@
-package com.android.unfold.updates.hinge
+package com.android.systemui.unfold.updates.hinge
import androidx.core.util.Consumer
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/HingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
similarity index 84%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/hinge/HingeAngleProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
index 4196f60..8549913 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/HingeAngleProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
@@ -1,4 +1,4 @@
-package com.android.unfold.updates.hinge
+package com.android.systemui.unfold.updates.hinge
import androidx.core.util.Consumer
import com.android.systemui.statusbar.policy.CallbackController
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
index 011582e..8b6eecf 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
@@ -1,4 +1,4 @@
-package com.android.unfold.updates.hinge
+package com.android.systemui.unfold.updates.hinge
import android.hardware.Sensor
import android.hardware.SensorEvent
diff --git a/packages/SystemUI/shared/src/com/android/unfold/updates/screen/ScreenStatusProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
similarity index 87%
rename from packages/SystemUI/shared/src/com/android/unfold/updates/screen/ScreenStatusProvider.kt
rename to packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
index a65e888..1eec803 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/updates/screen/ScreenStatusProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unfold.updates.screen
+package com.android.systemui.unfold.updates.screen
-import com.android.unfold.updates.screen.ScreenStatusProvider.ScreenListener
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
import com.android.systemui.statusbar.policy.CallbackController
interface ScreenStatusProvider : CallbackController<ScreenListener> {
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 06fbe84..cc166c2 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -92,9 +92,11 @@
@Override
public void startActivity(Intent intent, boolean dismissShade,
- @Nullable ActivityLaunchAnimator.Controller animationController) {
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ boolean showOverLockscreenWhenLocked) {
mActualStarterOptionalLazy.get().ifPresent(
- starter -> starter.startActivity(intent, dismissShade, animationController));
+ starter -> starter.startActivity(intent, dismissShade, animationController,
+ showOverLockscreenWhenLocked));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
index c9e6771..5616a00 100644
--- a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
@@ -40,10 +40,10 @@
* After restoring is done, a [ACTION_RESTORE_FINISHED] intent will be send to SystemUI user 0,
* indicating that restoring is finished for a given user.
*/
-class BackupHelper : BackupAgentHelper() {
+open class BackupHelper : BackupAgentHelper() {
companion object {
- private const val TAG = "BackupHelper"
+ const val TAG = "BackupHelper"
internal const val CONTROLS = ControlsFavoritePersistenceWrapper.FILE_NAME
private const val NO_OVERWRITE_FILES_BACKUP_KEY = "systemui.files_no_overwrite"
private const val PEOPLE_TILES_BACKUP_KEY = "systemui.people.shared_preferences"
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index b9440c5..66085ac0 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -41,24 +41,22 @@
import android.widget.TextView;
import androidx.annotation.StyleRes;
+import androidx.annotation.VisibleForTesting;
import com.android.settingslib.graph.ThemedBatteryDrawable;
-import com.android.systemui.Dependency;
import com.android.systemui.DualToneHandler;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.text.NumberFormat;
-public class BatteryMeterView extends LinearLayout implements
- BatteryStateChangeCallback, DarkReceiver {
+public class BatteryMeterView extends LinearLayout implements DarkReceiver {
@Retention(SOURCE)
@IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF, MODE_ESTIMATE})
@@ -72,7 +70,6 @@
private final ImageView mBatteryIconView;
private TextView mBatteryPercentView;
- private BatteryController mBatteryController;
private final @StyleRes int mPercentageStyleId;
private int mTextColor;
private int mLevel;
@@ -90,6 +87,8 @@
private int mNonAdaptedForegroundColor;
private int mNonAdaptedBackgroundColor;
+ private BatteryEstimateFetcher mBatteryEstimateFetcher;
+
public BatteryMeterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -178,22 +177,7 @@
return false;
}
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- mBatteryController = Dependency.get(BatteryController.class);
- mBatteryController.addCallback(this);
- updateShowPercent();
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mBatteryController.removeCallback(this);
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ void onBatteryLevelChanged(int level, boolean pluggedIn) {
mDrawable.setCharging(pluggedIn);
mDrawable.setBatteryLevel(level);
mCharging = pluggedIn;
@@ -201,8 +185,7 @@
updatePercentText();
}
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
+ void onPowerSaveChanged(boolean isPowerSave) {
mDrawable.setPowerSaveEnabled(isPowerSave);
}
@@ -222,19 +205,28 @@
updateShowPercent();
}
+ /**
+ * Sets the fetcher that should be used to get the estimated time remaining for the user's
+ * battery.
+ */
+ void setBatteryEstimateFetcher(BatteryEstimateFetcher fetcher) {
+ mBatteryEstimateFetcher = fetcher;
+ }
+
void updatePercentText() {
if (mBatteryStateUnknown) {
setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
return;
}
- if (mBatteryController == null) {
+ if (mBatteryEstimateFetcher == null) {
return;
}
if (mBatteryPercentView != null) {
if (mShowPercentMode == MODE_ESTIMATE && !mCharging) {
- mBatteryController.getEstimatedTimeRemainingString((String estimate) -> {
+ mBatteryEstimateFetcher.fetchBatteryTimeRemainingEstimate(
+ (String estimate) -> {
if (mBatteryPercentView == null) {
return;
}
@@ -310,8 +302,7 @@
return mUnknownStateDrawable;
}
- @Override
- public void onBatteryUnknownStateChanged(boolean isUnknown) {
+ void onBatteryUnknownStateChanged(boolean isUnknown) {
if (mBatteryStateUnknown == isUnknown) {
return;
}
@@ -390,5 +381,16 @@
pw.println(" mLevel: " + mLevel);
pw.println(" mMode: " + mShowPercentMode);
}
+
+ @VisibleForTesting
+ CharSequence getBatteryPercentViewText() {
+ return mBatteryPercentView.getText();
+ }
+
+ /** An interface that will fetch the estimated time remaining for the user's battery. */
+ public interface BatteryEstimateFetcher {
+ void fetchBatteryTimeRemainingEstimate(
+ BatteryController.EstimateFetchCompletion completion);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index b7e2982..ae9a323 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -31,6 +31,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
@@ -42,6 +43,7 @@
private final ConfigurationController mConfigurationController;
private final TunerService mTunerService;
private final ContentResolver mContentResolver;
+ private final BatteryController mBatteryController;
private final String mSlotBattery;
private final SettingObserver mSettingObserver;
@@ -66,6 +68,24 @@
}
};
+ private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
+ new BatteryController.BatteryStateChangeCallback() {
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ mView.onBatteryLevelChanged(level, pluggedIn);
+ }
+
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mView.onPowerSaveChanged(isPowerSave);
+ }
+
+ @Override
+ public void onBatteryUnknownStateChanged(boolean isUnknown) {
+ mView.onBatteryUnknownStateChanged(isUnknown);
+ }
+ };
+
// Some places may need to show the battery conditionally, and not obey the tuner
private boolean mIgnoreTunerUpdates;
private boolean mIsSubscribedForTunerUpdates;
@@ -77,11 +97,15 @@
TunerService tunerService,
BroadcastDispatcher broadcastDispatcher,
@Main Handler mainHandler,
- ContentResolver contentResolver) {
+ ContentResolver contentResolver,
+ BatteryController batteryController) {
super(view);
mConfigurationController = configurationController;
mTunerService = tunerService;
mContentResolver = contentResolver;
+ mBatteryController = batteryController;
+
+ mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
mSettingObserver = new SettingObserver(mainHandler);
@@ -99,16 +123,21 @@
protected void onViewAttached() {
mConfigurationController.addCallback(mConfigurationListener);
subscribeForTunerUpdates();
+ mBatteryController.addCallback(mBatteryStateChangeCallback);
registerShowBatteryPercentObserver(ActivityManager.getCurrentUser());
registerGlobalBatteryUpdateObserver();
mCurrentUserTracker.startTracking();
+
+ mView.updateShowPercent();
}
@Override
protected void onViewDetached() {
mConfigurationController.removeCallback(mConfigurationListener);
unsubscribeFromTunerUpdates();
+ mBatteryController.removeCallback(mBatteryStateChangeCallback);
+
mCurrentUserTracker.stopTracking();
mContentResolver.unregisterContentObserver(mSettingObserver);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 69f9004..b5378cd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -43,7 +43,6 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -76,6 +75,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
+import com.android.systemui.util.time.SystemClock;
import java.util.Optional;
@@ -125,6 +125,7 @@
@Nullable private final UdfpsHbmProvider mHbmProvider;
@NonNull private final KeyguardBypassController mKeyguardBypassController;
@NonNull private final ConfigurationController mConfigurationController;
+ @NonNull private final SystemClock mSystemClock;
@VisibleForTesting @NonNull final BiometricOrientationEventListener mOrientationListener;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@@ -449,19 +450,19 @@
final String touchInfo = String.format(
"minor: %.1f, major: %.1f, v: %.1f, exceedsVelocityThreshold: %b",
minor, major, v, exceedsVelocityThreshold);
- final long sinceLastLog = SystemClock.elapsedRealtime() - mTouchLogTime;
+ final long sinceLastLog = mSystemClock.elapsedRealtime() - mTouchLogTime;
if (!isIlluminationRequested && !mGoodCaptureReceived &&
!exceedsVelocityThreshold) {
onFingerDown((int) event.getRawX(), (int) event.getRawY(), minor,
major);
Log.v(TAG, "onTouch | finger down: " + touchInfo);
- mTouchLogTime = SystemClock.elapsedRealtime();
- mPowerManager.userActivity(SystemClock.uptimeMillis(),
+ mTouchLogTime = mSystemClock.elapsedRealtime();
+ mPowerManager.userActivity(mSystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
handled = true;
} else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) {
Log.v(TAG, "onTouch | finger move: " + touchInfo);
- mTouchLogTime = SystemClock.elapsedRealtime();
+ mTouchLogTime = mSystemClock.elapsedRealtime();
}
} else {
Log.v(TAG, "onTouch | finger outside");
@@ -525,7 +526,8 @@
@NonNull KeyguardBypassController keyguardBypassController,
@NonNull DisplayManager displayManager,
@Main Handler mainHandler,
- @NonNull ConfigurationController configurationController) {
+ @NonNull ConfigurationController configurationController,
+ @NonNull SystemClock systemClock) {
mContext = context;
mExecution = execution;
// TODO (b/185124905): inject main handler and vibrator once done prototyping
@@ -561,6 +563,7 @@
mainHandler);
mKeyguardBypassController = keyguardBypassController;
mConfigurationController = configurationController;
+ mSystemClock = systemClock;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -781,6 +784,7 @@
mKeyguardViewMediator,
mLockscreenShadeTransitionController,
mConfigurationController,
+ mSystemClock,
this
);
case IUdfpsOverlayController.REASON_AUTH_BP:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 79a4a0b..b81b547 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.SystemClock;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -51,6 +52,7 @@
@NonNull private final KeyguardViewMediator mKeyguardViewMediator;
@NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController;
@NonNull private final ConfigurationController mConfigurationController;
+ @NonNull private final SystemClock mSystemClock;
@NonNull private final UdfpsController mUdfpsController;
private boolean mShowingUdfpsBouncer;
@@ -60,6 +62,7 @@
private int mStatusBarState;
private float mTransitionToFullShadeProgress;
private float mLastDozeAmount;
+ private long mLastUdfpsBouncerShowTime = -1;
/**
* hidden amount of pin/pattern/password bouncer
@@ -80,6 +83,7 @@
@NonNull KeyguardViewMediator keyguardViewMediator,
@NonNull LockscreenShadeTransitionController transitionController,
@NonNull ConfigurationController configurationController,
+ @NonNull SystemClock systemClock,
@NonNull UdfpsController udfpsController) {
super(view, statusBarStateController, statusBarOptional, dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
@@ -88,6 +92,7 @@
mKeyguardViewMediator = keyguardViewMediator;
mLockScreenShadeTransitionController = transitionController;
mConfigurationController = configurationController;
+ mSystemClock = systemClock;
mUdfpsController = udfpsController;
}
@@ -156,6 +161,9 @@
}
mShowingUdfpsBouncer = show;
+ if (mShowingUdfpsBouncer) {
+ mLastUdfpsBouncerShowTime = mSystemClock.uptimeMillis();
+ }
updatePauseAuth();
if (mShowingUdfpsBouncer) {
if (mStatusBarState == StatusBarState.SHADE_LOCKED) {
@@ -219,16 +227,25 @@
* If we were previously showing the udfps bouncer, hide it and instead show the regular
* (pin/pattern/password) bouncer.
*
- * Does nothing if we weren't previously showing the udfps bouncer.
+ * Does nothing if we weren't previously showing the UDFPS bouncer.
*/
private void maybeShowInputBouncer() {
- if (mShowingUdfpsBouncer) {
+ if (mShowingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) {
mKeyguardViewManager.showBouncer(true);
mKeyguardViewManager.resetAlternateAuth(false);
}
}
/**
+ * Whether the udfps bouncer has shown for at least 200ms before allowing touches outside
+ * of the udfps icon area to dismiss the udfps bouncer and show the pin/pattern/password
+ * bouncer.
+ */
+ private boolean hasUdfpsBouncerShownWithMinTime() {
+ return (mSystemClock.uptimeMillis() - mLastUdfpsBouncerShowTime) > 200;
+ }
+
+ /**
* Set the progress we're currently transitioning to the full shade. 0.0f means we're not
* transitioning yet, while 1.0f means we've fully dragged down.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 54a1b55..c093219 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -92,9 +92,9 @@
import com.android.systemui.theme.ThemeOverlayApplier;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.util.settings.SecureSettings;
-import com.android.unfold.UnfoldTransitionFactory;
-import com.android.unfold.UnfoldTransitionProgressProvider;
-import com.android.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.UnfoldTransitionFactory;
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
+import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.pip.Pip;
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
index bfa4780..5b327bd 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
@@ -34,7 +34,7 @@
* See [DumpHandler] for more information on how and when this information is dumped.
*/
@SysUISingleton
-class DumpManager @Inject constructor() {
+open class DumpManager @Inject constructor() {
private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap()
private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap()
diff --git a/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt b/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
index 28f63b0..6561bd5 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
@@ -25,8 +25,12 @@
* Proxy to make {@link SystemProperties} easily testable.
*/
@SysUISingleton
-class SystemPropertiesHelper @Inject constructor() {
+open class SystemPropertiesHelper @Inject constructor() {
fun getBoolean(name: String, default: Boolean): Boolean {
return SystemProperties.getBoolean(name, default)
}
+
+ fun set(name: String, value: Int) {
+ SystemProperties.set(name, value.toString())
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 04a0226..df6aa34 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -62,6 +62,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.view.RotationPolicy;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -173,7 +174,8 @@
SysUiState sysUiState,
@Main Handler handler,
PackageManager packageManager,
- Optional<StatusBar> statusBarOptional) {
+ Optional<StatusBar> statusBarOptional,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
super(context,
windowManagerFuncs,
@@ -204,7 +206,8 @@
sysUiState,
handler,
packageManager,
- statusBarOptional);
+ statusBarOptional,
+ keyguardUpdateMonitor);
mLockPatternUtils = lockPatternUtils;
mKeyguardStateController = keyguardStateController;
@@ -266,7 +269,7 @@
this::getWalletViewController, mSysuiColorExtractor,
mStatusBarService, mNotificationShadeWindowController,
mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger(),
- getStatusBar());
+ getStatusBar(), getKeyguardUpdateMonitor(), mLockPatternUtils);
if (shouldShowLockMessage(dialog)) {
dialog.showLockMessage();
@@ -334,11 +337,13 @@
NotificationShadeWindowController notificationShadeWindowController,
SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing,
MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
- Optional<StatusBar> statusBarOptional) {
+ Optional<StatusBar> statusBarOptional, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ LockPatternUtils lockPatternUtils) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions,
adapter, overflowAdapter, sysuiColorExtractor, statusBarService,
notificationShadeWindowController, sysuiState, onRotateCallback,
- keyguardShowing, powerAdapter, uiEventLogger, statusBarOptional);
+ keyguardShowing, powerAdapter, uiEventLogger, statusBarOptional,
+ keyguardUpdateMonitor, lockPatternUtils);
mWalletFactory = walletFactory;
// Update window attributes
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 6cd5f91..b06b024 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -84,6 +84,7 @@
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
@@ -108,6 +109,7 @@
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.MultiListLayout;
import com.android.systemui.MultiListLayout.MultiListAdapter;
import com.android.systemui.animation.Interpolators;
@@ -171,6 +173,11 @@
static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+ // See NotificationManagerService#scheduleDurationReachedLocked
+ private static final long TOAST_FADE_TIME = 333;
+ // See NotificationManagerService.LONG_DELAY
+ private static final int TOAST_VISIBLE_TIME = 3500;
+
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -231,6 +238,7 @@
protected Handler mMainHandler;
private int mSmallestScreenWidthDp;
private final Optional<StatusBar> mStatusBarOptional;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@VisibleForTesting
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@@ -337,7 +345,8 @@
SysUiState sysUiState,
@Main Handler handler,
PackageManager packageManager,
- Optional<StatusBar> statusBarOptional) {
+ Optional<StatusBar> statusBarOptional,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mWindowManagerFuncs = windowManagerFuncs;
mAudioManager = audioManager;
@@ -367,6 +376,7 @@
mMainHandler = handler;
mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp;
mStatusBarOptional = statusBarOptional;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -420,6 +430,10 @@
return mStatusBarOptional;
}
+ protected KeyguardUpdateMonitor getKeyguardUpdateMonitor() {
+ return mKeyguardUpdateMonitor;
+ }
+
/**
* Show the global actions dialog (creating if necessary)
*
@@ -651,7 +665,7 @@
mAdapter, mOverflowAdapter, mSysuiColorExtractor,
mStatusBarService, mNotificationShadeWindowController,
mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger,
- mStatusBarOptional);
+ mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils);
dialog.setOnDismissListener(this);
dialog.setOnShowListener(this);
@@ -2119,6 +2133,8 @@
private UiEventLogger mUiEventLogger;
private GestureDetector mGestureDetector;
private Optional<StatusBar> mStatusBarOptional;
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private LockPatternUtils mLockPatternUtils;
protected ViewGroup mContainer;
@@ -2172,7 +2188,8 @@
NotificationShadeWindowController notificationShadeWindowController,
SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing,
MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
- Optional<StatusBar> statusBarOptional) {
+ Optional<StatusBar> statusBarOptional,
+ KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) {
super(context, themeRes);
mContext = context;
mAdapter = adapter;
@@ -2186,6 +2203,8 @@
mKeyguardShowing = keyguardShowing;
mUiEventLogger = uiEventLogger;
mStatusBarOptional = statusBarOptional;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mLockPatternUtils = lockPatternUtils;
mGestureDetector = new GestureDetector(mContext, mGestureListener);
@@ -2304,6 +2323,14 @@
mBackgroundDrawable = new ScrimDrawable();
mScrimAlpha = 1.0f;
}
+
+ // If user entered from the lock screen and smart lock was enabled, disable it
+ int user = KeyguardUpdateMonitor.getCurrentUser();
+ boolean userHasTrust = mKeyguardUpdateMonitor.getUserHasTrust(user);
+ if (mKeyguardShowing && userHasTrust) {
+ mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
+ showSmartLockDisabledMessage();
+ }
}
protected void fixNavBarClipping() {
@@ -2315,6 +2342,37 @@
contentParent.setClipToPadding(false);
}
+ private void showSmartLockDisabledMessage() {
+ // Since power menu is the top window, make a Toast-like view that will show up
+ View message = LayoutInflater.from(mContext)
+ .inflate(com.android.systemui.R.layout.global_actions_toast, mContainer, false);
+
+ // Set up animation
+ AccessibilityManager mAccessibilityManager =
+ (AccessibilityManager) getContext().getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+ final int visibleTime = mAccessibilityManager.getRecommendedTimeoutMillis(
+ TOAST_VISIBLE_TIME, AccessibilityManager.FLAG_CONTENT_TEXT);
+ message.setVisibility(View.VISIBLE);
+ message.setAlpha(0f);
+ mContainer.addView(message);
+
+ // Fade in
+ message.animate()
+ .alpha(1f)
+ .setDuration(TOAST_FADE_TIME)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Then fade out
+ message.animate()
+ .alpha(0f)
+ .setDuration(TOAST_FADE_TIME)
+ .setStartDelay(visibleTime);
+ }
+ });
+ }
+
@Override
protected void onStart() {
super.onStart();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index a641ad4..c4508e0 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -97,7 +97,7 @@
int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
background.setAlpha(backgroundAlpha);
mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
- mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
+ (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
} else {
float backgroundAlpha = mContext.getResources().getFloat(
com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
index d8905a0..f25ec55 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
@@ -16,8 +16,8 @@
package com.android.systemui.keyguard
import com.android.systemui.dagger.SysUISingleton
-import com.android.unfold.updates.screen.ScreenStatusProvider
-import com.android.unfold.updates.screen.ScreenStatusProvider.ScreenListener
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
import javax.inject.Inject
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index de42730..2e7ab6e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -191,8 +191,8 @@
mNavMode = mNavigationModeController.addListener(this);
mNavigationModeController.addListener(this);
mTaskbarDelegate = taskbarDelegate;
- mTaskbarDelegate.setOverviewProxyService(overviewProxyService,
- navigationBarA11yHelper, mSysUiFlagsContainer);
+ mTaskbarDelegate.setOverviewProxyService(commandQueue, overviewProxyService,
+ navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer);
mIsTablet = isTablet(mContext);
mUserTracker = userTracker;
}
@@ -252,12 +252,10 @@
/** @return {@code true} if taskbar is enabled, false otherwise */
private boolean initializeTaskbarIfNecessary() {
if (mIsTablet) {
- // Remove navigation bar when taskbar is showing, currently only for 3 button mode
+ // Remove navigation bar when taskbar is showing
removeNavigationBar(mContext.getDisplayId());
- mCommandQueue.addCallback(mTaskbarDelegate);
mTaskbarDelegate.init(mContext.getDisplayId());
} else {
- mCommandQueue.removeCallback(mTaskbarDelegate);
mTaskbarDelegate.destroy();
}
return mIsTablet;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index fe24ecd..e0caf12 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -21,15 +21,22 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+import android.content.Context;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.view.InsetsVisibilities;
+import android.view.View;
import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.Dependency;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.statusbar.CommandQueue;
@@ -38,33 +45,53 @@
import javax.inject.Singleton;
@Singleton
-public class TaskbarDelegate implements CommandQueue.Callbacks {
+public class TaskbarDelegate implements CommandQueue.Callbacks,
+ OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener {
+ private final EdgeBackGestureHandler mEdgeBackGestureHandler;
+
+ private CommandQueue mCommandQueue;
private OverviewProxyService mOverviewProxyService;
private NavigationBarA11yHelper mNavigationBarA11yHelper;
+ private NavigationModeController mNavigationModeController;
private SysUiState mSysUiState;
private int mDisplayId;
private int mNavigationIconHints;
private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener =
this::updateSysuiFlags;
- @Inject
- public TaskbarDelegate() { /* no-op */ }
+ private int mDisabledFlags;
- public void setOverviewProxyService(OverviewProxyService overviewProxyService,
+ @Inject
+ public TaskbarDelegate(Context context) {
+ mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class)
+ .create(context);
+ }
+
+ public void setOverviewProxyService(CommandQueue commandQueue,
+ OverviewProxyService overviewProxyService,
NavigationBarA11yHelper navigationBarA11yHelper,
+ NavigationModeController navigationModeController,
SysUiState sysUiState) {
// TODO: adding this in the ctor results in a dagger dependency cycle :(
+ mCommandQueue = commandQueue;
mOverviewProxyService = overviewProxyService;
mNavigationBarA11yHelper = navigationBarA11yHelper;
+ mNavigationModeController = navigationModeController;
mSysUiState = sysUiState;
}
public void destroy() {
+ mCommandQueue.removeCallback(this);
+ mOverviewProxyService.removeCallback(this);
+ mNavigationModeController.removeListener(this);
mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener);
}
public void init(int displayId) {
mDisplayId = displayId;
+ mCommandQueue.addCallback(this);
+ mOverviewProxyService.addCallback(this);
+ mNavigationModeController.addListener(this);
mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener);
// Set initial state for any listeners
updateSysuiFlags();
@@ -81,6 +108,12 @@
(mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
.setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING,
(mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0)
+ .setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
+ (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
+ .setFlag(SYSUI_STATE_HOME_DISABLED,
+ (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
+ .setFlag(SYSUI_STATE_BACK_DISABLED,
+ (mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
.commitUpdate(mDisplayId);
}
@@ -103,6 +136,8 @@
@Override
public void disable(int displayId, int state1, int state2, boolean animate) {
+ mDisabledFlags = state1;
+ updateSysuiFlags();
mOverviewProxyService.disable(displayId, state1, state2, animate);
}
@@ -112,4 +147,18 @@
InsetsVisibilities requestedVisibilities, String packageName) {
mOverviewProxyService.onSystemBarAttributesChanged(displayId, behavior);
}
+
+ @Override
+ public void onTaskbarStatusUpdated(boolean visible, boolean stashed) {
+ if (visible) {
+ mEdgeBackGestureHandler.onNavBarAttached();
+ } else {
+ mEdgeBackGestureHandler.onNavBarDetached();
+ }
+ }
+
+ @Override
+ public void onNavigationModeChanged(int mode) {
+ mEdgeBackGestureHandler.onNavigationModeChanged(mode);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
deleted file mode 100644
index 38b20ee..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2017 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.qs;
-
-import static com.android.systemui.statusbar.phone.AutoTileManager.HOTSPOT;
-import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
-import static com.android.systemui.statusbar.phone.AutoTileManager.NIGHT;
-import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
-import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings.Secure;
-import android.text.TextUtils;
-import android.util.ArraySet;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
-import com.android.systemui.util.UserAwareController;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-import javax.inject.Inject;
-
-public class AutoAddTracker implements UserAwareController {
-
- private static final String[][] CONVERT_PREFS = {
- {Key.QS_HOTSPOT_ADDED, HOTSPOT},
- {Key.QS_DATA_SAVER_ADDED, SAVER},
- {Key.QS_INVERT_COLORS_ADDED, INVERSION},
- {Key.QS_WORK_ADDED, WORK},
- {Key.QS_NIGHTDISPLAY_ADDED, NIGHT},
- };
-
- private final ArraySet<String> mAutoAdded;
- private final Context mContext;
- private int mUserId;
-
- public AutoAddTracker(Context context, int userId) {
- mContext = context;
- mUserId = userId;
- mAutoAdded = new ArraySet<>(getAdded());
- }
-
- /**
- * Init method must be called after construction to start listening
- */
- public void initialize() {
- // TODO: remove migration code and shared preferences keys after P release
- if (mUserId == UserHandle.USER_SYSTEM) {
- for (String[] convertPref : CONVERT_PREFS) {
- if (Prefs.getBoolean(mContext, convertPref[0], false)) {
- setTileAdded(convertPref[1]);
- Prefs.remove(mContext, convertPref[0]);
- }
- }
- }
- mContext.getContentResolver().registerContentObserver(
- Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver,
- UserHandle.USER_ALL);
- }
-
- @Override
- public void changeUser(UserHandle newUser) {
- if (newUser.getIdentifier() == mUserId) {
- return;
- }
- mUserId = newUser.getIdentifier();
- mAutoAdded.clear();
- mAutoAdded.addAll(getAdded());
- }
-
- @Override
- public int getCurrentUserId() {
- return mUserId;
- }
-
- public boolean isAdded(String tile) {
- return mAutoAdded.contains(tile);
- }
-
- public void setTileAdded(String tile) {
- if (mAutoAdded.add(tile)) {
- saveTiles();
- }
- }
-
- public void setTileRemoved(String tile) {
- if (mAutoAdded.remove(tile)) {
- saveTiles();
- }
- }
-
- public void destroy() {
- mContext.getContentResolver().unregisterContentObserver(mObserver);
- }
-
- private void saveTiles() {
- Secure.putStringForUser(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES,
- TextUtils.join(",", mAutoAdded), mUserId);
- }
-
- private Collection<String> getAdded() {
- String current = Secure.getStringForUser(mContext.getContentResolver(),
- Secure.QS_AUTO_ADDED_TILES, mUserId);
- if (current == null) {
- return Collections.emptyList();
- }
- return Arrays.asList(current.split(","));
- }
-
- @VisibleForTesting
- protected final ContentObserver mObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- mAutoAdded.clear();
- mAutoAdded.addAll(getAdded());
- }
- };
-
- public static class Builder {
- private final Context mContext;
- private int mUserId;
-
- @Inject
- public Builder(Context context) {
- mContext = context;
- }
-
- public Builder setUserId(int userId) {
- mUserId = userId;
- return this;
- }
-
- public AutoAddTracker build() {
- return new AutoAddTracker(mContext, mUserId);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
new file mode 100644
index 0000000..7ffa9d9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2021 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.qs
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.UserHandle
+import android.provider.Settings
+import android.text.TextUtils
+import android.util.ArraySet
+import android.util.Log
+import androidx.annotation.GuardedBy
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.Dumpable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.UserAwareController
+import com.android.systemui.util.settings.SecureSettings
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+private const val TAG = "AutoAddTracker"
+
+/**
+ * Class to track tiles that have been auto-added
+ *
+ * The list is backed by [Settings.Secure.QS_AUTO_ADDED_TILES].
+ *
+ * It also handles restore gracefully.
+ */
+class AutoAddTracker @VisibleForTesting constructor(
+ private val secureSettings: SecureSettings,
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val qsHost: QSHost,
+ private val dumpManager: DumpManager,
+ private val mainHandler: Handler?,
+ private val backgroundExecutor: Executor,
+ private var userId: Int
+) : UserAwareController, Dumpable {
+
+ companion object {
+ private val FILTER = IntentFilter(Intent.ACTION_SETTING_RESTORED)
+ }
+
+ @GuardedBy("autoAdded")
+ private val autoAdded = ArraySet<String>()
+ private var restoredTiles: Set<String>? = null
+
+ override val currentUserId: Int
+ get() = userId
+
+ private val contentObserver = object : ContentObserver(mainHandler) {
+ override fun onChange(
+ selfChange: Boolean,
+ uris: Collection<Uri>,
+ flags: Int,
+ _userId: Int
+ ) {
+ if (_userId != userId) {
+ // Ignore changes outside of our user. We'll load the correct value on user change
+ return
+ }
+ loadTiles()
+ }
+ }
+
+ private val restoreReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action != Intent.ACTION_SETTING_RESTORED) return
+ processRestoreIntent(intent)
+ }
+ }
+
+ private fun processRestoreIntent(intent: Intent) {
+ when (intent.getStringExtra(Intent.EXTRA_SETTING_NAME)) {
+ Settings.Secure.QS_TILES -> {
+ restoredTiles = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)
+ ?.split(",")
+ ?.toSet()
+ ?: run {
+ Log.w(TAG, "Null restored tiles for user $userId")
+ emptySet()
+ }
+ }
+ Settings.Secure.QS_AUTO_ADDED_TILES -> {
+ restoredTiles?.let { tiles ->
+ val restoredAutoAdded = intent
+ .getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)
+ ?.split(",")
+ ?: emptyList()
+ val autoAddedBeforeRestore = intent
+ .getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE)
+ ?.split(",")
+ ?: emptyList()
+
+ val tilesToRemove = restoredAutoAdded.filter { it !in tiles }
+ if (tilesToRemove.isNotEmpty()) {
+ qsHost.removeTiles(tilesToRemove)
+ }
+ val tiles = synchronized(autoAdded) {
+ autoAdded.clear()
+ autoAdded.addAll(restoredAutoAdded + autoAddedBeforeRestore)
+ getTilesFromListLocked()
+ }
+ saveTiles(tiles)
+ } ?: run {
+ Log.w(TAG, "${Settings.Secure.QS_AUTO_ADDED_TILES} restored before " +
+ "${Settings.Secure.QS_TILES} for user $userId")
+ }
+ }
+ else -> {} // Do nothing for other Settings
+ }
+ }
+
+ /**
+ * Init method must be called after construction to start listening
+ */
+ fun initialize() {
+ dumpManager.registerDumpable(TAG, this)
+ loadTiles()
+ secureSettings.registerContentObserverForUser(
+ secureSettings.getUriFor(Settings.Secure.QS_AUTO_ADDED_TILES),
+ contentObserver,
+ UserHandle.USER_ALL
+ )
+ registerBroadcastReceiver()
+ }
+
+ /**
+ * Unregister listeners, receivers and observers
+ */
+ fun destroy() {
+ dumpManager.unregisterDumpable(TAG)
+ secureSettings.unregisterContentObserver(contentObserver)
+ unregisterBroadcastReceiver()
+ }
+
+ private fun registerBroadcastReceiver() {
+ broadcastDispatcher.registerReceiver(
+ restoreReceiver,
+ FILTER,
+ backgroundExecutor,
+ UserHandle.of(userId)
+ )
+ }
+
+ private fun unregisterBroadcastReceiver() {
+ broadcastDispatcher.unregisterReceiver(restoreReceiver)
+ }
+
+ override fun changeUser(newUser: UserHandle) {
+ if (newUser.identifier == userId) return
+ unregisterBroadcastReceiver()
+ userId = newUser.identifier
+ restoredTiles = null
+ loadTiles()
+ registerBroadcastReceiver()
+ }
+
+ /**
+ * Returns `true` if the tile has been auto-added before
+ */
+ fun isAdded(tile: String): Boolean {
+ return synchronized(autoAdded) {
+ tile in autoAdded
+ }
+ }
+
+ /**
+ * Sets a tile as auto-added.
+ *
+ * From here on, [isAdded] will return true for that tile.
+ */
+ fun setTileAdded(tile: String) {
+ val tiles = synchronized(autoAdded) {
+ if (autoAdded.add(tile)) {
+ getTilesFromListLocked()
+ } else {
+ null
+ }
+ }
+ tiles?.let { saveTiles(it) }
+ }
+
+ /**
+ * Removes a tile from the list of auto-added.
+ *
+ * This allows for this tile to be auto-added again in the future.
+ */
+ fun setTileRemoved(tile: String) {
+ val tiles = synchronized(autoAdded) {
+ if (autoAdded.remove(tile)) {
+ getTilesFromListLocked()
+ } else {
+ null
+ }
+ }
+ tiles?.let { saveTiles(it) }
+ }
+
+ private fun getTilesFromListLocked(): String {
+ return TextUtils.join(",", autoAdded)
+ }
+
+ private fun saveTiles(tiles: String) {
+ secureSettings.putStringForUser(
+ Settings.Secure.QS_AUTO_ADDED_TILES,
+ tiles,
+ /* tag */ null,
+ /* makeDefault */ false,
+ userId,
+ /* overrideableByRestore */ true
+ )
+ }
+
+ private fun loadTiles() {
+ synchronized(autoAdded) {
+ autoAdded.clear()
+ autoAdded.addAll(getAdded())
+ }
+ }
+
+ private fun getAdded(): Collection<String> {
+ val current = secureSettings.getStringForUser(Settings.Secure.QS_AUTO_ADDED_TILES, userId)
+ return current?.split(",") ?: emptySet()
+ }
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println("Current user: $userId")
+ pw.println("Added tiles: $autoAdded")
+ }
+
+ @SysUISingleton
+ class Builder @Inject constructor(
+ private val secureSettings: SecureSettings,
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val qsHost: QSHost,
+ private val dumpManager: DumpManager,
+ @Main private val handler: Handler,
+ @Background private val executor: Executor
+ ) {
+ private var userId: Int = 0
+
+ fun setUserId(_userId: Int): Builder {
+ userId = _userId
+ return this
+ }
+
+ fun build(): AutoAddTracker {
+ return AutoAddTracker(
+ secureSettings,
+ broadcastDispatcher,
+ qsHost,
+ dumpManager,
+ handler,
+ executor,
+ userId
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 000fd1c..9f585bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -37,6 +37,7 @@
void removeCallback(Callback callback);
TileServices getTileServices();
void removeTile(String tileSpec);
+ void removeTiles(Collection<String> specs);
void unmarkTileAsAutoAdded(String tileSpec);
int indexOf(String tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index ae3dde1..9ceeb75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -348,6 +348,17 @@
changeTileSpecs(tileSpecs-> tileSpecs.remove(spec));
}
+ /**
+ * Remove many tiles at once.
+ *
+ * It will only save to settings once (as opposed to {@link QSTileHost#removeTile} called
+ * multiple times).
+ */
+ @Override
+ public void removeTiles(Collection<String> specs) {
+ changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs));
+ }
+
@Override
public void unmarkTileAsAutoAdded(String spec) {
if (mAutoTiles != null) mAutoTiles.unmarkTileAsAutoAdded(spec);
@@ -369,6 +380,7 @@
* @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
*/
public void addTile(String spec, int requestPosition) {
+ if (spec.equals("work")) Log.wtfStack(TAG, "Adding work tile");
changeTileSpecs(tileSpecs -> {
if (tileSpecs.contains(spec)) return false;
@@ -383,6 +395,7 @@
}
void saveTilesToSettings(List<String> tileSpecs) {
+ if (tileSpecs.contains("work")) Log.wtfStack(TAG, "Saving work tile");
mSecureSettings.putStringForUser(TILES_SETTING, TextUtils.join(",", tileSpecs),
null /* tag */, false /* default */, mCurrentUser,
true /* overrideable by restore */);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index 82b6c0c..d9919bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -131,22 +131,16 @@
Intent intent = new Intent(mContext, WalletActivity.class)
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
- if (mKeyguardStateController.isUnlocked()) {
- mActivityStarter.startActivity(intent, true /* dismissShade */,
- animationController);
- } else {
- mHost.collapsePanels();
- // Do not use ActivityStarter here because the WalletActivity is required to be
- // started without prompting keyguard when the device is locked.
- mContext.startActivity(intent);
- }
+ mActivityStarter.startActivity(intent, true /* dismissShade */,
+ animationController, true /* showOverLockscreenWhenLocked */);
} else {
- if (mController.getWalletClient().createWalletIntent() == null) {
+ Intent intent = mController.getWalletClient().createWalletIntent();
+ if (intent == null) {
Log.w(TAG, "Could not get intent of the wallet app.");
return;
}
mActivityStarter.postStartActivityDismissingKeyguard(
- mController.getWalletClient().createWalletIntent(),
+ intent,
/* delay= */ 0,
animationController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
index 0aa9d4d..5a6f2a2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
@@ -27,6 +27,7 @@
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.util.Log;
+import android.util.MathUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -128,30 +129,64 @@
mThread = new Thread(() -> {
short[] bufferInternal = null;
short[] bufferMic = null;
- byte[] buffer = null;
+ byte[] buffer = new byte[size];
if (mMic) {
bufferInternal = new short[size / 2];
bufferMic = new short[size / 2];
- } else {
- buffer = new byte[size];
}
+ int readBytes = 0;
+ int readShortsInternal = 0;
+ int offsetShortsInternal = 0;
+ int readShortsMic = 0;
+ int offsetShortsMic = 0;
while (true) {
- int readBytes = 0;
- int readShortsInternal = 0;
- int readShortsMic = 0;
if (mMic) {
- readShortsInternal = mAudioRecord.read(bufferInternal, 0,
- bufferInternal.length);
- readShortsMic = mAudioRecordMic.read(bufferMic, 0, bufferMic.length);
+ readShortsInternal = mAudioRecord.read(bufferInternal, offsetShortsInternal,
+ bufferInternal.length - offsetShortsInternal);
+ readShortsMic = mAudioRecordMic.read(
+ bufferMic, offsetShortsMic, bufferMic.length - offsetShortsMic);
+
+ // if both error, end the recording
+ if (readShortsInternal < 0 && readShortsMic < 0) {
+ break;
+ }
+
+ // if one has an errors, fill its buffer with zeros and assume it is mute
+ // with the same size as the other buffer
+ if (readShortsInternal < 0) {
+ readShortsInternal = readShortsMic;
+ offsetShortsInternal = offsetShortsMic;
+ java.util.Arrays.fill(bufferInternal, (short) 0);
+ }
+
+ if (readShortsMic < 0) {
+ readShortsMic = readShortsInternal;
+ offsetShortsMic = offsetShortsInternal;
+ java.util.Arrays.fill(bufferMic, (short) 0);
+ }
+
+ // Add offset (previous unmixed values) to the buffer
+ readShortsInternal += offsetShortsInternal;
+ readShortsMic += offsetShortsMic;
+
+ int minShorts = Math.min(readShortsInternal, readShortsMic);
+ readBytes = minShorts * 2;
// modify the volume
- bufferMic = scaleValues(bufferMic,
- readShortsMic, MIC_VOLUME_SCALE);
- readBytes = Math.min(readShortsInternal, readShortsMic) * 2;
- buffer = addAndConvertBuffers(bufferInternal, readShortsInternal, bufferMic,
- readShortsMic);
+ // scale only mixed shorts
+ scaleValues(bufferMic, minShorts, MIC_VOLUME_SCALE);
+ // Mix the two buffers
+ addAndConvertBuffers(bufferInternal, bufferMic, buffer, minShorts);
+
+ // shift unmixed shorts to the beginning of the buffer
+ shiftToStart(bufferInternal, minShorts, offsetShortsInternal);
+ shiftToStart(bufferMic, minShorts, offsetShortsMic);
+
+ // reset the offset for the next loop
+ offsetShortsInternal = readShortsInternal - minShorts;
+ offsetShortsMic = readShortsMic - minShorts;
} else {
readBytes = mAudioRecord.read(buffer, 0, buffer.length);
}
@@ -169,40 +204,31 @@
});
}
- private short[] scaleValues(short[] buff, int len, float scale) {
- for (int i = 0; i < len; i++) {
- int oldValue = buff[i];
- int newValue = (int) (buff[i] * scale);
- if (newValue > Short.MAX_VALUE) {
- newValue = Short.MAX_VALUE;
- } else if (newValue < Short.MIN_VALUE) {
- newValue = Short.MIN_VALUE;
- }
- buff[i] = (short) (newValue);
+ /**
+ * moves all bits from start to end to the beginning of the array
+ */
+ private void shiftToStart(short[] target, int start, int end) {
+ for (int i = 0; i < end - start; i++) {
+ target[i] = target[start + i];
}
- return buff;
}
- private byte[] addAndConvertBuffers(short[] a1, int a1Limit, short[] a2, int a2Limit) {
- int size = Math.max(a1Limit, a2Limit);
- if (size < 0) return new byte[0];
- byte[] buff = new byte[size * 2];
- for (int i = 0; i < size; i++) {
- int sum;
- if (i > a1Limit) {
- sum = a2[i];
- } else if (i > a2Limit) {
- sum = a1[i];
- } else {
- sum = (int) a1[i] + (int) a2[i];
- }
- if (sum > Short.MAX_VALUE) sum = Short.MAX_VALUE;
- if (sum < Short.MIN_VALUE) sum = Short.MIN_VALUE;
- int byteIndex = i * 2;
- buff[byteIndex] = (byte) (sum & 0xff);
- buff[byteIndex + 1] = (byte) ((sum >> 8) & 0xff);
+ private void scaleValues(short[] buff, int len, float scale) {
+ for (int i = 0; i < len; i++) {
+ int newValue = (int) (buff[i] * scale);
+ buff[i] = (short) MathUtils.constrain(newValue, Short.MIN_VALUE, Short.MAX_VALUE);
}
- return buff;
+ }
+
+ private void addAndConvertBuffers(short[] src1, short[] src2, byte[] dst, int sizeShorts) {
+ for (int i = 0; i < sizeShorts; i++) {
+ int sum;
+ sum = (short) MathUtils.constrain(
+ (int) src1[i] + (int) src2[i], Short.MIN_VALUE, Short.MAX_VALUE);
+ int byteIndex = i * 2;
+ dst[byteIndex] = (byte) (sum & 0xff);
+ dst[byteIndex + 1] = (byte) ((sum >> 8) & 0xff);
+ }
}
private void encode(byte[] buffer, int readBytes) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index dce19cf..cfbe3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -54,22 +54,22 @@
/**
* Translates a ratio from 0 to 1 to a blur radius in pixels.
*/
- fun blurRadiusOfRatio(ratio: Float): Int {
+ fun blurRadiusOfRatio(ratio: Float): Float {
if (ratio == 0f) {
- return 0
+ return 0f
}
- return MathUtils.lerp(minBlurRadius.toFloat(), maxBlurRadius.toFloat(), ratio).toInt()
+ return MathUtils.lerp(minBlurRadius.toFloat(), maxBlurRadius.toFloat(), ratio)
}
/**
* Translates a blur radius in pixels to a ratio between 0 to 1.
*/
- fun ratioOfBlurRadius(blur: Int): Float {
- if (blur == 0) {
+ fun ratioOfBlurRadius(blur: Float): Float {
+ if (blur == 0f) {
return 0f
}
return MathUtils.map(minBlurRadius.toFloat(), maxBlurRadius.toFloat(),
- 0f /* maxStart */, 1f /* maxStop */, blur.toFloat())
+ 0f /* maxStart */, 1f /* maxStop */, blur)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 503b5c0..1431c9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -821,7 +821,7 @@
}
}
- private void showTryFingerprintMsg() {
+ private void showTryFingerprintMsg(String a11yString) {
if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
// if udfps available, there will always be a tappable affordance to unlock
// For example, the lock icon
@@ -833,6 +833,11 @@
} else {
showTransientIndication(R.string.keyguard_try_fingerprint);
}
+
+ // Although we suppress face auth errors visually, we still announce them for a11y
+ if (!TextUtils.isEmpty(a11yString)) {
+ mLockScreenIndicationView.announceForAccessibility(a11yString);
+ }
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -913,7 +918,7 @@
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
if (biometricSourceType == BiometricSourceType.FACE
&& shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
- showTryFingerprintMsg();
+ showTryFingerprintMsg(helpString);
return;
}
showTransientIndication(helpString, false /* isError */, showActionToUnlock);
@@ -933,7 +938,7 @@
&& shouldSuppressFaceMsgAndShowTryFingerprintMsg()
&& !mStatusBarKeyguardViewManager.isBouncerShowing()
&& mKeyguardUpdateMonitor.isScreenOn()) {
- showTryFingerprintMsg();
+ showTryFingerprintMsg(errString);
return;
}
if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
@@ -942,7 +947,7 @@
if (!mStatusBarKeyguardViewManager.isBouncerShowing()
&& mKeyguardUpdateMonitor.isUdfpsEnrolled()
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
- showTryFingerprintMsg();
+ showTryFingerprintMsg(errString);
} else if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
mStatusBarKeyguardViewManager.showBouncerMessage(
mContext.getResources().getString(R.string.keyguard_unlock_press),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 8780ad8..51dbd85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -178,7 +178,10 @@
*/
class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
- lateinit var revealAmountListener: Consumer<Float>
+ /**
+ * Listener that is called if the scrim's opaqueness changes
+ */
+ lateinit var isScrimOpaqueChangedListener: Consumer<Boolean>
/**
* How much of the underlying views are revealed, in percent. 0 means they will be completely
@@ -190,7 +193,7 @@
field = value
revealEffect.setRevealAmountOnScrim(value, this)
- revealAmountListener.accept(value)
+ updateScrimOpaque()
invalidate()
}
}
@@ -230,6 +233,31 @@
}
/**
+ * Is the scrim currently fully opaque
+ */
+ var isScrimOpaque = false
+ private set(value) {
+ if (field != value) {
+ field = value
+ isScrimOpaqueChangedListener.accept(field)
+ }
+ }
+
+ private fun updateScrimOpaque() {
+ isScrimOpaque = revealAmount == 0.0f && alpha == 1.0f && visibility == VISIBLE
+ }
+
+ override fun setAlpha(alpha: Float) {
+ super.setAlpha(alpha)
+ updateScrimOpaque()
+ }
+
+ override fun setVisibility(visibility: Int) {
+ super.setVisibility(visibility)
+ updateScrimOpaque()
+ }
+
+ /**
* Paint used to draw a transparent-to-white radial gradient. This will be scaled and translated
* via local matrix in [onDraw] so we never need to construct a new shader.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 002c9c7..b833427 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -68,7 +68,7 @@
private const val VELOCITY_SCALE = 100f
private const val MAX_VELOCITY = 3000f
private const val MIN_VELOCITY = -MAX_VELOCITY
- private const val INTERACTION_BLUR_FRACTION = 0.4f
+ private const val INTERACTION_BLUR_FRACTION = 0.8f
private const val ANIMATION_BLUR_FRACTION = 1f - INTERACTION_BLUR_FRACTION
private const val TAG = "DepthController"
}
@@ -92,8 +92,6 @@
// Only for dumpsys
private var lastAppliedBlur = 0
- @VisibleForTesting
- var shadeSpring = DepthAnimation()
var shadeAnimation = DepthAnimation()
@VisibleForTesting
@@ -101,12 +99,16 @@
var brightnessMirrorVisible: Boolean = false
set(value) {
field = value
- brightnessMirrorSpring.animateTo(if (value) blurUtils.blurRadiusOfRatio(1f)
+ brightnessMirrorSpring.animateTo(if (value) blurUtils.blurRadiusOfRatio(1f).toInt()
else 0)
}
var qsPanelExpansion = 0f
set(value) {
+ if (value.isNaN()) {
+ Log.w(TAG, "Invalid qs expansion")
+ return
+ }
if (field == value) return
field = value
scheduleUpdate()
@@ -134,15 +136,13 @@
field = value
scheduleUpdate()
- if (shadeSpring.radius == 0 && shadeAnimation.radius == 0) {
+ if (shadeExpansion == 0f && shadeAnimation.radius == 0f) {
return
}
// Do not remove blurs when we're re-enabling them
if (!value) {
return
}
- shadeSpring.animateTo(0)
- shadeSpring.finishIfRunning()
shadeAnimation.animateTo(0)
shadeAnimation.finishIfRunning()
@@ -161,7 +161,7 @@
/**
* Blur radius of the wake-up animation on this frame.
*/
- private var wakeAndUnlockBlurRadius = 0
+ private var wakeAndUnlockBlurRadius = 0f
set(value) {
if (field == value) return
field = value
@@ -174,26 +174,30 @@
@VisibleForTesting
val updateBlurCallback = Choreographer.FrameCallback {
updateScheduled = false
- val normalizedBlurRadius = MathUtils.constrain(shadeAnimation.radius,
- blurUtils.minBlurRadius, blurUtils.maxBlurRadius)
- var combinedBlur = (shadeSpring.radius * INTERACTION_BLUR_FRACTION +
- normalizedBlurRadius * ANIMATION_BLUR_FRACTION).toInt()
+ val animationRadius = MathUtils.constrain(shadeAnimation.radius,
+ blurUtils.minBlurRadius.toFloat(), blurUtils.maxBlurRadius.toFloat())
+ val expansionRadius = blurUtils.blurRadiusOfRatio(
+ Interpolators.getNotificationScrimAlpha(
+ if (shouldApplyShadeBlur()) shadeExpansion else 0f, false))
+ var combinedBlur = (expansionRadius * INTERACTION_BLUR_FRACTION +
+ animationRadius * ANIMATION_BLUR_FRACTION)
val qsExpandedRatio = qsPanelExpansion * shadeExpansion
combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio))
combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
- var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius).toFloat()
+ var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius)
if (blursDisabledForAppLaunch) {
shadeRadius = 0f
}
+ var zoomOut = MathUtils.saturate(blurUtils.ratioOfBlurRadius(shadeRadius))
var blur = shadeRadius.toInt()
// Make blur be 0 if it is necessary to stop blur effect.
if (scrimsVisible) {
blur = 0
+ zoomOut = 0f
}
- val zoomOut = blurUtils.ratioOfBlurRadius(blur)
if (!blurUtils.supportsBlursOnWindows()) {
blur = 0
@@ -266,12 +270,11 @@
override fun onStateChanged(newState: Int) {
updateShadeAnimationBlur(
shadeExpansion, prevTracking, prevShadeVelocity, prevShadeDirection)
- updateShadeBlur()
+ scheduleUpdate()
}
override fun onDozingChanged(isDozing: Boolean) {
if (isDozing) {
- shadeSpring.finishIfRunning()
shadeAnimation.finishIfRunning()
brightnessMirrorSpring.finishIfRunning()
}
@@ -336,7 +339,7 @@
prevTracking = tracking
prevTimestamp = timestamp
- updateShadeBlur()
+ scheduleUpdate()
}
private fun updateShadeAnimationBlur(
@@ -399,15 +402,7 @@
}
shadeAnimation.setStartVelocity(velocity)
- shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized))
- }
-
- private fun updateShadeBlur() {
- var newBlur = 0
- if (shouldApplyShadeBlur()) {
- newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion)
- }
- shadeSpring.animateTo(newBlur)
+ shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized).toInt())
}
private fun scheduleUpdate(viewToBlur: View? = null) {
@@ -433,7 +428,8 @@
IndentingPrintWriter(pw, " ").let {
it.println("StatusBarWindowBlurController:")
it.increaseIndent()
- it.println("shadeRadius: ${shadeSpring.radius}")
+ it.println("shadeExpansion: $shadeExpansion")
+ it.println("shouldApplyShaeBlur: ${shouldApplyShadeBlur()}")
it.println("shadeAnimation: ${shadeAnimation.radius}")
it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
@@ -452,7 +448,7 @@
/**
* Blur radius visible on the UI, in pixels.
*/
- var radius = 0
+ var radius = 0f
/**
* Depth ratio of the current blur radius.
@@ -473,12 +469,12 @@
private var springAnimation = SpringAnimation(this, object :
FloatPropertyCompat<DepthAnimation>("blurRadius") {
override fun setValue(rect: DepthAnimation?, value: Float) {
- radius = value.toInt()
+ radius = value
scheduleUpdate(view)
}
override fun getValue(rect: DepthAnimation?): Float {
- return radius.toFloat()
+ return radius
}
})
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index f0d779c..6ea79af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -182,10 +182,10 @@
default void setFaceAuthDisplayBrightness(float brightness) {}
/**
- * How much {@link LightRevealScrim} obscures the UI.
- * @param amount 0 when opaque, 1 when not transparent
+ * If {@link LightRevealScrim} obscures the UI.
+ * @param opaque if the scrim is opaque
*/
- default void setLightRevealScrimAmount(float amount) {}
+ default void setLightRevealScrimOpaque(boolean opaque) {}
/**
* Custom listener to pipe data back to plugins about whether or not the status bar would be
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index f1610d8..dcf8e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -114,6 +114,10 @@
Log.d(TAG, "updating current event from: $event")
}
scheduledEvent?.updateFromEvent(event)
+ if (event.forceVisible) {
+ hasPersistentDot = true
+ notifyTransitionToPersistentDot()
+ }
} else {
if (DEBUG) {
Log.d(TAG, "ignoring event $event")
@@ -154,6 +158,7 @@
// If animations are turned off, we'll transition directly to the dot
if (!event.showAnimation && event.forceVisible) {
notifyTransitionToPersistentDot()
+ scheduledEvent = null
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b2cf72a..21c3e5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -116,11 +116,18 @@
if (!mDozing || mPulseCallback != null) {
if (DEBUG) {
- Log.d(TAG, "Pulse supressed. Dozing: " + mDozeParameters + " had callback? "
+ Log.d(TAG, "Pulse suppressed. Dozing: " + mDozeParameters + " had callback? "
+ (mPulseCallback != null));
}
// Pulse suppressed.
callback.onPulseFinished();
+ if (!mDozing) {
+ mDozeLog.tracePulseDropped("device isn't dozing");
+ } else {
+ mDozeLog.tracePulseDropped("already has pulse callback mPulseCallback="
+ + mPulseCallback);
+ }
+
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 0a4e59c..a56b8ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -80,6 +80,7 @@
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.camera.CameraIntents;
@@ -1044,11 +1045,13 @@
return;
}
+ ActivityLaunchAnimator.Controller animationController = createLaunchAnimationController(v);
if (mHasCard) {
Intent intent = new Intent(mContext, WalletActivity.class)
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ mActivityStarter.startActivity(intent, true /* dismissShade */, animationController,
+ true /* showOverLockscreenWhenLocked */);
} else {
if (mQuickAccessWalletController.getWalletClient().createWalletIntent() == null) {
Log.w(TAG, "Could not get intent of the wallet app.");
@@ -1056,10 +1059,14 @@
}
mActivityStarter.postStartActivityDismissingKeyguard(
mQuickAccessWalletController.getWalletClient().createWalletIntent(),
- /* delay= */ 0);
+ /* delay= */ 0, animationController);
}
}
+ protected ActivityLaunchAnimator.Controller createLaunchAnimationController(View view) {
+ return ActivityLaunchAnimator.Controller.fromView(view, null);
+ }
+
private void onControlsClick(View v) {
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index c52a094..030a895 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -606,12 +606,11 @@
}
@Override
- public void setLightRevealScrimAmount(float amount) {
- boolean lightRevealScrimOpaque = amount == 0;
- if (mCurrentState.mLightRevealScrimOpaque == lightRevealScrimOpaque) {
+ public void setLightRevealScrimOpaque(boolean opaque) {
+ if (mCurrentState.mLightRevealScrimOpaque == opaque) {
return;
}
- mCurrentState.mLightRevealScrimOpaque = lightRevealScrimOpaque;
+ mCurrentState.mLightRevealScrimOpaque = opaque;
apply(mCurrentState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index b5d9bd6..e57e200 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -311,6 +311,12 @@
// Capture all touch events in always-on.
return true;
}
+
+ if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
+ // capture all touches if the alt auth bouncer is showing
+ return true;
+ }
+
boolean intercept = false;
if (mNotificationPanelViewController.isFullyExpanded()
&& mDragDownHelper.isDragDownEnabled()
@@ -338,6 +344,12 @@
if (mStatusBarStateController.isDozing()) {
handled = !mService.isPulsing();
}
+
+ if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
+ // eat the touch
+ handled = true;
+ }
+
if ((mDragDownHelper.isDragDownEnabled() && !handled)
|| mDragDownHelper.isDraggingDown()) {
// we still want to finish our drag down gesture when locking the screen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 310f02e..a3877b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -1213,10 +1213,14 @@
case MotionEvent.ACTION_MOVE:
final float h = y - mInitialTouchY;
addMovement(event);
- if (canCollapsePanel || mTouchStartedInEmptyArea || mAnimatingOnDown) {
+ final boolean openShadeWithoutHun =
+ mPanelClosedOnDown && !mCollapsedAndHeadsUpOnDown;
+ if (canCollapsePanel || mTouchStartedInEmptyArea || mAnimatingOnDown
+ || openShadeWithoutHun) {
float hAbs = Math.abs(h);
float touchSlop = getTouchSlop(event);
- if ((h < -touchSlop || (mAnimatingOnDown && hAbs > touchSlop))
+ if ((h < -touchSlop
+ || ((openShadeWithoutHun || mAnimatingOnDown) && hAbs > touchSlop))
&& hAbs > Math.abs(x - mInitialTouchX)) {
cancelHeightAnimator();
startExpandMotion(x, y, true /* startTracking */, mExpandedHeight);
@@ -1229,10 +1233,7 @@
mVelocityTracker.clear();
break;
}
-
- // Finally, if none of the above cases applies, ensure that touches do not get handled
- // by the contents of a panel that is not showing (a bit of a hack to avoid b/178277858)
- return (mView.getVisibility() != View.VISIBLE);
+ return false;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 43a8630..e3319e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -111,6 +111,20 @@
*/
private boolean mTransitioningToFullShade;
+ /**
+ * Is there currently an unocclusion animation running. Used to avoid bright flickers
+ * of the notification scrim.
+ */
+ private boolean mUnOcclusionAnimationRunning;
+
+ /**
+ * Set whether an unocclusion animation is currently running on the notification panel. Used
+ * to avoid bright flickers of the notification scrim.
+ */
+ public void setUnocclusionAnimationRunning(boolean unocclusionAnimationRunning) {
+ mUnOcclusionAnimationRunning = unocclusionAnimationRunning;
+ }
+
@IntDef(prefix = {"VISIBILITY_"}, value = {
TRANSPARENT,
SEMI_TRANSPARENT,
@@ -436,6 +450,7 @@
public void onExpandingFinished() {
mTracking = false;
+ setUnocclusionAnimationRunning(false);
}
@VisibleForTesting
@@ -672,6 +687,17 @@
mNotificationsTint = mState.getNotifTint();
mBehindTint = behindTint;
}
+
+ // At the end of a launch animation over the lockscreen, the state is either KEYGUARD or
+ // SHADE_LOCKED and this code is called. We have to set the notification alpha to 0
+ // otherwise there is a flicker to its previous value.
+ if (mKeyguardOccluded) {
+ mNotificationsAlpha = 0;
+ }
+ if (mUnOcclusionAnimationRunning && mState == ScrimState.KEYGUARD) {
+ // We're unoccluding the keyguard and don't want to have a bright flash.
+ mNotificationsAlpha = 0f;
+ }
}
assertAlphasValid();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
index edacbe1..768222d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
@@ -118,10 +118,6 @@
+ " flags=" + flags);
}
- if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
- getStatusBar().postHideRecentApps();
- }
-
// TODO(b/62444020): remove when this bug is fixed
Log.v(TAG, "NotificationShadeWindow: " + getNotificationShadeWindowView()
+ " canPanelBeCollapsed(): "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5c1e648..0cfdf79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -51,6 +51,7 @@
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.TaskInfo;
+import android.app.TaskStackBuilder;
import android.app.UiModeManager;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
@@ -73,7 +74,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
-import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -143,6 +143,7 @@
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.emergency.EmergencyGesture;
@@ -227,9 +228,11 @@
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.concurrency.MessageRouter;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
-import com.android.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
@@ -252,16 +255,9 @@
/** */
public class StatusBar extends SystemUI implements
ActivityStarter,
- ConfigurationListener,
- StatusBarStateController.StateListener,
- LifecycleOwner, BatteryController.BatteryStateChangeCallback,
- ActivityLaunchAnimator.Callback {
+ LifecycleOwner {
public static final boolean MULTIUSER_DEBUG = false;
- protected static final int MSG_HIDE_RECENT_APPS = 1020;
- protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
- protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
- protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
// Should match the values in PhoneWindowManager
@@ -289,8 +285,6 @@
public static final String ACTION_FAKE_ARTWORK = "fake_artwork";
- private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
- private static final int MSG_CLOSE_PANELS = 1001;
private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
// 1020-1040 reserved for BaseStatusBar
@@ -370,13 +364,14 @@
mWereIconsJustHidden = justHidden;
}
- void resetHandlerMsg(int msg) {
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
+ void resendMessage(int msg) {
+ mMessageRouter.cancelMessages(msg);
+ mMessageRouter.sendMessage(msg);
}
- Handler getHandler() {
- return mHandler;
+ void resendMessage(Object msg) {
+ mMessageRouter.cancelMessages(msg.getClass());
+ mMessageRouter.sendMessage(msg);
}
int getDisabled1() {
@@ -544,6 +539,7 @@
private final UnfoldTransitionConfig mUnfoldTransitionConfig;
private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ private final MessageRouter mMessageRouter;
private final WallpaperManager mWallpaperManager;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private final TunerService mTunerService;
@@ -574,29 +570,6 @@
// ensure quick settings is disabled until the current user makes it through the setup wizard
@VisibleForTesting
protected boolean mUserSetup = false;
- private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
- @Override
- public void onUserSetupChanged() {
- final boolean userSetup = mDeviceProvisionedController.isUserSetup(
- mDeviceProvisionedController.getCurrentUser());
- Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
- + mDeviceProvisionedController.getCurrentUser());
- if (MULTIUSER_DEBUG) {
- Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
- userSetup, mUserSetup));
- }
-
- if (userSetup != mUserSetup) {
- mUserSetup = userSetup;
- if (!mUserSetup && mStatusBarView != null)
- animateCollapseQuickSettings();
- if (mNotificationPanelViewController != null) {
- mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
- }
- updateQsExpansionEnabled();
- }
- }
- };
@VisibleForTesting
public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum {
@@ -636,7 +609,8 @@
}
}
- protected final H mHandler = createHandler();
+ private Handler mMainHandler;
+ private final DelayableExecutor mMainExecutor;
private int mInteractingWindows;
private @TransitionMode int mStatusBarMode;
@@ -653,33 +627,6 @@
private final NotificationRemoteInputManager mRemoteInputManager;
private boolean mWallpaperSupported;
- private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mWallpaperSupported) {
- // Receiver should not have been registered at all...
- Log.wtf(TAG, "WallpaperManager not supported");
- return;
- }
- WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
- final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
- // If WallpaperInfo is null, it must be ImageWallpaper.
- final boolean supportsAmbientMode = deviceSupportsAodWallpaper
- && (info != null && info.supportsAmbientMode());
-
- mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
- mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
- }
- };
-
- BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mBubblesOptional.ifPresent(bubbles -> bubbles.onTaskbarChanged(intent.getExtras()));
- }
- };
-
private Runnable mLaunchTransitionEndRunnable;
private boolean mLaunchCameraWhenFinishedWaking;
private boolean mLaunchCameraOnFinishedGoingToSleep;
@@ -698,29 +645,7 @@
private boolean mIsOccluded;
private boolean mWereIconsJustHidden;
private boolean mBouncerWasShowingWhenHidden;
-
- // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
- // this animation is tied to the scrim for historic reasons.
- // TODO: notify when keyguard has faded away instead of the scrim.
- private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
- .Callback() {
- @Override
- public void onFinished() {
- if (mStatusBarKeyguardViewManager == null) {
- Log.w(TAG, "Tried to notify keyguard visibility when "
- + "mStatusBarKeyguardViewManager was null");
- return;
- }
- if (mKeyguardStateController.isKeyguardFadingAway()) {
- mStatusBarKeyguardViewManager.onKeyguardFadedAway();
- }
- }
-
- @Override
- public void onCancelled() {
- onFinished();
- }
- };
+ private boolean mIsLaunchingActivityOverLockscreen;
private final UserSwitcherController mUserSwitcherController;
private final NetworkController mNetworkController;
@@ -739,36 +664,6 @@
private boolean mNoAnimationOnNextBarModeChange;
private final SysuiStatusBarStateController mStatusBarStateController;
- private final KeyguardUpdateMonitorCallback mUpdateCallback =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onDreamingStateChanged(boolean dreaming) {
- if (dreaming) {
- maybeEscalateHeadsUp();
- }
- }
-
- // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
- // KeyguardCoordinator
- @Override
- public void onStrongAuthStateChanged(int userId) {
- super.onStrongAuthStateChanged(userId);
- mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
- }
- };
-
-
- private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
- new FalsingManager.FalsingBeliefListener() {
- @Override
- public void onFalse() {
- // Hides quick settings, bouncer, and quick-quick settings.
- mStatusBarKeyguardViewManager.reset(true);
- }
- };
-
- private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
-
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private ActivityLaunchAnimator mActivityLaunchAnimator;
private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
@@ -787,6 +682,7 @@
private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
(extractor, which) -> updateTheme();
+
/**
* Public constructor for StatusBar.
*
@@ -881,6 +777,9 @@
LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+ @Main Handler mainHandler,
+ @Main DelayableExecutor delayableExecutor,
+ @Main MessageRouter messageRouter,
WallpaperManager wallpaperManager,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
Optional<StartingSurface> startingSurfaceOptional,
@@ -968,6 +867,9 @@
mStatusBarIconController = statusBarIconController;
mFeatureFlags = featureFlags;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
+ mMainHandler = mainHandler;
+ mMainExecutor = delayableExecutor;
+ mMessageRouter = messageRouter;
mWallpaperManager = wallpaperManager;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mTunerService = tunerService;
@@ -985,7 +887,18 @@
});
mActivityIntentHelper = new ActivityIntentHelper(mContext);
+
+ // TODO(b/190746471): Find a better home for this.
DateTimeView.setReceiverHandler(timeTickHandler);
+
+ mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
+ data -> toggleKeyboardShortcuts(data.mDeviceId));
+ mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
+ id -> dismissKeyboardShortcuts());
+ mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
+ data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
+ mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
+ id -> onLaunchTransitionTimeout());
}
@Override
@@ -1003,7 +916,7 @@
mKeyguardIndicationController.init();
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
- mStatusBarStateController.addCallback(this,
+ mStatusBarStateController.addCallback(mStateListener,
SysuiStatusBarStateController.RANK_STATUS_BAR);
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -1117,9 +1030,9 @@
mAmbientIndicationContainer);
mDozeParameters.addCallback(this::updateLightRevealScrimVisibility);
- mConfigurationController.addCallback(this);
+ mConfigurationController.addCallback(mConfigurationListener);
- mBatteryController.observe(mLifecycle, this);
+ mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
mLifecycle.setCurrentState(RESUMED);
// set the initial view visibility
@@ -1140,7 +1053,7 @@
@Override
public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
- mMainThreadHandler.post(
+ mMainExecutor.execute(
() -> plugin.setup(getNotificationShadeWindowView(),
getNavigationBarView(),
new Callback(plugin), mDozeParameters));
@@ -1148,7 +1061,7 @@
@Override
public void onPluginDisconnected(OverlayPlugin plugin) {
- mMainThreadHandler.post(() -> {
+ mMainExecutor.execute(() -> {
mOverlays.remove(plugin);
mNotificationShadeWindowController
.setForcePluginOpen(mOverlays.size() != 0, this);
@@ -1169,7 +1082,7 @@
} else {
mOverlays.remove(mPlugin);
}
- mMainThreadHandler.post(() -> {
+ mMainExecutor.execute(() -> {
mNotificationShadeWindowController
.setStateListener(b -> mOverlays.forEach(
o -> o.setCollapseDesired(b)));
@@ -1231,8 +1144,9 @@
mConfigurationController,
mTunerService,
mBroadcastDispatcher,
- mMainThreadHandler,
- mContext.getContentResolver()
+ mMainHandler,
+ mContext.getContentResolver(),
+ mBatteryController
);
mBatteryMeterViewController.init();
@@ -1343,8 +1257,19 @@
mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
- mLightRevealScrim.setRevealAmountListener(
- mNotificationShadeWindowController::setLightRevealScrimAmount);
+ mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
+ Runnable updateOpaqueness = () -> {
+ mNotificationShadeWindowController.setLightRevealScrimOpaque(
+ mLightRevealScrim.isScrimOpaque());
+ };
+ if (opaque) {
+ // Delay making the view opaque for a frame, because it needs some time to render
+ // otherwise this can lead to a flicker where the scrim doesn't cover the screen
+ mLightRevealScrim.post(updateOpaqueness);
+ } else {
+ updateOpaqueness.run();
+ }
+ });
mUnlockedScreenOffAnimationController.initialize(this, mLightRevealScrim);
updateLightRevealScrimVisibility();
@@ -1487,19 +1412,6 @@
return mLifecycle;
}
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- mHandler.post(mCheckBarModes);
- if (mDozeServiceHost != null) {
- mDozeServiceHost.firePowerSaveChanged(isPowerSave);
- }
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- // noop
- }
-
@VisibleForTesting
protected void registerBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
@@ -1515,7 +1427,7 @@
private void setUpPresenter() {
// Set up the initial notification state.
- mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
+ mActivityLaunchAnimator = new ActivityLaunchAnimator(mKeyguardHandler, mContext);
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
@@ -1631,48 +1543,6 @@
.getNotificationShelfController(mStackScroller);
}
- @Override
- public void onDensityOrFontScaleChanged() {
- // TODO: Remove this.
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.onDensityOrFontScaleChanged();
- }
- // TODO: Bring these out of StatusBar.
- mUserInfoControllerImpl.onDensityOrFontScaleChanged();
- mUserSwitcherController.onDensityOrFontScaleChanged();
- mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
- mHeadsUpManager.onDensityOrFontScaleChanged();
- }
-
- @Override
- public void onThemeChanged() {
- if (mStatusBarKeyguardViewManager != null) {
- mStatusBarKeyguardViewManager.onThemeChanged();
- }
- if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
- ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
- }
- mNotificationIconAreaController.onThemeChanged();
- }
-
- @Override
- public void onOverlayChanged() {
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.onOverlayChanged();
- }
- // We need the new R.id.keyguard_indication_area before recreating
- // mKeyguardIndicationController
- mNotificationPanelViewController.onThemeChanged();
- onThemeChanged();
- }
-
- @Override
- public void onUiModeChanged() {
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.onUiModeChanged();
- }
- }
-
private void inflateStatusBarWindow() {
mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView();
StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get()
@@ -1858,10 +1728,6 @@
return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
}
- protected H createHandler() {
- return new StatusBar.H();
- }
-
@Override
public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
int flags) {
@@ -1875,10 +1741,77 @@
@Override
public void startActivity(Intent intent, boolean dismissShade,
- ActivityLaunchAnimator.Controller animationController) {
- startActivityDismissingKeyguard(intent, false, dismissShade,
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ boolean showOverLockscreenWhenLocked) {
+ // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't
+ // want to show the activity above it.
+ if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) {
+ startActivityDismissingKeyguard(intent, false, dismissShade,
false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
0 /* flags */, animationController);
+ return;
+ }
+
+ boolean animate =
+ animationController != null && shouldAnimateLaunch(true /* isActivityIntent */,
+ showOverLockscreenWhenLocked);
+
+ ActivityLaunchAnimator.Controller controller = null;
+ if (animate) {
+ // Wrap the animation controller to dismiss the shade and set
+ // mIsLaunchingActivityOverLockscreen during the animation.
+ ActivityLaunchAnimator.Controller delegate = wrapAnimationController(
+ animationController, dismissShade);
+ controller = new DelegateLaunchAnimatorController(delegate) {
+ @Override
+ public void onIntentStarted(boolean willAnimate) {
+ getDelegate().onIntentStarted(willAnimate);
+
+ if (willAnimate) {
+ StatusBar.this.mIsLaunchingActivityOverLockscreen = true;
+ }
+ }
+
+ @Override
+ public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
+ // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
+ // animation so that we can assume that mIsLaunchingActivityOverLockscreen
+ // being true means that we will collapse the shade (or at least run the
+ // post collapse runnables) later on.
+ StatusBar.this.mIsLaunchingActivityOverLockscreen = false;
+ getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove);
+ }
+
+ @Override
+ public void onLaunchAnimationCancelled() {
+ // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
+ // animation so that we can assume that mIsLaunchingActivityOverLockscreen
+ // being true means that we will collapse the shade (or at least run the
+ // post collapse runnables) later on.
+ StatusBar.this.mIsLaunchingActivityOverLockscreen = false;
+ getDelegate().onLaunchAnimationCancelled();
+ }
+ };
+ } else if (dismissShade) {
+ // The animation will take care of dismissing the shade at the end of the animation. If
+ // we don't animate, collapse it directly.
+ collapseShade();
+ }
+
+ mActivityLaunchAnimator.startIntentWithAnimation(controller, animate,
+ intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder
+ .create(mContext)
+ .addNextIntent(intent)
+ .startActivities(getActivityOptions(getDisplayId(), adapter),
+ UserHandle.CURRENT));
+ }
+
+ /**
+ * Whether we are currently animating an activity launch above the lockscreen (occluding
+ * activity).
+ */
+ public boolean isLaunchingActivityOverLockscreen() {
+ return mIsLaunchingActivityOverLockscreen;
}
@Override
@@ -1996,7 +1929,7 @@
// We're delaying the showing, since most of the time the fullscreen app will
// hide the icons again and we don't want them to fade in and out immediately again.
mWereIconsJustHidden = true;
- mHandler.postDelayed(() -> {
+ mMainExecutor.executeDelayed(() -> {
mWereIconsJustHidden = false;
mCommandQueue.recomputeDisableFlags(mDisplayId, true);
}, 500);
@@ -2039,51 +1972,28 @@
*
* Note: This method must be called *before* dismissing the keyguard.
*/
- public boolean shouldAnimateLaunch(boolean isActivityIntent) {
+ public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) {
// TODO(b/184121838): Support launch animations when occluded.
if (isOccluded()) {
return false;
}
- // Always animate if we are unlocked.
- if (!mKeyguardStateController.isShowing()) {
+ // Always animate if we are not showing the keyguard or if we animate over the lockscreen
+ // (without unlocking it).
+ if (showOverLockscreen || !mKeyguardStateController.isShowing()) {
return true;
}
- // If we are locked, only animate if remote unlock animations are enabled. We also don't
- // animate non-activity launches as they can break the animation.
+ // If we are locked and have to dismiss the keyguard, only animate if remote unlock
+ // animations are enabled. We also don't animate non-activity launches as they can break the
+ // animation.
// TODO(b/184121838): Support non activity launches on the lockscreen.
return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
}
- @Override
- public boolean isOnKeyguard() {
- return mKeyguardStateController.isShowing();
- }
-
- @Override
- public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
- // We post to the main thread for 2 reasons:
- // 1. KeyguardViewMediator is not thread-safe.
- // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
- // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur when doing
- // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
- mMainThreadHandler.post(() -> mKeyguardViewMediator.hideWithAnimation(runner));
- }
-
- @Override
- public void setBlursDisabledForAppLaunch(boolean disabled) {
- mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
- }
-
- @Override
- public int getBackgroundColor(TaskInfo task) {
- if (!mStartingSurfaceOptional.isPresent()) {
- Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
- return SplashscreenContentDrawer.getSystemBGColor();
- }
-
- return mStartingSurfaceOptional.get().getBackgroundColor(task);
+ /** Whether we should animate an activity launch. */
+ public boolean shouldAnimateLaunch(boolean isActivityIntent) {
+ return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */);
}
public boolean isDeviceInVrMode() {
@@ -2099,37 +2009,19 @@
mState = state;
}
- /**
- * All changes to the status bar and notifications funnel through here and are batched.
- */
- protected class H extends Handler {
- H() {
- super(Looper.myLooper());
- }
+ static class KeyboardShortcutsMessage {
+ final int mDeviceId;
- @Override
- public void handleMessage(Message m) {
- switch (m.what) {
- case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
- toggleKeyboardShortcuts(m.arg1);
- break;
- case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
- dismissKeyboardShortcuts();
- break;
- // End old BaseStatusBar.H handling.
- case MSG_OPEN_NOTIFICATION_PANEL:
- mCommandQueueCallbacks.animateExpandNotificationsPanel();
- break;
- case MSG_OPEN_SETTINGS_PANEL:
- mCommandQueueCallbacks.animateExpandSettingsPanel((String) m.obj);
- break;
- case MSG_CLOSE_PANELS:
- mShadeController.animateCollapsePanels();
- break;
- case MSG_LAUNCH_TRANSITION_TIMEOUT:
- onLaunchTransitionTimeout();
- break;
- }
+ KeyboardShortcutsMessage(int deviceId) {
+ mDeviceId = deviceId;
+ }
+ }
+
+ static class AnimateExpandSettingsPanelMessage {
+ final String mSubpanel;
+
+ AnimateExpandSettingsPanelMessage(String subpanel) {
+ mSubpanel = subpanel;
}
}
@@ -2171,27 +2063,17 @@
}
public void postAnimateCollapsePanels() {
- mHandler.post(mShadeController::animateCollapsePanels);
+ mMainExecutor.execute(mShadeController::animateCollapsePanels);
}
public void postAnimateForceCollapsePanels() {
- mHandler.post(() -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE,
+ mMainExecutor.execute(
+ () -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE,
true /* force */));
}
public void postAnimateOpenPanels() {
- mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL);
- }
-
- /**
- * Called by {@link ShadeController} when it calls
- * {@link ShadeController#animateCollapsePanels(int, boolean, boolean, float)}.
- */
- void postHideRecentApps() {
- if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) {
- mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
- mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
- }
+ mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL);
}
public boolean isExpandedVisible() {
@@ -2760,7 +2642,7 @@
&& mStatusBarKeyguardViewManager.isOccluded()) {
mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
} else {
- mHandler.post(runnable);
+ mMainExecutor.execute(runnable);
}
}
if (dismissShade) {
@@ -2772,7 +2654,7 @@
// Do it after DismissAction has been processed to conserve the needed
// ordering.
- mHandler.post(mShadeController::runPostCollapseRunnables);
+ mMainExecutor.execute(mShadeController::runPostCollapseRunnables);
}
} else if (StatusBar.this.isInLaunchTransition()
&& mNotificationPanelViewController.isLaunchTransitionFinished()) {
@@ -2781,7 +2663,7 @@
// finished,
// so nobody will call readyForKeyguardDone anymore. Post it such that
// keyguardDonePending gets called first.
- mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
+ mMainExecutor.execute(mStatusBarKeyguardViewManager::readyForKeyguardDone);
}
return deferred;
}
@@ -2820,8 +2702,8 @@
mNotificationShadeWindowController.setNotTouchable(false);
}
if (mBubblesOptional.isPresent() && mBubblesOptional.get().isStackExpanded()) {
- // Post to main thread handler, since updating the UI.
- mMainThreadHandler.post(() -> mBubblesOptional.get().collapseStack());
+ // Post to main thread, since updating the UI.
+ mMainExecutor.execute(() -> mBubblesOptional.get().collapseStack());
}
finishBarAnimations();
resetUserExpandedStates();
@@ -2882,20 +2764,6 @@
action.onDismiss();
}
}
-
- @Override
- public void onConfigChanged(Configuration newConfig) {
- updateResources();
- updateDisplaySize(); // populates mDisplayMetrics
-
- if (DEBUG) {
- Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
- }
-
- mViewHierarchyManager.updateRowStates();
- mScreenPinningRequest.onConfigurationChanged();
- }
-
/**
* Notify the shade controller that the current user changed
*
@@ -3045,10 +2913,10 @@
@Override
public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
- mHandler.post(() -> {
+ mMainExecutor.execute(() -> {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
- executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false,
- false);
+ executeRunnableDismissingKeyguard(
+ () -> mMainExecutor.execute(runnable), null, false, false, false);
});
}
@@ -3060,7 +2928,7 @@
@Override
public void postStartActivityDismissingKeyguard(final PendingIntent intent,
@Nullable ActivityLaunchAnimator.Controller animationController) {
- mHandler.post(() -> startPendingIntentDismissingKeyguard(intent,
+ mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent,
null /* intentSentUiThreadCallback */, animationController));
}
@@ -3072,7 +2940,7 @@
@Override
public void postStartActivityDismissingKeyguard(Intent intent, int delay,
@Nullable ActivityLaunchAnimator.Controller animationController) {
- mHandler.postDelayed(
+ mMainExecutor.executeDelayed(
() ->
startActivityDismissingKeyguard(intent, true /* onlyProvisioned */,
true /* dismissShade */,
@@ -3142,7 +3010,7 @@
mNotificationPanelViewController.cancelAnimation();
onLaunchTransitionFadingEnded();
}
- mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+ mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) {
mStatusBarStateController.setState(StatusBarState.FULLSCREEN_USER_SWITCHER);
} else if (!mPulseExpansionHandler.isWakingToShadeLocked()) {
@@ -3183,7 +3051,7 @@
*/
public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
Runnable endRunnable) {
- mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+ mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
mLaunchTransitionEndRunnable = endRunnable;
Runnable hideRunnable = () -> {
mKeyguardStateController.setLaunchTransitionFadingAway(true);
@@ -3224,6 +3092,7 @@
public void animateKeyguardUnoccluding() {
mNotificationPanelViewController.setExpandedFraction(0f);
mCommandQueueCallbacks.animateExpandNotificationsPanel();
+ mScrimController.setUnocclusionAnimationRunning(true);
}
/**
@@ -3232,8 +3101,8 @@
* because the launched app crashed or something else went wrong.
*/
public void startLaunchTransitionTimeout() {
- mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT,
- LAUNCH_TRANSITION_TIMEOUT_MS);
+ mMessageRouter.sendMessageDelayed(
+ MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS);
}
private void onLaunchTransitionTimeout() {
@@ -3288,7 +3157,7 @@
if (mQSPanelController != null) {
mQSPanelController.refreshAllTiles();
}
- mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+ mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
releaseGestureWakeLock();
mNotificationPanelViewController.onAffordanceLaunchEnded();
mNotificationPanelViewController.cancelAnimation();
@@ -3516,69 +3385,7 @@
mNotificationPanelViewController.collapseWithDuration(duration);
}
- @Override
- public void onStatePreChange(int oldState, int newState) {
- // If we're visible and switched to SHADE_LOCKED (the user dragged
- // down on the lockscreen), clear notification LED, vibration,
- // ringing.
- // Other transitions are covered in handleVisibleToUserChanged().
- if (mVisible && (newState == StatusBarState.SHADE_LOCKED
- || mStatusBarStateController.goingToFullShade())) {
- clearNotificationEffects();
- }
- if (newState == StatusBarState.KEYGUARD) {
- mRemoteInputManager.onPanelCollapsed();
- maybeEscalateHeadsUp();
- }
- }
- @Override
- public void onStateChanged(int newState) {
- mState = newState;
- updateReportRejectedTouchVisibility();
- mDozeServiceHost.updateDozing();
- updateTheme();
- mNavigationBarController.touchAutoDim(mDisplayId);
- Trace.beginSection("StatusBar#updateKeyguardState");
- if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) {
- mStatusBarView.removePendingHideExpandedRunnables();
- }
- updateDozingState();
- checkBarModes();
- updateScrimController();
- mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
- updateKeyguardState();
- Trace.endSection();
- }
-
- @Override
- public void onDozeAmountChanged(float linear, float eased) {
- if (mFeatureFlags.useNewLockscreenAnimations()
- && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
- mLightRevealScrim.setRevealAmount(1f - linear);
- }
- }
-
- @Override
- public void onDozingChanged(boolean isDozing) {
- Trace.beginSection("StatusBar#updateDozing");
- mDozing = isDozing;
-
- // Collapse the notification panel if open
- boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
- && mDozeParameters.shouldControlScreenOff();
- mNotificationPanelViewController.resetViews(dozingAnimated);
-
- updateQsExpansionEnabled();
- mKeyguardViewMediator.setDozing(mDozing);
-
- mNotificationsController.requestNotificationUpdate("onDozingChanged");
- updateDozingState();
- mDozeServiceHost.updateDozing();
- updateScrimController();
- updateReportRejectedTouchVisibility();
- Trace.endSection();
- }
/**
* Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
@@ -3720,7 +3527,7 @@
// This gets executed before we will show Keyguard, so post it in order that the state
// is correct.
- mHandler.post(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
+ mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
mLastCameraLaunchSource));
}
@@ -3729,7 +3536,7 @@
// This gets executed before we will show Keyguard, so post it in order that the
// state is correct.
- mHandler.post(
+ mMainExecutor.execute(
() -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected());
}
updateIsKeyguard();
@@ -3949,10 +3756,8 @@
ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
- } else if (isInLaunchTransition()
- || mLaunchCameraWhenFinishedWaking
- || launchingAffordanceWithPreview) {
- // TODO(b/170133395) Investigate whether Emergency Gesture flag should be included here.
+ } else if (launchingAffordanceWithPreview) {
+ // We want to avoid animating when launching with a preview.
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
@@ -4198,7 +4003,7 @@
}
private void postOnUiThread(Runnable runnable) {
- mMainThreadHandler.post(runnable);
+ mMainExecutor.execute(runnable);
}
/**
@@ -4376,4 +4181,277 @@
mLightRevealScrim.setVisibility(View.GONE);
}
}
+
+ private final KeyguardUpdateMonitorCallback mUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onDreamingStateChanged(boolean dreaming) {
+ if (dreaming) {
+ maybeEscalateHeadsUp();
+ }
+ }
+
+ // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
+ // KeyguardCoordinator
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ super.onStrongAuthStateChanged(userId);
+ mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
+ }
+ };
+
+
+ private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
+ new FalsingManager.FalsingBeliefListener() {
+ @Override
+ public void onFalse() {
+ // Hides quick settings, bouncer, and quick-quick settings.
+ mStatusBarKeyguardViewManager.reset(true);
+ }
+ };
+
+ // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
+ // this animation is tied to the scrim for historic reasons.
+ // TODO: notify when keyguard has faded away instead of the scrim.
+ private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
+ .Callback() {
+ @Override
+ public void onFinished() {
+ if (mStatusBarKeyguardViewManager == null) {
+ Log.w(TAG, "Tried to notify keyguard visibility when "
+ + "mStatusBarKeyguardViewManager was null");
+ return;
+ }
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
+ mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+ }
+ }
+
+ @Override
+ public void onCancelled() {
+ onFinished();
+ }
+ };
+
+ private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
+ @Override
+ public void onUserSetupChanged() {
+ final boolean userSetup = mDeviceProvisionedController.isUserSetup(
+ mDeviceProvisionedController.getCurrentUser());
+ Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
+ + mDeviceProvisionedController.getCurrentUser());
+ if (MULTIUSER_DEBUG) {
+ Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
+ userSetup, mUserSetup));
+ }
+
+ if (userSetup != mUserSetup) {
+ mUserSetup = userSetup;
+ if (!mUserSetup && mStatusBarView != null) {
+ animateCollapseQuickSettings();
+ }
+ if (mNotificationPanelViewController != null) {
+ mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
+ }
+ updateQsExpansionEnabled();
+ }
+ }
+ };
+
+ private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!mWallpaperSupported) {
+ // Receiver should not have been registered at all...
+ Log.wtf(TAG, "WallpaperManager not supported");
+ return;
+ }
+ WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
+ final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
+ // If WallpaperInfo is null, it must be ImageWallpaper.
+ final boolean supportsAmbientMode = deviceSupportsAodWallpaper
+ && (info != null && info.supportsAmbientMode());
+
+ mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+ mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+ }
+ };
+
+ BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mBubblesOptional.ifPresent(bubbles -> bubbles.onTaskbarChanged(intent.getExtras()));
+ }
+ };
+
+ private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ updateResources();
+ updateDisplaySize(); // populates mDisplayMetrics
+
+ if (DEBUG) {
+ Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
+ }
+
+ mViewHierarchyManager.updateRowStates();
+ mScreenPinningRequest.onConfigurationChanged();
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ // TODO: Remove this.
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onDensityOrFontScaleChanged();
+ }
+ // TODO: Bring these out of StatusBar.
+ mUserInfoControllerImpl.onDensityOrFontScaleChanged();
+ mUserSwitcherController.onDensityOrFontScaleChanged();
+ mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
+ mHeadsUpManager.onDensityOrFontScaleChanged();
+ }
+
+ @Override
+ public void onThemeChanged() {
+ if (mStatusBarKeyguardViewManager != null) {
+ mStatusBarKeyguardViewManager.onThemeChanged();
+ }
+ if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
+ ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
+ }
+ mNotificationIconAreaController.onThemeChanged();
+ }
+
+ @Override
+ public void onOverlayChanged() {
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onOverlayChanged();
+ }
+ // We need the new R.id.keyguard_indication_area before recreating
+ // mKeyguardIndicationController
+ mNotificationPanelViewController.onThemeChanged();
+ onThemeChanged();
+ }
+
+ @Override
+ public void onUiModeChanged() {
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onUiModeChanged();
+ }
+ }
+ };
+
+ private StatusBarStateController.StateListener mStateListener =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onStatePreChange(int oldState, int newState) {
+ // If we're visible and switched to SHADE_LOCKED (the user dragged
+ // down on the lockscreen), clear notification LED, vibration,
+ // ringing.
+ // Other transitions are covered in handleVisibleToUserChanged().
+ if (mVisible && (newState == StatusBarState.SHADE_LOCKED
+ || mStatusBarStateController.goingToFullShade())) {
+ clearNotificationEffects();
+ }
+ if (newState == StatusBarState.KEYGUARD) {
+ mRemoteInputManager.onPanelCollapsed();
+ maybeEscalateHeadsUp();
+ }
+ }
+
+ @Override
+ public void onStateChanged(int newState) {
+ mState = newState;
+ updateReportRejectedTouchVisibility();
+ mDozeServiceHost.updateDozing();
+ updateTheme();
+ mNavigationBarController.touchAutoDim(mDisplayId);
+ Trace.beginSection("StatusBar#updateKeyguardState");
+ if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) {
+ mStatusBarView.removePendingHideExpandedRunnables();
+ }
+ updateDozingState();
+ checkBarModes();
+ updateScrimController();
+ mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+ updateKeyguardState();
+ Trace.endSection();
+ }
+
+ @Override
+ public void onDozeAmountChanged(float linear, float eased) {
+ if (mFeatureFlags.useNewLockscreenAnimations()
+ && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
+ mLightRevealScrim.setRevealAmount(1f - linear);
+ }
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ Trace.beginSection("StatusBar#updateDozing");
+ mDozing = isDozing;
+
+ // Collapse the notification panel if open
+ boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
+ && mDozeParameters.shouldControlScreenOff();
+ mNotificationPanelViewController.resetViews(dozingAnimated);
+
+ updateQsExpansionEnabled();
+ mKeyguardViewMediator.setDozing(mDozing);
+
+ mNotificationsController.requestNotificationUpdate("onDozingChanged");
+ updateDozingState();
+ mDozeServiceHost.updateDozing();
+ updateScrimController();
+ updateReportRejectedTouchVisibility();
+ Trace.endSection();
+ }
+ };
+
+ private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
+ new BatteryController.BatteryStateChangeCallback() {
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mMainExecutor.execute(mCheckBarModes);
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.firePowerSaveChanged(isPowerSave);
+ }
+ }
+ };
+
+ private final ActivityLaunchAnimator.Callback mKeyguardHandler =
+ new ActivityLaunchAnimator.Callback() {
+ @Override
+ public boolean isOnKeyguard() {
+ return mKeyguardStateController.isShowing();
+ }
+
+ @Override
+ public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
+ // We post to the main thread for 2 reasons:
+ // 1. KeyguardViewMediator is not thread-safe.
+ // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
+ // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur
+ // when doing
+ // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
+ mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner));
+ }
+
+ @Override
+ public void setBlursDisabledForAppLaunch(boolean disabled) {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
+ }
+
+ @Override
+ public int getBackgroundColor(TaskInfo task) {
+ if (!mStartingSurfaceOptional.isPresent()) {
+ Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
+ return SplashscreenContentDrawer.getSystemBGColor();
+ }
+
+ return mStartingSurfaceOptional.get().getBackgroundColor(task);
+ }
+ };
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index 95f2d0a..6a510c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -256,18 +256,8 @@
}
@Override
- public void preloadRecentApps() {
- mStatusBar.resetHandlerMsg(StatusBar.MSG_PRELOAD_RECENT_APPS);
- }
-
- @Override
- public void cancelPreloadRecentApps() {
- mStatusBar.resetHandlerMsg(StatusBar.MSG_CANCEL_PRELOAD_RECENT_APPS);
- }
-
- @Override
public void dismissKeyboardShortcutsMenu() {
- mStatusBar.resetHandlerMsg(StatusBar.MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU);
+ mStatusBar.resendMessage(StatusBar.MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU);
}
/**
* State is one or more of the DISABLE constants from StatusBarManager.
@@ -330,13 +320,6 @@
}
}
- if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) {
- if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
- // close recents if it's visible
- mStatusBar.resetHandlerMsg(StatusBar.MSG_HIDE_RECENT_APPS);
- }
- }
-
if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
if (mStatusBar.areNotificationAlertsDisabled()) {
mHeadsUpManager.releaseAllImmediately();
@@ -544,9 +527,7 @@
@Override
public void toggleKeyboardShortcutsMenu(int deviceId) {
- int msg = StatusBar.MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
- mStatusBar.getHandler().removeMessages(msg);
- mStatusBar.getHandler().obtainMessage(msg, deviceId, 0).sendToTarget();
+ mStatusBar.resendMessage(new StatusBar.KeyboardShortcutsMessage(deviceId));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 95fd886d..119eff6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -73,6 +73,8 @@
import javax.inject.Inject;
+import dagger.Lazy;
+
/**
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -111,6 +113,7 @@
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private final KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
private KeyguardMessageAreaController mKeyguardMessageAreaController;
+ private final Lazy<ShadeController> mShadeController;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@Override
public void onFullyShown() {
@@ -243,7 +246,8 @@
KeyguardBouncer.Factory keyguardBouncerFactory,
WakefulnessLifecycle wakefulnessLifecycle,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
- KeyguardMessageAreaController.Factory keyguardMessageAreaFactory) {
+ KeyguardMessageAreaController.Factory keyguardMessageAreaFactory,
+ Lazy<ShadeController> shadeController) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -260,6 +264,7 @@
mWakefulnessLifecycle = wakefulnessLifecycle;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mKeyguardMessageAreaFactory = keyguardMessageAreaFactory;
+ mShadeController = shadeController;
}
@Override
@@ -634,6 +639,18 @@
});
return;
}
+
+ if (mStatusBar.isLaunchingActivityOverLockscreen()) {
+ mOccluded = true;
+
+ // When isLaunchingActivityOverLockscreen() is true, we know for sure that the post
+ // collapse runnables will be run.
+ mShadeController.get().addPostCollapseAction(() -> {
+ mNotificationShadeWindowController.setKeyguardOccluded(mOccluded);
+ reset(true /* hideBouncerWhenShowing */);
+ });
+ return;
+ }
} else if (!occluded && mOccluded && mShowing) {
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 2a34794..b36c45e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -33,6 +33,7 @@
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.flags.FeatureFlags;
@@ -103,9 +104,11 @@
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.concurrency.MessageRouter;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
-import com.android.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
@@ -217,6 +220,9 @@
LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+ @Main Handler mainHandler,
+ @Main DelayableExecutor delayableExecutor,
+ @Main MessageRouter messageRouter,
WallpaperManager wallpaperManager,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
Optional<StartingSurface> startingSurfaceOptional,
@@ -307,6 +313,9 @@
transitionController,
featureFlags,
keyguardUnlockAnimationController,
+ mainHandler,
+ delayableExecutor,
+ messageRouter,
wallpaperManager,
unlockedScreenOffAnimationController,
startingSurfaceOptional,
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index c807ad8..a53d528 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -530,6 +530,10 @@
mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, currentUser,
managedProfiles);
}
+ onOverlaysApplied();
+ }
+
+ protected void onOverlaysApplied() {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
index 8e7c49a..9283403 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
@@ -23,8 +23,7 @@
import android.view.WindowManager
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
-import com.android.unfold.UnfoldTransitionProgressProvider
-import com.android.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.LinearLightRevealEffect
import java.util.concurrent.Executor
@@ -93,7 +92,7 @@
val newScrimView = LightRevealScrim(context, null)
.apply {
revealEffect = LinearLightRevealEffect(isVerticalFold)
- revealAmountListener = Consumer {}
+ isScrimOpaqueChangedListener = Consumer {}
revealAmount = 0f
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 76cc7a0e..7794136 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -188,6 +188,7 @@
public void deleteWindowMagnification_enableAtTheBottom_overlapFlagIsFalse() {
final WindowManager wm = mContext.getSystemService(WindowManager.class);
final Rect bounds = wm.getCurrentWindowMetrics().getBounds();
+ setSystemGestureInsets();
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
@@ -463,10 +464,7 @@
@Test
public void moveWindowMagnificationToTheBottom_enabledWithGestureInset_overlapFlagIsTrue() {
final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
- final WindowInsets testInsets = new WindowInsets.Builder()
- .setInsets(systemGestures(), Insets.of(0, 0, 0, 10))
- .build();
- mWindowManager.setWindowInsets(testInsets);
+ setSystemGestureInsets();
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN);
@@ -492,4 +490,11 @@
private boolean hasMagnificationOverlapFlag() {
return (mSysUiState.getFlags() & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0;
}
+
+ private void setSystemGestureInsets() {
+ final WindowInsets testInsets = new WindowInsets.Builder()
+ .setInsets(systemGestures(), Insets.of(0, 0, 0, 10))
+ .build();
+ mWindowManager.setWindowInsets(testInsets);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
index 903cbb5..1d038a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -35,6 +35,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
@@ -58,6 +59,8 @@
private Handler mHandler;
@Mock
private ContentResolver mContentResolver;
+ @Mock
+ private BatteryController mBatteryController;
private BatteryMeterViewController mController;
@@ -74,7 +77,8 @@
mTunerService,
mBroadcastDispatcher,
mHandler,
- mContentResolver
+ mContentResolver,
+ mBatteryController
);
}
@@ -92,6 +96,7 @@
anyBoolean(),
any()
);
+ verify(mBatteryController).addCallback(any());
}
@Test
@@ -104,6 +109,7 @@
verify(mConfigurationController).removeCallback(any());
verify(mTunerService).removeTunable(any());
verify(mContentResolver).unregisterContentObserver(any());
+ verify(mBatteryController).removeCallback(any());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
new file mode 100644
index 0000000..b4ff2a5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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.battery
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
+import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class BatteryMeterViewTest : SysuiTestCase() {
+
+ private lateinit var mBatteryMeterView: BatteryMeterView
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ mBatteryMeterView = BatteryMeterView(mContext, null)
+ }
+
+ @Test
+ fun updatePercentText_estimateModeAndNotCharging_estimateFetched() {
+ mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+ mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
+
+ mBatteryMeterView.updatePercentText()
+
+ assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo(ESTIMATE)
+ }
+
+ @Test
+ fun updatePercentText_noBatteryEstimateFetcher_noCrash() {
+ mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+
+ mBatteryMeterView.updatePercentText()
+ // No assert needed
+ }
+
+ private class Fetcher : BatteryEstimateFetcher {
+ override fun fetchBatteryTimeRemainingEstimate(
+ completion: EstimateFetchCompletion) {
+ completion.onBatteryRemainingEstimateRetrieved(ESTIMATE)
+ }
+ }
+
+ private companion object {
+ const val ESTIMATE = "2 hours 2 minutes"
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 9098e44..5901080 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -69,6 +69,7 @@
import com.android.systemui.util.concurrency.FakeExecution;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
import org.junit.Before;
import org.junit.Rule;
@@ -147,6 +148,8 @@
private Handler mHandler;
@Mock
private ConfigurationController mConfigurationController;
+ @Mock
+ private SystemClock mSystemClock;
private FakeExecutor mFgExecutor;
@@ -229,7 +232,8 @@
mKeyguardBypassController,
mDisplayManager,
mHandler,
- mConfigurationController);
+ mConfigurationController,
+ mSystemClock);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index cc34c30..17730d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -18,8 +18,11 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -41,6 +44,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -81,6 +85,7 @@
private ConfigurationController mConfigurationController;
@Mock
private UdfpsController mUdfpsController;
+ private FakeSystemClock mSystemClock = new FakeSystemClock();
private UdfpsKeyguardViewController mController;
@@ -115,6 +120,7 @@
mKeyguardViewMediator,
mLockscreenShadeTransitionController,
mConfigurationController,
+ mSystemClock,
mUdfpsController);
}
@@ -274,6 +280,59 @@
verify(mStatusBarKeyguardViewManager).removeAlternateAuthInterceptor(mAltAuthInterceptor);
}
+ @Test
+ public void testHiddenUdfpsBouncerOnTouchOutside_nothingHappens() {
+ // GIVEN view is attached
+ mController.onViewAttached();
+ captureAltAuthInterceptor();
+
+ // GIVEN udfps bouncer isn't showing
+ mAltAuthInterceptor.hideAlternateAuthBouncer();
+
+ // WHEN touch is observed outside the view
+ mController.onTouchOutsideView();
+
+ // THEN bouncer / alt auth methods are never called
+ verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+ verify(mStatusBarKeyguardViewManager, never()).resetAlternateAuth(anyBoolean());
+ }
+
+ @Test
+ public void testShowingUdfpsBouncerOnTouchOutsideWithinThreshold_nothingHappens() {
+ // GIVEN view is attached
+ mController.onViewAttached();
+ captureAltAuthInterceptor();
+
+ // GIVEN udfps bouncer is showing
+ mAltAuthInterceptor.showAlternateAuthBouncer();
+
+ // WHEN touch is observed outside the view 200ms later (just within threshold)
+ mSystemClock.advanceTime(200);
+ mController.onTouchOutsideView();
+
+ // THEN bouncer / alt auth methods are never called because not enough time has passed
+ verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+ verify(mStatusBarKeyguardViewManager, never()).resetAlternateAuth(anyBoolean());
+ }
+
+ @Test
+ public void testShowingUdfpsBouncerOnTouchOutsideAboveThreshold_showInputBouncer() {
+ // GIVEN view is attached
+ mController.onViewAttached();
+ captureAltAuthInterceptor();
+
+ // GIVEN udfps bouncer is showing
+ mAltAuthInterceptor.showAlternateAuthBouncer();
+
+ // WHEN touch is observed outside the view 205ms later
+ mSystemClock.advanceTime(205);
+ mController.onTouchOutsideView();
+
+ // THEN show the bouncer and reset alt auth
+ verify(mStatusBarKeyguardViewManager).showBouncer(eq(true));
+ verify(mStatusBarKeyguardViewManager).resetAlternateAuth(anyBoolean());
+ }
+
private void sendStatusBarStateChanged(int statusBarState) {
mStatusBarStateListener.onStateChanged(statusBarState);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 8c0d21e..0e344a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -51,6 +52,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -112,6 +114,7 @@
@Mock private Handler mHandler;
@Mock private UserContextProvider mUserContextProvider;
@Mock private StatusBar mStatusBar;
+ @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private TestableLooper mTestableLooper;
@@ -155,7 +158,8 @@
mSysUiState,
mHandler,
mPackageManager,
- Optional.of(mStatusBar)
+ Optional.of(mStatusBar),
+ mKeyguardUpdateMonitor
);
mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
@@ -421,4 +425,31 @@
restartAction.onLongPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_REBOOT_LONG_PRESS);
}
+
+ @Test
+ public void testOnLockScreen_disableSmartLock() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ int user = KeyguardUpdateMonitor.getCurrentUser();
+ doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
+ doReturn(false).when(mStatusBar).isKeyguardShowing();
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+
+ // When entering power menu from lockscreen, with smart lock enabled
+ when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+ mGlobalActionsDialogLite.showOrHideDialog(true, true);
+
+ // Then smart lock will be disabled
+ verify(mLockPatternUtils).requireCredentialEntry(eq(user));
+
+ // hide dialog again
+ mGlobalActionsDialogLite.showOrHideDialog(true, true);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index 6d1db37..f8ab42f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -56,6 +56,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -127,6 +128,7 @@
@Mock private PackageManager mPackageManager;
@Mock private SecureSettings mSecureSettings;
@Mock private StatusBar mStatusBar;
+ @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private TestableLooper mTestableLooper;
@@ -170,7 +172,8 @@
mSysUiState,
mHandler,
mPackageManager,
- Optional.of(mStatusBar)
+ Optional.of(mStatusBar),
+ mKeyguardUpdateMonitor
);
mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
index de7abf8..922c6b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -14,13 +14,19 @@
package com.android.systemui.qs;
-import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
-import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.testing.AndroidTestingRunner;
@@ -28,13 +34,24 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.concurrent.Executor;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -43,42 +60,38 @@
private static final int USER = 0;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private QSHost mQSHost;
+ @Mock
+ private DumpManager mDumpManager;
+ @Captor
+ private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor;
+ @Captor
+ private ArgumentCaptor<IntentFilter> mIntentFilterArgumentCaptor;
+
+ private Executor mBackgroundExecutor = Runnable::run; // Direct executor
private AutoAddTracker mAutoTracker;
+ private SecureSettings mSecureSettings;
@Before
public void setUp() {
- Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, "");
- }
+ MockitoAnnotations.initMocks(this);
- @Test
- public void testMigration() {
- Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
- Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
- mAutoTracker = new AutoAddTracker(mContext, USER);
+ mSecureSettings = new FakeSettings();
+
+ mSecureSettings.putStringForUser(Secure.QS_AUTO_ADDED_TILES, null, USER);
+
+ mAutoTracker = createAutoAddTracker(USER);
mAutoTracker.initialize();
-
- assertTrue(mAutoTracker.isAdded(SAVER));
- assertTrue(mAutoTracker.isAdded(WORK));
- assertFalse(mAutoTracker.isAdded(INVERSION));
-
- // These keys have been removed; retrieving their values should always return the default.
- assertTrue(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true ));
- assertFalse(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, false));
- assertTrue(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, true));
- assertFalse(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, false));
-
- mAutoTracker.destroy();
}
@Test
public void testChangeFromBackup() {
- mAutoTracker = new AutoAddTracker(mContext, USER);
- mAutoTracker.initialize();
-
assertFalse(mAutoTracker.isAdded(SAVER));
- Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, SAVER);
- mAutoTracker.mObserver.onChange(false);
+ mSecureSettings.putStringForUser(Secure.QS_AUTO_ADDED_TILES, SAVER, USER);
assertTrue(mAutoTracker.isAdded(SAVER));
@@ -87,9 +100,6 @@
@Test
public void testSetAdded() {
- mAutoTracker = new AutoAddTracker(mContext, USER);
- mAutoTracker.initialize();
-
assertFalse(mAutoTracker.isAdded(SAVER));
mAutoTracker.setTileAdded(SAVER);
@@ -100,14 +110,12 @@
@Test
public void testPersist() {
- mAutoTracker = new AutoAddTracker(mContext, USER);
- mAutoTracker.initialize();
-
assertFalse(mAutoTracker.isAdded(SAVER));
mAutoTracker.setTileAdded(SAVER);
mAutoTracker.destroy();
- mAutoTracker = new AutoAddTracker(mContext, USER);
+ mAutoTracker = createAutoAddTracker(USER);
+ mAutoTracker.initialize();
assertTrue(mAutoTracker.isAdded(SAVER));
@@ -116,22 +124,158 @@
@Test
public void testIndependentUsers() {
- mAutoTracker = new AutoAddTracker(mContext, USER);
- mAutoTracker.initialize();
mAutoTracker.setTileAdded(SAVER);
- mAutoTracker = new AutoAddTracker(mContext, USER + 1);
+ mAutoTracker = createAutoAddTracker(USER + 1);
+ mAutoTracker.initialize();
assertFalse(mAutoTracker.isAdded(SAVER));
}
@Test
public void testChangeUser() {
- mAutoTracker = new AutoAddTracker(mContext, USER);
- mAutoTracker.initialize();
mAutoTracker.setTileAdded(SAVER);
- mAutoTracker = new AutoAddTracker(mContext, USER + 1);
+ mAutoTracker = createAutoAddTracker(USER + 1);
mAutoTracker.changeUser(UserHandle.of(USER));
assertTrue(mAutoTracker.isAdded(SAVER));
}
+
+ @Test
+ public void testBroadcastReceiverRegistered() {
+ verify(mBroadcastDispatcher).registerReceiver(
+ any(), mIntentFilterArgumentCaptor.capture(), any(), eq(UserHandle.of(USER)));
+
+ assertTrue(
+ mIntentFilterArgumentCaptor.getValue().hasAction(Intent.ACTION_SETTING_RESTORED));
+ }
+
+ @Test
+ public void testBroadcastReceiverChangesWithUser() {
+ mAutoTracker.changeUser(UserHandle.of(USER + 1));
+
+ InOrder inOrder = Mockito.inOrder(mBroadcastDispatcher);
+ inOrder.verify(mBroadcastDispatcher).unregisterReceiver(any());
+ inOrder.verify(mBroadcastDispatcher)
+ .registerReceiver(any(), any(), any(), eq(UserHandle.of(USER + 1)));
+ }
+
+ @Test
+ public void testSettingRestoredWithTilesNotRemovedInSource_noAutoAddedInTarget() {
+ verify(mBroadcastDispatcher).registerReceiver(
+ mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+
+ // These tiles were present in the original device
+ String restoredTiles = "saver,work,internet,cast";
+ Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, restoredTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent);
+
+ // And these tiles have been auto-added in the original device
+ // (no auto-added before restore)
+ String restoredAutoAddTiles = "work";
+ Intent restoreAutoAddTilesIntent =
+ makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, null, restoredAutoAddTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent);
+
+ // Then, don't remove any current tiles
+ verify(mQSHost, never()).removeTiles(any());
+ assertEquals(restoredAutoAddTiles,
+ mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER));
+ }
+
+ @Test
+ public void testSettingRestoredWithTilesRemovedInSource_noAutoAddedInTarget() {
+ verify(mBroadcastDispatcher)
+ .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+
+ // These tiles were present in the original device
+ String restoredTiles = "saver,internet,cast";
+ Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, restoredTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent);
+
+ // And these tiles have been auto-added in the original device
+ // (no auto-added before restore)
+ String restoredAutoAddTiles = "work";
+ Intent restoreAutoAddTilesIntent =
+ makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, null, restoredAutoAddTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent);
+
+ // Then, remove work tile
+ verify(mQSHost).removeTiles(List.of("work"));
+ assertEquals(restoredAutoAddTiles,
+ mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER));
+ }
+
+ @Test
+ public void testSettingRestoredWithTilesRemovedInSource_sameAutoAddedinTarget() {
+ verify(mBroadcastDispatcher)
+ .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+
+ // These tiles were present in the original device
+ String restoredTiles = "saver,internet,cast";
+ Intent restoreTilesIntent =
+ makeRestoreIntent(Secure.QS_TILES, "saver, internet, cast, work", restoredTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent);
+
+ // And these tiles have been auto-added in the original device
+ // (no auto-added before restore)
+ String restoredAutoAddTiles = "work";
+ Intent restoreAutoAddTilesIntent =
+ makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, "work", restoredAutoAddTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent);
+
+ // Then, remove work tile
+ verify(mQSHost).removeTiles(List.of("work"));
+ assertEquals(restoredAutoAddTiles,
+ mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER));
+ }
+
+ @Test
+ public void testSettingRestoredWithTilesRemovedInSource_othersAutoAddedinTarget() {
+ verify(mBroadcastDispatcher)
+ .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+
+ // These tiles were present in the original device
+ String restoredTiles = "saver,internet,cast";
+ Intent restoreTilesIntent =
+ makeRestoreIntent(Secure.QS_TILES, "saver, internet, cast, work", restoredTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent);
+
+ // And these tiles have been auto-added in the original device
+ // (no auto-added before restore)
+ String restoredAutoAddTiles = "work";
+ Intent restoreAutoAddTilesIntent =
+ makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, "inversion", restoredAutoAddTiles);
+ mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent);
+
+ // Then, remove work tile
+ verify(mQSHost).removeTiles(List.of("work"));
+
+ String setting = mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER);
+ assertEquals(2, setting.split(",").length);
+ assertTrue(setting.contains("work"));
+ assertTrue(setting.contains("inversion"));
+ }
+
+
+ private Intent makeRestoreIntent(
+ String settingName, String previousValue, String restoredValue) {
+ Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED);
+ intent.putExtra(Intent.EXTRA_SETTING_NAME, settingName);
+ intent.putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, previousValue);
+ intent.putExtra(Intent.EXTRA_SETTING_NEW_VALUE, restoredValue);
+ return intent;
+ }
+
+ private AutoAddTracker createAutoAddTracker(int user) {
+ // Null handler wil dispatch sync.
+ return new AutoAddTracker(
+ mSecureSettings,
+ mBroadcastDispatcher,
+ mQSHost,
+ mDumpManager,
+ null,
+ mBackgroundExecutor,
+ user
+ );
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index c9dc7ad..6c7f770 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -18,14 +18,11 @@
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static junit.framework.TestCase.assertFalse;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -68,12 +65,12 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -121,7 +118,6 @@
private UiEventLogger mUiEventLogger;
@Mock
private UserTracker mUserTracker;
- @Mock
private SecureSettings mSecureSettings;
@Mock
private CustomTileStatePersister mCustomTileStatePersister;
@@ -135,14 +131,15 @@
MockitoAnnotations.initMocks(this);
mLooper = TestableLooper.get(this);
mHandler = new Handler(mLooper.getLooper());
+
+ mSecureSettings = new FakeSettings();
+ mSecureSettings.putStringForUser(
+ QSTileHost.TILES_SETTING, "", "", false, mUserTracker.getUserId(), false);
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
mSecureSettings, mCustomTileStatePersister);
setUpTileFactory();
-
- when(mSecureSettings.getStringForUser(eq(QSTileHost.TILES_SETTING), anyInt()))
- .thenReturn("");
}
private void setUpTileFactory() {
@@ -365,6 +362,16 @@
.removeState(new TileServiceKey(CUSTOM_TILE, mQSTileHost.getUserId()));
}
+ @Test
+ public void testRemoveTiles() {
+ List<String> tiles = List.of("spec1", "spec2", "spec3");
+ mQSTileHost.saveTilesToSettings(tiles);
+
+ mQSTileHost.removeTiles(List.of("spec1", "spec2"));
+
+ assertEquals(List.of("spec3"), mQSTileHost.mTileSpecs);
+ }
+
private class TestQSTileHost extends QSTileHost {
TestQSTileHost(Context context, StatusBarIconController iconController,
QSFactory defaultFactory, Handler mainHandler, Looper bgLooper,
@@ -390,14 +397,11 @@
@Override
void saveTilesToSettings(List<String> tileSpecs) {
super.saveTilesToSettings(tileSpecs);
-
- ArgumentCaptor<String> specs = ArgumentCaptor.forClass(String.class);
- verify(mSecureSettings, atLeastOnce()).putStringForUser(eq(QSTileHost.TILES_SETTING),
- specs.capture(), isNull(), eq(false), anyInt(), eq(true));
-
// After tiles are changed, make sure to call onTuningChanged with the new setting if it
// changed
- onTuningChanged(TILES_SETTING, specs.getValue());
+ String specs = mSecureSettings.getStringForUser(
+ QSTileHost.TILES_SETTING, mUserTracker.getUserId());
+ onTuningChanged(TILES_SETTING, specs);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index a70c2be..8922b43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -228,7 +228,9 @@
mTile.handleClick(null /* view */);
mTestableLooper.processAllMessages();
- verify(mSpiedContext).startActivity(mIntentCaptor.capture());
+ verify(mActivityStarter).startActivity(mIntentCaptor.capture(), eq(true) /* dismissShade */,
+ (ActivityLaunchAnimator.Controller) eq(null),
+ eq(true) /* showOverLockscreenWhenLocked */);
Intent nextStartedIntent = mIntentCaptor.getValue();
String walletClassName = "com.android.systemui.wallet.ui.WalletActivity";
@@ -246,7 +248,8 @@
mTestableLooper.processAllMessages();
verify(mActivityStarter).startActivity(mIntentCaptor.capture(), eq(true) /* dismissShade */,
- (ActivityLaunchAnimator.Controller) eq(null));
+ (ActivityLaunchAnimator.Controller) eq(null),
+ eq(true) /* showOverLockscreenWhenLocked */);
Intent nextStartedIntent = mIntentCaptor.getValue();
String walletClassName = "com.android.systemui.wallet.ui.WalletActivity";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index f5ce673..4c90063 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -111,6 +111,7 @@
private static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName("com.android.foo",
"bar");
+ private String mKeyguardTryFingerprintMsg;
private String mDisclosureWithOrganization;
private String mDisclosureGeneric;
private String mFinancedDisclosureWithOrganization;
@@ -182,6 +183,7 @@
mContext.addMockSystemService(UserManager.class, mUserManager);
mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class));
+ mKeyguardTryFingerprintMsg = mContext.getString(R.string.keyguard_try_fingerprint);
mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name,
ORGANIZATION_NAME);
mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic);
@@ -677,6 +679,34 @@
verifyTransientMessage(message);
}
+ @Test
+ public void faceAuthMessageSuppressed() {
+ createController();
+ String faceHelpMsg = "Face auth help message";
+
+ // GIVEN state of showing message when keyguard screen is on
+ when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
+ when(mKeyguardUpdateMonitor.isScreenOn()).thenReturn(true);
+
+ // GIVEN fingerprint is also running (not udfps)
+ when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isUdfpsAvailable()).thenReturn(false);
+
+ mController.setVisible(true);
+
+ // WHEN a face help message comes in
+ mController.getKeyguardCallback().onBiometricHelp(
+ KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, faceHelpMsg,
+ BiometricSourceType.FACE);
+
+ // THEN "try fingerprint" message appears (and not the face help message)
+ verifyTransientMessage(mKeyguardTryFingerprintMsg);
+
+ // THEN the face help message is still announced for a11y
+ verify(mIndicationAreaBottom).announceForAccessibility(eq(faceHelpMsg));
+ }
+
private void sendUpdateDisclosureBroadcast() {
mBroadcastReceiver.onReceive(mContext, new Intent());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
new file mode 100644
index 0000000..97fe25d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar
+
+import android.testing.AndroidTestingRunner
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.function.Consumer
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class LightRevealScrimTest : SysuiTestCase() {
+
+ private lateinit var scrim: LightRevealScrim
+ private var isOpaque = false
+
+ @Before
+ fun setUp() {
+ scrim = LightRevealScrim(context, null)
+ scrim.isScrimOpaqueChangedListener = Consumer { opaque ->
+ isOpaque = opaque
+ }
+ scrim.revealAmount = 0f
+ assertTrue("Scrim is not opaque in initial setup", scrim.isScrimOpaque)
+ }
+
+ @Test
+ fun testAlphaSetsOpaque() {
+ scrim.alpha = 0.5f
+ assertFalse("Scrim is opaque even though alpha is set", scrim.isScrimOpaque)
+ }
+
+ @Test
+ fun testVisibilitySetsOpaque() {
+ scrim.visibility = View.INVISIBLE
+ assertFalse("Scrim is opaque even though it's invisible", scrim.isScrimOpaque)
+ scrim.visibility = View.GONE
+ assertFalse("Scrim is opaque even though it's gone", scrim.isScrimOpaque)
+ }
+
+ @Test
+ fun testRevealSetsOpaque() {
+ scrim.revealAmount = 0.5f
+ assertFalse("Scrim is opaque even though it's revealed", scrim.isScrimOpaque)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 7c045c1..a7b1446 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -69,7 +69,6 @@
@Mock private lateinit var root: View
@Mock private lateinit var viewRootImpl: ViewRootImpl
@Mock private lateinit var windowToken: IBinder
- @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation
@Mock private lateinit var shadeAnimation: NotificationShadeDepthController.DepthAnimation
@Mock private lateinit var brightnessSpring: NotificationShadeDepthController.DepthAnimation
@Mock private lateinit var listener: NotificationShadeDepthController.DepthListener
@@ -89,10 +88,10 @@
`when`(root.isAttachedToWindow).thenReturn(true)
`when`(statusBarStateController.state).then { statusBarState }
`when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer ->
- (answer.arguments[0] as Float * maxBlur).toInt()
+ answer.arguments[0] as Float * maxBlur.toFloat()
}
- `when`(blurUtils.ratioOfBlurRadius(anyInt())).then { answer ->
- answer.arguments[0] as Int / maxBlur.toFloat()
+ `when`(blurUtils.ratioOfBlurRadius(anyFloat())).then { answer ->
+ answer.arguments[0] as Float / maxBlur.toFloat()
}
`when`(blurUtils.supportsBlursOnWindows()).thenReturn(true)
`when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
@@ -102,7 +101,6 @@
statusBarStateController, blurUtils, biometricUnlockController,
keyguardStateController, choreographer, wallpaperManager,
notificationShadeWindowController, dozeParameters, dumpManager)
- notificationShadeDepthController.shadeSpring = shadeSpring
notificationShadeDepthController.shadeAnimation = shadeAnimation
notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring
notificationShadeDepthController.root = root
@@ -123,7 +121,6 @@
fun onPanelExpansionChanged_apliesBlur_ifShade() {
notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */,
false /* tracking */)
- verify(shadeSpring).animateTo(eq(maxBlur), any())
verify(shadeAnimation).animateTo(eq(maxBlur), any())
}
@@ -172,12 +169,10 @@
@Test
fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() {
onPanelExpansionChanged_apliesBlur_ifShade()
- clearInvocations(shadeSpring)
- clearInvocations(shadeAnimation)
+ clearInvocations(choreographer)
statusBarState = StatusBarState.KEYGUARD
statusBarStateListener.onStateChanged(statusBarState)
- verify(shadeSpring).animateTo(eq(0), any())
verify(shadeAnimation).animateTo(eq(0), any())
}
@@ -186,7 +181,7 @@
notificationShadeDepthController.qsPanelExpansion = 1f
notificationShadeDepthController.onPanelExpansionChanged(0.5f, tracking = false)
notificationShadeDepthController.updateBlurCallback.doFrame(0)
- verify(blurUtils).applyBlur(any(), eq(maxBlur / 2), eq(false))
+ verify(blurUtils).applyBlur(any(), anyInt(), eq(false))
}
@Test
@@ -207,10 +202,10 @@
fun setFullShadeTransition_appliesBlur_onlyIfSupported() {
reset(blurUtils)
`when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer ->
- (answer.arguments[0] as Float * maxBlur).toInt()
+ answer.arguments[0] as Float * maxBlur
}
- `when`(blurUtils.ratioOfBlurRadius(anyInt())).then { answer ->
- answer.arguments[0] as Int / maxBlur.toFloat()
+ `when`(blurUtils.ratioOfBlurRadius(anyFloat())).then { answer ->
+ answer.arguments[0] as Float / maxBlur.toFloat()
}
`when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
`when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
@@ -239,16 +234,16 @@
@Test
fun updateBlurCallback_setsBlur_whenExpanded() {
- `when`(shadeSpring.radius).thenReturn(maxBlur)
- `when`(shadeAnimation.radius).thenReturn(maxBlur)
+ notificationShadeDepthController.onPanelExpansionChanged(1f, false)
+ `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
notificationShadeDepthController.updateBlurCallback.doFrame(0)
verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
}
@Test
fun updateBlurCallback_ignoreShadeBlurUntilHidden_overridesZoom() {
- `when`(shadeSpring.radius).thenReturn(maxBlur)
- `when`(shadeAnimation.radius).thenReturn(maxBlur)
+ notificationShadeDepthController.onPanelExpansionChanged(1f, false)
+ `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
notificationShadeDepthController.blursDisabledForAppLaunch = true
notificationShadeDepthController.updateBlurCallback.doFrame(0)
verify(blurUtils).applyBlur(any(), eq(0), eq(false))
@@ -293,8 +288,8 @@
// Brightness mirror is fully visible
`when`(brightnessSpring.ratio).thenReturn(1f)
// And shade is blurred
- `when`(shadeSpring.radius).thenReturn(maxBlur)
- `when`(shadeAnimation.radius).thenReturn(maxBlur)
+ notificationShadeDepthController.onPanelExpansionChanged(1f, false)
+ `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
notificationShadeDepthController.updateBlurCallback.doFrame(0)
verify(notificationShadeWindowController).setBackgroundBlurRadius(eq(0))
@@ -304,10 +299,8 @@
@Test
fun ignoreShadeBlurUntilHidden_whennNull_ignoresIfShadeHasNoBlur() {
- `when`(shadeSpring.radius).thenReturn(0)
- `when`(shadeAnimation.radius).thenReturn(0)
+ `when`(shadeAnimation.radius).thenReturn(0f)
notificationShadeDepthController.blursDisabledForAppLaunch = true
- verify(shadeSpring, never()).animateTo(anyInt(), any())
verify(shadeAnimation, never()).animateTo(anyInt(), any())
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
index ddd7854..90b8a74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java
@@ -146,7 +146,7 @@
mNotificationShadeWindowController.attach();
clearInvocations(mWindowManager);
- mNotificationShadeWindowController.setLightRevealScrimAmount(0f);
+ mNotificationShadeWindowController.setLightRevealScrimOpaque(true);
verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) == 0).isTrue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
index 6c1a3c9..bcc257d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
@@ -16,6 +16,11 @@
package com.android.systemui.statusbar.phone;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -55,6 +60,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -91,6 +98,10 @@
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
+ mInteractionEventHandlerCaptor;
+ private NotificationShadeWindowView.InteractionEventHandler mInteractionEventHandler;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -147,4 +158,49 @@
verify(mDragDownHelper).onTouchEvent(ev);
ev.recycle();
}
+
+ @Test
+ public void testInterceptTouchWhenShowingAltAuth() {
+ captureInteractionEventHandler();
+
+ // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(true);
+ when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
+
+ // THEN we should intercept touch
+ assertTrue(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
+ }
+
+ @Test
+ public void testNoInterceptTouch() {
+ captureInteractionEventHandler();
+
+ // WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(false);
+ when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
+
+ // THEN we shouldn't intercept touch
+ assertFalse(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
+ }
+
+ @Test
+ public void testHandleTouchEventWhenShowingAltAuth() {
+ captureInteractionEventHandler();
+
+ // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(true);
+ when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
+
+ // THEN we should handle the touch
+ assertTrue(mInteractionEventHandler.handleTouchEvent(mock(MotionEvent.class)));
+ }
+
+ private void captureInteractionEventHandler() {
+ verify(mView).setInteractionEventHandler(mInteractionEventHandlerCaptor.capture());
+ mInteractionEventHandler = mInteractionEventHandlerCaptor.getValue();
+
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 30fc13b..1953903 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1139,6 +1139,19 @@
}
@Test
+ public void testNotificationTransparency_unnocclusion() {
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.setUnocclusionAnimationRunning(true);
+
+ assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.0f, /* expansion */ 0.0f);
+ assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.0f, /* expansion */ 1.0f);
+
+ // Verify normal behavior after
+ mScrimController.setUnocclusionAnimationRunning(false);
+ assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.4f);
+ }
+
+ @Test
public void testNotificationTransparency_inKeyguardState() {
mScrimController.transitionTo(ScrimState.KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index c39a906..38f36bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -64,6 +64,8 @@
import java.util.Optional;
+import dagger.Lazy;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -103,6 +105,8 @@
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Mock
private KeyguardMessageArea mKeyguardMessageArea;
+ @Mock
+ private Lazy<ShadeController> mShadeController;
private WakefulnessLifecycle mWakefulnessLifecycle;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -133,7 +137,8 @@
mKeyguardBouncerFactory,
mWakefulnessLifecycle,
mUnlockedScreenOffAnimationController,
- mKeyguardMessageAreaFactory);
+ mKeyguardMessageAreaFactory,
+ mShadeController);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
mNotificationPanelView, mBiometrucUnlockController,
mNotificationContainer, mBypassController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 079a621..71c61ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -141,10 +141,11 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.concurrency.MessageRouterImpl;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
-import com.android.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
@@ -271,7 +272,9 @@
@Mock private OperatorNameViewController mOperatorNameViewController;
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
private ShadeController mShadeController;
- private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
+ private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
+ private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock);
private InitController mInitController = new InitController();
@Before
@@ -436,6 +439,9 @@
mLockscreenTransitionController,
mFeatureFlags,
mKeyguardUnlockAnimationController,
+ new Handler(TestableLooper.get(this).getLooper()),
+ mMainExecutor,
+ new MessageRouterImpl(mMainExecutor),
mWallpaperManager,
mUnlockedScreenOffAnimationController,
Optional.of(mStartingSurface),
@@ -702,7 +708,7 @@
} catch (RemoteException e) {
fail();
}
- TestableLooper.get(this).processAllMessages();
+ mMainExecutor.runAllReady();
}
@Test
@@ -721,7 +727,7 @@
} catch (RemoteException e) {
fail();
}
- TestableLooper.get(this).processAllMessages();
+ mMainExecutor.runAllReady();
}
@Test
@@ -739,7 +745,7 @@
} catch (RemoteException e) {
fail();
}
- TestableLooper.get(this).processAllMessages();
+ mMainExecutor.runAllReady();
}
@Test
@@ -754,15 +760,6 @@
}
@Test
- @RunWithLooper(setAsMainLooper = true)
- public void testUpdateKeyguardState_DoesNotCrash() {
- mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
- when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(
- new SparseArray<>());
- mStatusBar.onStateChanged(StatusBarState.SHADE);
- }
-
- @Test
public void testFingerprintNotification_UpdatesScrims() {
mStatusBar.notifyBiometricAuthModeChanged();
verify(mScrimController).transitionTo(any(), any());
@@ -778,6 +775,30 @@
}
@Test
+ public void testTransitionLaunch_goesToUnlocked() {
+ mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+ mStatusBar.showKeyguardImpl();
+
+ // Starting a pulse should change the scrim controller to the pulsing state
+ when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true);
+ when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(true);
+ mStatusBar.updateScrimController();
+ verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any());
+ }
+
+ @Test
+ public void testTransitionLaunch_noPreview_doesntGoUnlocked() {
+ mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+ mStatusBar.showKeyguardImpl();
+
+ // Starting a pulse should change the scrim controller to the pulsing state
+ when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true);
+ when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(false);
+ mStatusBar.updateScrimController();
+ verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD));
+ }
+
+ @Test
public void testSetOccluded_propagatesToScrimController() {
mStatusBar.setOccluded(true);
verify(mScrimController).setKeyguardOccluded(eq(true));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 57198db..4a5770d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -238,7 +238,7 @@
mNetworkController.setNoNetworksAvailable(false);
setWifiStateForVcn(true, testSsid);
setWifiLevelForVcn(0);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
+ verifyLastMobileDataIndicatorsForVcn(true, 0, TelephonyIcons.ICON_CWF, false);
mNetworkController.setNoNetworksAvailable(true);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
@@ -246,11 +246,11 @@
setConnectivityViaCallbackInNetworkControllerForVcn(
NetworkCapabilities.TRANSPORT_CELLULAR, true, true, mVcnTransportInfo);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
+ verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, true);
setConnectivityViaCallbackInNetworkControllerForVcn(
NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
+ verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, false);
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 8961a5a..5ecdfe4 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1719,11 +1719,10 @@
if (client == null) {
return;
}
- Log.w(TAG, "Speaker client died");
- if (removeCommunicationRouteClient(client.getBinder(), false)
- != null) {
- onUpdateCommunicationRoute("onCommunicationRouteClientDied");
- }
+ Log.w(TAG, "Communication client died");
+ setCommunicationRouteForClient(
+ client.getBinder(), client.getPid(), null, BtHelper.SCO_MODE_UNDEFINED,
+ "onCommunicationRouteClientDied");
}
/**
diff --git a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
index 54a4ad4..23f0ffb 100644
--- a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
@@ -52,11 +52,11 @@
public BroadcastRadioService(Context context) {
super(context);
- mHal1 = new com.android.server.broadcastradio.hal1.BroadcastRadioService();
+ mHal1 = new com.android.server.broadcastradio.hal1.BroadcastRadioService(mLock);
mV1Modules = mHal1.loadModules();
OptionalInt max = mV1Modules.stream().mapToInt(RadioManager.ModuleProperties::getId).max();
mHal2 = new com.android.server.broadcastradio.hal2.BroadcastRadioService(
- max.isPresent() ? max.getAsInt() + 1 : 0);
+ max.isPresent() ? max.getAsInt() + 1 : 0, mLock);
}
@Override
@@ -111,7 +111,7 @@
synchronized (mLock) {
if (!mHal2.hasAnyModules()) {
Slog.i(TAG, "There are no HAL 2.x modules registered");
- return new AnnouncementAggregator(listener);
+ return new AnnouncementAggregator(listener, mLock);
}
return mHal2.addAnnouncementListener(enabledTypes, listener);
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java
index e8ac547..5da6032 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java
@@ -17,16 +17,9 @@
package com.android.server.broadcastradio.hal1;
import android.annotation.NonNull;
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.radio.IRadioService;
import android.hardware.radio.ITuner;
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
-import android.os.ParcelableException;
-
-import com.android.server.SystemService;
import java.util.List;
import java.util.Objects;
@@ -37,7 +30,7 @@
*/
private final long mNativeContext = nativeInit();
- private final Object mLock = new Object();
+ private final Object mLock;
@Override
protected void finalize() throws Throwable {
@@ -51,6 +44,14 @@
private native Tuner nativeOpenTuner(long nativeContext, int moduleId,
RadioManager.BandConfig config, boolean withAudio, ITunerCallback callback);
+ /**
+ * Constructor. should pass
+ * {@code com.android.server.broadcastradio.BroadcastRadioService#mLock} for lock.
+ */
+ public BroadcastRadioService(@NonNull Object lock) {
+ mLock = lock;
+ }
+
public @NonNull List<RadioManager.ModuleProperties> loadModules() {
synchronized (mLock) {
return Objects.requireNonNull(nativeLoadModules(mNativeContext));
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java b/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
index 5307697..42e296f 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
@@ -35,7 +35,7 @@
public class AnnouncementAggregator extends ICloseHandle.Stub {
private static final String TAG = "BcRadio2Srv.AnnAggr";
- private final Object mLock = new Object();
+ private final Object mLock;
@NonNull private final IAnnouncementListener mListener;
private final IBinder.DeathRecipient mDeathRecipient = new DeathRecipient();
@@ -45,8 +45,9 @@
@GuardedBy("mLock")
private boolean mIsClosed = false;
- public AnnouncementAggregator(@NonNull IAnnouncementListener listener) {
+ public AnnouncementAggregator(@NonNull IAnnouncementListener listener, @NonNull Object lock) {
mListener = Objects.requireNonNull(listener);
+ mLock = Objects.requireNonNull(lock);
try {
listener.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 5e79c59..5c07f76 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -42,7 +42,7 @@
public class BroadcastRadioService {
private static final String TAG = "BcRadio2Srv";
- private final Object mLock = new Object();
+ private final Object mLock;
@GuardedBy("mLock")
private int mNextModuleId = 0;
@@ -68,7 +68,7 @@
moduleId = mNextModuleId;
}
- RadioModule module = RadioModule.tryLoadingModule(moduleId, serviceName);
+ RadioModule module = RadioModule.tryLoadingModule(moduleId, serviceName, mLock);
if (module == null) {
return;
}
@@ -116,8 +116,9 @@
}
};
- public BroadcastRadioService(int nextModuleId) {
+ public BroadcastRadioService(int nextModuleId, Object lock) {
mNextModuleId = nextModuleId;
+ mLock = lock;
try {
IServiceManager manager = IServiceManager.getService();
if (manager == null) {
@@ -174,7 +175,7 @@
public ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes,
@NonNull IAnnouncementListener listener) {
- AnnouncementAggregator aggregator = new AnnouncementAggregator(listener);
+ AnnouncementAggregator aggregator = new AnnouncementAggregator(listener, mLock);
boolean anySupported = false;
synchronized (mLock) {
for (RadioModule module : mModules.values()) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index b7e188c..ef7f4c9 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -58,7 +58,7 @@
@NonNull private final IBroadcastRadio mService;
@NonNull public final RadioManager.ModuleProperties mProperties;
- private final Object mLock = new Object();
+ private final Object mLock;
@NonNull private final Handler mHandler;
@GuardedBy("mLock")
@@ -132,13 +132,15 @@
@VisibleForTesting
RadioModule(@NonNull IBroadcastRadio service,
- @NonNull RadioManager.ModuleProperties properties) {
+ @NonNull RadioManager.ModuleProperties properties, @NonNull Object lock) {
mProperties = Objects.requireNonNull(properties);
mService = Objects.requireNonNull(service);
+ mLock = Objects.requireNonNull(lock);
mHandler = new Handler(Looper.getMainLooper());
}
- public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName) {
+ public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName,
+ Object lock) {
try {
IBroadcastRadio service = IBroadcastRadio.getService(fqName);
if (service == null) return null;
@@ -156,7 +158,7 @@
RadioManager.ModuleProperties prop = Convert.propertiesFromHal(idx, fqName,
service.getProperties(), amfmConfig.value, dabConfig.value);
- return new RadioModule(service, prop);
+ return new RadioModule(service, prop, lock);
} catch (RemoteException ex) {
Slog.e(TAG, "failed to load module " + fqName, ex);
return null;
@@ -178,7 +180,8 @@
});
mHalTunerSession = Objects.requireNonNull(hwSession.value);
}
- TunerSession tunerSession = new TunerSession(this, mHalTunerSession, userCb);
+ TunerSession tunerSession = new TunerSession(this, mHalTunerSession, userCb,
+ mLock);
mAidlTunerSessions.add(tunerSession);
// Propagate state to new client. Note: These callbacks are invoked while holding mLock
@@ -377,7 +380,7 @@
}
};
- synchronized (mService) {
+ synchronized (mLock) {
mService.registerAnnouncementListener(enabledList, hwListener, (result, closeHnd) -> {
halResult.value = result;
hwCloseHandle.value = closeHnd;
@@ -401,7 +404,7 @@
if (id == 0) throw new IllegalArgumentException("Image ID is missing");
byte[] rawImage;
- synchronized (mService) {
+ synchronized (mLock) {
List<Byte> rawList = Utils.maybeRethrow(() -> mService.getImage(id));
rawImage = new byte[rawList.size()];
for (int i = 0; i < rawList.size(); i++) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 7ab3bdd..200af2f 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -40,7 +40,7 @@
private static final String TAG = "BcRadio2Srv.session";
private static final String kAudioDeviceName = "Radio tuner source";
- private final Object mLock = new Object();
+ private final Object mLock;
private final RadioModule mModule;
private final ITunerSession mHwSession;
@@ -53,10 +53,12 @@
private RadioManager.BandConfig mDummyConfig = null;
TunerSession(@NonNull RadioModule module, @NonNull ITunerSession hwSession,
- @NonNull android.hardware.radio.ITunerCallback callback) {
+ @NonNull android.hardware.radio.ITunerCallback callback,
+ @NonNull Object lock) {
mModule = Objects.requireNonNull(module);
mHwSession = Objects.requireNonNull(hwSession);
mCallback = Objects.requireNonNull(callback);
+ mLock = Objects.requireNonNull(lock);
}
@Override
diff --git a/services/core/java/com/android/server/devicestate/DeviceState.java b/services/core/java/com/android/server/devicestate/DeviceState.java
index e693bcc..7fe24ff 100644
--- a/services/core/java/com/android/server/devicestate/DeviceState.java
+++ b/services/core/java/com/android/server/devicestate/DeviceState.java
@@ -19,11 +19,14 @@
import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -39,6 +42,19 @@
* @see DeviceStateManagerService
*/
public final class DeviceState {
+ /**
+ * Flag that indicates sticky requests should be cancelled when this device state becomes the
+ * base device state.
+ */
+ public static final int FLAG_CANCEL_STICKY_REQUESTS = 1 << 0;
+
+ /** @hide */
+ @IntDef(prefix = {"FLAG_"}, flag = true, value = {
+ FLAG_CANCEL_STICKY_REQUESTS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeviceStateFlags {}
+
/** Unique identifier for the device state. */
@IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE)
private final int mIdentifier;
@@ -47,14 +63,19 @@
@NonNull
private final String mName;
+ @DeviceStateFlags
+ private final int mFlags;
+
public DeviceState(
@IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
- @NonNull String name) {
+ @NonNull String name,
+ @DeviceStateFlags int flags) {
Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE, MAXIMUM_DEVICE_STATE,
"identifier");
mIdentifier = identifier;
mName = name;
+ mFlags = flags;
}
/** Returns the unique identifier for the device state. */
@@ -69,6 +90,11 @@
return mName;
}
+ @DeviceStateFlags
+ public int getFlags() {
+ return mFlags;
+ }
+
@Override
public String toString() {
return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\'' + '}';
@@ -80,11 +106,12 @@
if (o == null || getClass() != o.getClass()) return false;
DeviceState that = (DeviceState) o;
return mIdentifier == that.mIdentifier
- && Objects.equals(mName, that.mName);
+ && Objects.equals(mName, that.mName)
+ && mFlags == that.mFlags;
}
@Override
public int hashCode() {
- return Objects.hash(mIdentifier, mName);
+ return Objects.hash(mIdentifier, mName, mFlags);
}
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index a8b0994..383b392 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -19,8 +19,13 @@
import static android.Manifest.permission.CONTROL_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES;
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
+import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
+import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
+
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,12 +35,12 @@
import android.hardware.devicestate.IDeviceStateManager;
import android.hardware.devicestate.IDeviceStateManagerCallback;
import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
-import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -43,14 +48,21 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.policy.DeviceStatePolicyImpl;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.WindowProcessController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
+import java.util.WeakHashMap;
/**
* A system service that manages the state of a device with user-configurable hardware like a
@@ -81,10 +93,20 @@
private static final boolean DEBUG = false;
private final Object mLock = new Object();
+ // Internal system service thread used to dispatch calls to the policy and to registered
+ // callbacks though its handler (mHandler). Provides a guarantee of callback order when
+ // leveraging mHandler and also enables posting messages with the service lock held.
+ private final HandlerThread mHandlerThread;
+ private final Handler mHandler;
@NonNull
private final DeviceStatePolicy mDeviceStatePolicy;
@NonNull
private final BinderService mBinderService;
+ @NonNull
+ private final OverrideRequestController mOverrideRequestController;
+ @VisibleForTesting
+ @NonNull
+ public ActivityTaskManagerInternal mActivityTaskManagerInternal;
// All supported device states keyed by identifier.
@GuardedBy("mLock")
@@ -109,17 +131,16 @@
@NonNull
private Optional<DeviceState> mBaseState = Optional.empty();
+ // The current active override request. When set the device state specified here will take
+ // precedence over mBaseState.
+ @GuardedBy("mLock")
+ @NonNull
+ private Optional<OverrideRequest> mActiveOverride = Optional.empty();
+
// List of processes registered to receive notifications about changes to device state and
// request status indexed by process id.
@GuardedBy("mLock")
private final SparseArray<ProcessRecord> mProcessRecords = new SparseArray<>();
- // List of override requests with the highest precedence request at the end.
- @GuardedBy("mLock")
- private final ArrayList<OverrideRequestRecord> mRequestRecords = new ArrayList<>();
- // Set of override requests that are pending a call to notifyStatusIfNeeded() to be notified
- // of a change in status.
- @GuardedBy("mLock")
- private final ArraySet<OverrideRequestRecord> mRequestsPendingStatusChange = new ArraySet<>();
public DeviceStateManagerService(@NonNull Context context) {
this(context, new DeviceStatePolicyImpl(context));
@@ -128,9 +149,17 @@
@VisibleForTesting
DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
super(context);
+ // Service thread assigned THREAD_PRIORITY_DISPLAY because this service indirectly drives
+ // display (on/off) and window (position) events through its callbacks.
+ mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_DISPLAY, false /* allowIo */);
+ mHandlerThread.start();
+ mHandler = mHandlerThread.getThreadHandler();
+ mOverrideRequestController = new OverrideRequestController(
+ this::onOverrideRequestStatusChangedLocked);
mDeviceStatePolicy = policy;
mDeviceStatePolicy.getDeviceStateProvider().setListener(new DeviceStateProviderListener());
mBinderService = new BinderService();
+ mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
@Override
@@ -138,6 +167,11 @@
publishBinderService(Context.DEVICE_STATE_SERVICE, mBinderService);
}
+ @VisibleForTesting
+ Handler getHandler() {
+ return mHandler;
+ }
+
/**
* Returns the current state the system is in. Note that the system may be in the process of
* configuring a different state.
@@ -191,12 +225,10 @@
@NonNull
Optional<DeviceState> getOverrideState() {
synchronized (mLock) {
- if (mRequestRecords.isEmpty()) {
- return Optional.empty();
+ if (mActiveOverride.isPresent()) {
+ return getStateLocked(mActiveOverride.get().getRequestedState());
}
-
- OverrideRequestRecord topRequest = mRequestRecords.get(mRequestRecords.size() - 1);
- return Optional.of(topRequest.mRequestedState);
+ return Optional.empty();
}
}
@@ -247,43 +279,41 @@
}
private void updateSupportedStates(DeviceState[] supportedDeviceStates) {
- boolean updatedPendingState;
- boolean hasBaseState;
synchronized (mLock) {
final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked();
+ // Whether or not at least one device state has the flag FLAG_CANCEL_STICKY_REQUESTS
+ // set. If set to true, the OverrideRequestController will be configured to allow sticky
+ // requests.
+ boolean hasTerminalDeviceState = false;
mDeviceStates.clear();
for (int i = 0; i < supportedDeviceStates.length; i++) {
DeviceState state = supportedDeviceStates[i];
+ if ((state.getFlags() & DeviceState.FLAG_CANCEL_STICKY_REQUESTS) != 0) {
+ hasTerminalDeviceState = true;
+ }
mDeviceStates.put(state.getIdentifier(), state);
}
+ mOverrideRequestController.setStickyRequestsAllowed(hasTerminalDeviceState);
+
final int[] newStateIdentifiers = getSupportedStateIdentifiersLocked();
if (Arrays.equals(oldStateIdentifiers, newStateIdentifiers)) {
return;
}
- final int requestSize = mRequestRecords.size();
- for (int i = 0; i < requestSize; i++) {
- OverrideRequestRecord request = mRequestRecords.get(i);
- if (!isSupportedStateLocked(request.mRequestedState.getIdentifier())) {
- request.setStatusLocked(OverrideRequestRecord.STATUS_CANCELED);
- }
+ mOverrideRequestController.handleNewSupportedStates(newStateIdentifiers);
+ updatePendingStateLocked();
+
+ if (!mPendingState.isPresent()) {
+ // If the change in the supported states didn't result in a change of the pending
+ // state commitPendingState() will never be called and the callbacks will never be
+ // notified of the change.
+ notifyDeviceStateInfoChangedAsync();
}
- updatedPendingState = updatePendingStateLocked();
- hasBaseState = mBaseState.isPresent();
+ mHandler.post(this::notifyPolicyIfNeeded);
}
-
- if (hasBaseState && !updatedPendingState) {
- // If the change in the supported states didn't result in a change of the pending state
- // commitPendingState() will never be called and the callbacks will never be notified
- // of the change.
- notifyDeviceStateInfoChanged();
- }
-
- notifyRequestsOfStatusChangeIfNeeded();
- notifyPolicyIfNeeded();
}
/**
@@ -311,7 +341,6 @@
* @see #isSupportedStateLocked(int)
*/
private void setBaseState(int identifier) {
- boolean updatedPendingState;
synchronized (mLock) {
final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
if (!baseStateOptional.isPresent()) {
@@ -325,26 +354,21 @@
}
mBaseState = Optional.of(baseState);
- final int requestSize = mRequestRecords.size();
- for (int i = 0; i < requestSize; i++) {
- OverrideRequestRecord request = mRequestRecords.get(i);
- if ((request.mFlags & FLAG_CANCEL_WHEN_BASE_CHANGES) > 0) {
- request.setStatusLocked(OverrideRequestRecord.STATUS_CANCELED);
- }
+ if ((baseState.getFlags() & DeviceState.FLAG_CANCEL_STICKY_REQUESTS) != 0) {
+ mOverrideRequestController.cancelStickyRequests();
+ }
+ mOverrideRequestController.handleBaseStateChanged();
+ updatePendingStateLocked();
+
+ if (!mPendingState.isPresent()) {
+ // If the change in base state didn't result in a change of the pending state
+ // commitPendingState() will never be called and the callbacks will never be
+ // notified of the change.
+ notifyDeviceStateInfoChangedAsync();
}
- updatedPendingState = updatePendingStateLocked();
+ mHandler.post(this::notifyPolicyIfNeeded);
}
-
- if (!updatedPendingState) {
- // If the change in base state didn't result in a change of the pending state
- // commitPendingState() will never be called and the callbacks will never be notified
- // of the change.
- notifyDeviceStateInfoChanged();
- }
-
- notifyRequestsOfStatusChangeIfNeeded();
- notifyPolicyIfNeeded();
}
/**
@@ -362,8 +386,8 @@
}
final DeviceState stateToConfigure;
- if (!mRequestRecords.isEmpty()) {
- stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState;
+ if (mActiveOverride.isPresent()) {
+ stateToConfigure = getStateLocked(mActiveOverride.get().getRequestedState()).get();
} else if (mBaseState.isPresent()
&& isSupportedStateLocked(mBaseState.get().getIdentifier())) {
// Base state could have recently become unsupported after a change in supported states.
@@ -429,108 +453,106 @@
* </p>
*/
private void commitPendingState() {
- // Update the current state.
synchronized (mLock) {
final DeviceState newState = mPendingState.get();
if (DEBUG) {
Slog.d(TAG, "Committing state: " + newState);
}
- if (!mRequestRecords.isEmpty()) {
- final OverrideRequestRecord topRequest =
- mRequestRecords.get(mRequestRecords.size() - 1);
- if (topRequest.mRequestedState.getIdentifier() == newState.getIdentifier()) {
- // The top request could have come in while the service was awaiting callback
- // from the policy. In that case we only set it to active if it matches the
- // current committed state, otherwise it will be set to active when its
- // requested state is committed.
- topRequest.setStatusLocked(OverrideRequestRecord.STATUS_ACTIVE);
- }
- }
-
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_STATE_CHANGED,
newState.getIdentifier(), !mCommittedState.isPresent());
mCommittedState = Optional.of(newState);
mPendingState = Optional.empty();
updatePendingStateLocked();
+
+ // Notify callbacks of a change.
+ notifyDeviceStateInfoChangedAsync();
+
+ // The top request could have come in while the service was awaiting callback
+ // from the policy. In that case we only set it to active if it matches the
+ // current committed state, otherwise it will be set to active when its
+ // requested state is committed.
+ OverrideRequest activeRequest = mActiveOverride.orElse(null);
+ if (activeRequest != null
+ && activeRequest.getRequestedState() == newState.getIdentifier()) {
+ ProcessRecord processRecord = mProcessRecords.get(activeRequest.getPid());
+ if (processRecord != null) {
+ processRecord.notifyRequestActiveAsync(activeRequest.getToken());
+ }
+ }
+
+ // Try to configure the next state if needed.
+ mHandler.post(this::notifyPolicyIfNeeded);
}
-
- // Notify callbacks of a change.
- notifyDeviceStateInfoChanged();
-
- // Notify the top request that it's active.
- notifyRequestsOfStatusChangeIfNeeded();
-
- // Try to configure the next state if needed.
- notifyPolicyIfNeeded();
}
- private void notifyDeviceStateInfoChanged() {
- if (Thread.holdsLock(mLock)) {
- throw new IllegalStateException(
- "Attempting to notify callbacks with service lock held.");
- }
-
- // Grab the lock and copy the process records and the current info.
- ArrayList<ProcessRecord> registeredProcesses;
- DeviceStateInfo info;
+ private void notifyDeviceStateInfoChangedAsync() {
synchronized (mLock) {
if (mProcessRecords.size() == 0) {
return;
}
- registeredProcesses = new ArrayList<>();
+ ArrayList<ProcessRecord> registeredProcesses = new ArrayList<>();
for (int i = 0; i < mProcessRecords.size(); i++) {
registeredProcesses.add(mProcessRecords.valueAt(i));
}
- info = getDeviceStateInfoLocked();
- }
+ DeviceStateInfo info = getDeviceStateInfoLocked();
- // After releasing the lock, send the notifications out.
- for (int i = 0; i < registeredProcesses.size(); i++) {
- registeredProcesses.get(i).notifyDeviceStateInfoAsync(info);
+ for (int i = 0; i < registeredProcesses.size(); i++) {
+ registeredProcesses.get(i).notifyDeviceStateInfoAsync(info);
+ }
}
}
- /**
- * Notifies all dirty requests (requests that have a change in status, but have not yet been
- * notified) that their status has changed.
- */
- private void notifyRequestsOfStatusChangeIfNeeded() {
- if (Thread.holdsLock(mLock)) {
- throw new IllegalStateException(
- "Attempting to notify requests with service lock held.");
- }
-
- ArraySet<OverrideRequestRecord> dirtyRequests;
- synchronized (mLock) {
- if (mRequestsPendingStatusChange.isEmpty()) {
- return;
+ private void onOverrideRequestStatusChangedLocked(@NonNull OverrideRequest request,
+ @OverrideRequestController.RequestStatus int status) {
+ if (status == STATUS_ACTIVE) {
+ mActiveOverride = Optional.of(request);
+ } else if (status == STATUS_SUSPENDED || status == STATUS_CANCELED) {
+ if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
+ mActiveOverride = Optional.empty();
}
-
- dirtyRequests = new ArraySet<>(mRequestsPendingStatusChange);
- mRequestsPendingStatusChange.clear();
+ } else {
+ throw new IllegalArgumentException("Unknown request status: " + status);
}
- // After releasing the lock, send the notifications out.
- for (int i = 0; i < dirtyRequests.size(); i++) {
- dirtyRequests.valueAt(i).notifyStatusIfNeeded();
+ boolean updatedPendingState = updatePendingStateLocked();
+
+ ProcessRecord processRecord = mProcessRecords.get(request.getPid());
+ if (processRecord == null) {
+ // If the process is no longer registered with the service, for example if it has died,
+ // there is no need to notify it of a change in request status.
+ mHandler.post(this::notifyPolicyIfNeeded);
+ return;
}
+
+ if (status == STATUS_ACTIVE) {
+ if (!updatedPendingState && !mPendingState.isPresent()) {
+ // If the pending state was not updated and there is not currently a pending state
+ // then this newly active request will never be notified of a change in state.
+ // Schedule the notification now.
+ processRecord.notifyRequestActiveAsync(request.getToken());
+ }
+ } else if (status == STATUS_SUSPENDED) {
+ processRecord.notifyRequestSuspendedAsync(request.getToken());
+ } else {
+ processRecord.notifyRequestCanceledAsync(request.getToken());
+ }
+
+ mHandler.post(this::notifyPolicyIfNeeded);
}
private void registerProcess(int pid, IDeviceStateManagerCallback callback) {
- DeviceStateInfo currentInfo;
- ProcessRecord record;
- // Grab the lock to register the callback and get the current state.
synchronized (mLock) {
if (mProcessRecords.contains(pid)) {
throw new SecurityException("The calling process has already registered an"
+ " IDeviceStateManagerCallback.");
}
- record = new ProcessRecord(callback, pid);
+ ProcessRecord record = new ProcessRecord(callback, pid, this::handleProcessDied,
+ mHandlerThread.getThreadHandler());
try {
callback.asBinder().linkToDeath(record, 0);
} catch (RemoteException ex) {
@@ -538,34 +560,21 @@
}
mProcessRecords.put(pid, record);
- currentInfo = mCommittedState.isPresent() ? getDeviceStateInfoLocked() : null;
- }
-
- if (currentInfo != null) {
- // If there is not a committed state we'll wait to notify the process of the initial
- // value.
- record.notifyDeviceStateInfoAsync(currentInfo);
+ DeviceStateInfo currentInfo = mCommittedState.isPresent()
+ ? getDeviceStateInfoLocked() : null;
+ if (currentInfo != null) {
+ // If there is not a committed state we'll wait to notify the process of the initial
+ // value.
+ record.notifyDeviceStateInfoAsync(currentInfo);
+ }
}
}
private void handleProcessDied(ProcessRecord processRecord) {
synchronized (mLock) {
- // Cancel all requests from this process.
- final int requestCount = processRecord.mRequestRecords.size();
- for (int i = 0; i < requestCount; i++) {
- final OverrideRequestRecord request = processRecord.mRequestRecords.valueAt(i);
- // Cancel the request but don't mark it as dirty since there's no need to send
- // notifications if the process has died.
- request.setStatusLocked(OverrideRequestRecord.STATUS_CANCELED,
- false /* markDirty */);
- }
-
mProcessRecords.remove(processRecord.mPid);
-
- updatePendingStateLocked();
+ mOverrideRequestController.handleProcessDied(processRecord.mPid);
}
-
- notifyPolicyIfNeeded();
}
private void requestStateInternal(int state, int flags, int callingPid,
@@ -577,7 +586,7 @@
+ " has no registered callback.");
}
- if (processRecord.mRequestRecords.get(token) != null) {
+ if (mOverrideRequestController.hasRequest(token)) {
throw new IllegalStateException("Request has already been made for the supplied"
+ " token: " + token);
}
@@ -588,27 +597,9 @@
+ " is not supported.");
}
- OverrideRequestRecord topRecord = mRequestRecords.isEmpty()
- ? null : mRequestRecords.get(mRequestRecords.size() - 1);
- if (topRecord != null) {
- topRecord.setStatusLocked(OverrideRequestRecord.STATUS_SUSPENDED);
- }
-
- final OverrideRequestRecord request =
- new OverrideRequestRecord(processRecord, token, deviceState.get(), flags);
- mRequestRecords.add(request);
- processRecord.mRequestRecords.put(request.mToken, request);
-
- final boolean updatedPendingState = updatePendingStateLocked();
- if (!updatedPendingState && !mPendingState.isPresent()) {
- // We don't set the status of the new request to ACTIVE if the request updated the
- // pending state as it will be set in commitPendingState().
- request.setStatusLocked(OverrideRequestRecord.STATUS_ACTIVE, true /* markDirty */);
- }
+ OverrideRequest request = new OverrideRequest(token, callingPid, state, flags);
+ mOverrideRequestController.addRequest(request);
}
-
- notifyRequestsOfStatusChangeIfNeeded();
- notifyPolicyIfNeeded();
}
private void cancelRequestInternal(int callingPid, @NonNull IBinder token) {
@@ -619,18 +610,8 @@
+ " has no registered callback.");
}
- OverrideRequestRecord request = processRecord.mRequestRecords.get(token);
- if (request == null) {
- throw new IllegalStateException("No known request for the given token");
- }
-
- request.setStatusLocked(OverrideRequestRecord.STATUS_CANCELED);
-
- updatePendingStateLocked();
+ mOverrideRequestController.cancelRequest(token);
}
-
- notifyRequestsOfStatusChangeIfNeeded();
- notifyPolicyIfNeeded();
}
private void dumpInternal(PrintWriter pw) {
@@ -650,16 +631,7 @@
pw.println(" " + i + ": mPid=" + processRecord.mPid);
}
- final int requestCount = mRequestRecords.size();
- pw.println();
- pw.println("Override requests: size=" + requestCount);
- for (int i = 0; i < requestCount; i++) {
- OverrideRequestRecord requestRecord = mRequestRecords.get(i);
- pw.println(" " + i + ": mPid=" + requestRecord.mProcessRecord.mPid
- + ", mRequestedState=" + requestRecord.mRequestedState
- + ", mFlags=" + requestRecord.mFlags
- + ", mStatus=" + requestRecord.statusToString(requestRecord.mStatus));
- }
+ mOverrideRequestController.dumpInternal(pw);
}
}
@@ -683,142 +655,107 @@
}
}
- private final class ProcessRecord implements IBinder.DeathRecipient {
+ private static final class ProcessRecord implements IBinder.DeathRecipient {
+ public interface DeathListener {
+ void onProcessDied(ProcessRecord record);
+ }
+
+ private static final int STATUS_ACTIVE = 0;
+
+ private static final int STATUS_SUSPENDED = 1;
+
+ private static final int STATUS_CANCELED = 2;
+
+ @IntDef(prefix = {"STATUS_"}, value = {
+ STATUS_ACTIVE,
+ STATUS_SUSPENDED,
+ STATUS_CANCELED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface RequestStatus {}
+
private final IDeviceStateManagerCallback mCallback;
private final int mPid;
+ private final DeathListener mDeathListener;
+ private final Handler mHandler;
- private final ArrayMap<IBinder, OverrideRequestRecord> mRequestRecords = new ArrayMap<>();
+ private final WeakHashMap<IBinder, Integer> mLastNotifiedStatus = new WeakHashMap<>();
- ProcessRecord(IDeviceStateManagerCallback callback, int pid) {
+ ProcessRecord(IDeviceStateManagerCallback callback, int pid, DeathListener deathListener,
+ Handler handler) {
mCallback = callback;
mPid = pid;
+ mDeathListener = deathListener;
+ mHandler = handler;
}
@Override
public void binderDied() {
- handleProcessDied(this);
+ mDeathListener.onProcessDied(this);
}
public void notifyDeviceStateInfoAsync(@NonNull DeviceStateInfo info) {
- try {
- mCallback.onDeviceStateInfoChanged(info);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that device state changed.",
- ex);
- }
- }
-
- public void notifyRequestActiveAsync(OverrideRequestRecord request) {
- try {
- mCallback.onRequestActive(request.mToken);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
- ex);
- }
- }
-
- public void notifyRequestSuspendedAsync(OverrideRequestRecord request) {
- try {
- mCallback.onRequestSuspended(request.mToken);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
- ex);
- }
- }
-
- public void notifyRequestCanceledAsync(OverrideRequestRecord request) {
- try {
- mCallback.onRequestCanceled(request.mToken);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
- ex);
- }
- }
- }
-
- /** A record describing a request to override the state of the device. */
- private final class OverrideRequestRecord {
- public static final int STATUS_UNKNOWN = 0;
- public static final int STATUS_ACTIVE = 1;
- public static final int STATUS_SUSPENDED = 2;
- public static final int STATUS_CANCELED = 3;
-
- @Nullable
- public String statusToString(int status) {
- switch (status) {
- case STATUS_ACTIVE:
- return "ACTIVE";
- case STATUS_SUSPENDED:
- return "SUSPENDED";
- case STATUS_CANCELED:
- return "CANCELED";
- case STATUS_UNKNOWN:
- return "UNKNOWN";
- default:
- return null;
- }
- }
-
- private final ProcessRecord mProcessRecord;
- @NonNull
- private final IBinder mToken;
- @NonNull
- private final DeviceState mRequestedState;
- private final int mFlags;
-
- private int mStatus = STATUS_UNKNOWN;
- private int mLastNotifiedStatus = STATUS_UNKNOWN;
-
- OverrideRequestRecord(@NonNull ProcessRecord processRecord, @NonNull IBinder token,
- @NonNull DeviceState requestedState, int flags) {
- mProcessRecord = processRecord;
- mToken = token;
- mRequestedState = requestedState;
- mFlags = flags;
- }
-
- public void setStatusLocked(int status) {
- setStatusLocked(status, true /* markDirty */);
- }
-
- public void setStatusLocked(int status, boolean markDirty) {
- if (mStatus != status) {
- if (mStatus == STATUS_CANCELED) {
- throw new IllegalStateException(
- "Can not alter the status of a request after set to CANCELED.");
+ mHandler.post(() -> {
+ try {
+ mCallback.onDeviceStateInfoChanged(info);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid + " that device state changed.",
+ ex);
}
-
- mStatus = status;
-
- if (mStatus == STATUS_CANCELED) {
- mRequestRecords.remove(this);
- mProcessRecord.mRequestRecords.remove(mToken);
- }
-
- if (markDirty) {
- mRequestsPendingStatusChange.add(this);
- }
- }
+ });
}
- public void notifyStatusIfNeeded() {
- int stateToReport;
- synchronized (mLock) {
- if (mLastNotifiedStatus == mStatus) {
- return;
+ public void notifyRequestActiveAsync(IBinder token) {
+ @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
+ if (lastStatus != null
+ && (lastStatus == STATUS_ACTIVE || lastStatus == STATUS_CANCELED)) {
+ return;
+ }
+
+ mLastNotifiedStatus.put(token, STATUS_ACTIVE);
+ mHandler.post(() -> {
+ try {
+ mCallback.onRequestActive(token);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
+ ex);
}
+ });
+ }
- stateToReport = mStatus;
- mLastNotifiedStatus = mStatus;
+ public void notifyRequestSuspendedAsync(IBinder token) {
+ @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
+ if (lastStatus != null
+ && (lastStatus == STATUS_SUSPENDED || lastStatus == STATUS_CANCELED)) {
+ return;
}
- if (stateToReport == STATUS_ACTIVE) {
- mProcessRecord.notifyRequestActiveAsync(this);
- } else if (stateToReport == STATUS_SUSPENDED) {
- mProcessRecord.notifyRequestSuspendedAsync(this);
- } else if (stateToReport == STATUS_CANCELED) {
- mProcessRecord.notifyRequestCanceledAsync(this);
+ mLastNotifiedStatus.put(token, STATUS_SUSPENDED);
+ mHandler.post(() -> {
+ try {
+ mCallback.onRequestSuspended(token);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
+ ex);
+ }
+ });
+ }
+
+ public void notifyRequestCanceledAsync(IBinder token) {
+ @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
+ if (lastStatus != null && lastStatus == STATUS_CANCELED) {
+ return;
}
+
+ mLastNotifiedStatus.put(token, STATUS_CANCELED);
+ mHandler.post(() -> {
+ try {
+ mCallback.onRequestCanceled(token);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
+ ex);
+ }
+ });
}
}
@@ -848,14 +785,21 @@
@Override // Binder call
public void requestState(IBinder token, int state, int flags) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to request device state.");
+ final int callingPid = Binder.getCallingPid();
+ // Allow top processes to request a device state change
+ // If the calling process ID is not the top app, then we check if this process
+ // holds a permission to CONTROL_DEVICE_STATE
+ final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
+ if (topApp.getPid() != callingPid) {
+ getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
+ "Permission required to request device state, "
+ + "or the call must come from the top focused app.");
+ }
if (token == null) {
throw new IllegalArgumentException("Request token must not be null.");
}
- final int callingPid = Binder.getCallingPid();
final long callingIdentity = Binder.clearCallingIdentity();
try {
requestStateInternal(state, flags, callingPid, token);
@@ -866,14 +810,21 @@
@Override // Binder call
public void cancelRequest(IBinder token) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to clear requested device state.");
+ final int callingPid = Binder.getCallingPid();
+ // Allow top processes to cancel a device state change
+ // If the calling process ID is not the top app, then we check if this process
+ // holds a permission to CONTROL_DEVICE_STATE
+ final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
+ if (topApp.getPid() != callingPid) {
+ getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
+ "Permission required to cancel device state, "
+ + "or the call must come from the top focused app.");
+ }
if (token == null) {
throw new IllegalArgumentException("Request token must not be null.");
}
- final int callingPid = Binder.getCallingPid();
final long callingIdentity = Binder.clearCallingIdentity();
try {
cancelRequestInternal(callingPid, token);
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequest.java b/services/core/java/com/android/server/devicestate/OverrideRequest.java
new file mode 100644
index 0000000..35a4c84
--- /dev/null
+++ b/services/core/java/com/android/server/devicestate/OverrideRequest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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.devicestate;
+
+import android.hardware.devicestate.DeviceStateRequest;
+import android.os.IBinder;
+
+/**
+ * A request to override the state managed by {@link DeviceStateManagerService}.
+ *
+ * @see OverrideRequestController
+ */
+final class OverrideRequest {
+ private final IBinder mToken;
+ private final int mPid;
+ private final int mRequestedState;
+ @DeviceStateRequest.RequestFlags
+ private final int mFlags;
+
+ OverrideRequest(IBinder token, int pid, int requestedState,
+ @DeviceStateRequest.RequestFlags int flags) {
+ mToken = token;
+ mPid = pid;
+ mRequestedState = requestedState;
+ mFlags = flags;
+ }
+
+ IBinder getToken() {
+ return mToken;
+ }
+
+ int getPid() {
+ return mPid;
+ }
+
+ int getRequestedState() {
+ return mRequestedState;
+ }
+
+ @DeviceStateRequest.RequestFlags
+ int getFlags() {
+ return mFlags;
+ }
+}
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
new file mode 100644
index 0000000..05c9eb2
--- /dev/null
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2021 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.devicestate;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.devicestate.DeviceStateRequest;
+import android.os.IBinder;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the lifecycle of override requests.
+ * <p>
+ * New requests are added with {@link #addRequest(OverrideRequest)} and are kept active until
+ * either:
+ * <ul>
+ * <li>A new request is added with {@link #addRequest(OverrideRequest)}, in which case the
+ * request will become suspended.</li>
+ * <li>The request is cancelled with {@link #cancelRequest(IBinder)} or as a side effect
+ * of other methods calls, such as {@link #handleProcessDied(int)}.</li>
+ * </ul>
+ */
+final class OverrideRequestController {
+ static final int STATUS_UNKNOWN = 0;
+ /**
+ * The request is the top-most request.
+ */
+ static final int STATUS_ACTIVE = 1;
+ /**
+ * The request is still present but is being superseded by another request.
+ */
+ static final int STATUS_SUSPENDED = 2;
+ /**
+ * The request is not longer valid.
+ */
+ static final int STATUS_CANCELED = 3;
+
+ @IntDef(prefix = {"STATUS_"}, value = {
+ STATUS_UNKNOWN,
+ STATUS_ACTIVE,
+ STATUS_SUSPENDED,
+ STATUS_CANCELED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface RequestStatus {}
+
+ static String statusToString(@RequestStatus int status) {
+ switch (status) {
+ case STATUS_ACTIVE:
+ return "ACTIVE";
+ case STATUS_SUSPENDED:
+ return "SUSPENDED";
+ case STATUS_CANCELED:
+ return "CANCELED";
+ case STATUS_UNKNOWN:
+ return "UNKNOWN";
+ }
+ throw new IllegalArgumentException("Unknown status: " + status);
+ }
+
+ private final StatusChangeListener mListener;
+ private final List<OverrideRequest> mTmpRequestsToCancel = new ArrayList<>();
+
+ // List of override requests with the most recent override request at the end.
+ private final ArrayList<OverrideRequest> mRequests = new ArrayList<>();
+
+ private boolean mStickyRequestsAllowed;
+ // List of override requests that have outlived their process and will only be cancelled through
+ // a call to cancelStickyRequests().
+ private final ArrayList<OverrideRequest> mStickyRequests = new ArrayList<>();
+
+ OverrideRequestController(@NonNull StatusChangeListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Sets sticky requests as either allowed or disallowed. When sticky requests are allowed a call
+ * to {@link #handleProcessDied(int)} will not result in the request being cancelled
+ * immediately. Instead, the request will be marked sticky and must be cancelled with a call
+ * to {@link #cancelStickyRequests()}.
+ */
+ void setStickyRequestsAllowed(boolean stickyRequestsAllowed) {
+ mStickyRequestsAllowed = stickyRequestsAllowed;
+ if (!mStickyRequestsAllowed) {
+ cancelStickyRequests();
+ }
+ }
+
+ /**
+ * Adds a request to the top of the stack and notifies the listener of all changes to request
+ * status as a result of this operation.
+ */
+ void addRequest(@NonNull OverrideRequest request) {
+ mRequests.add(request);
+ mListener.onStatusChanged(request, STATUS_ACTIVE);
+
+ if (mRequests.size() > 1) {
+ OverrideRequest prevRequest = mRequests.get(mRequests.size() - 2);
+ mListener.onStatusChanged(prevRequest, STATUS_SUSPENDED);
+ }
+ }
+
+ /**
+ * Cancels the request with the specified {@code token} and notifies the listener of all changes
+ * to request status as a result of this operation.
+ */
+ void cancelRequest(@NonNull IBinder token) {
+ int index = getRequestIndex(token);
+ if (index == -1) {
+ return;
+ }
+
+ OverrideRequest request = mRequests.remove(index);
+ if (index == mRequests.size() && mRequests.size() > 0) {
+ // We removed the current active request so we need to set the new active request
+ // before cancelling this request.
+ OverrideRequest newTop = getLast(mRequests);
+ mListener.onStatusChanged(newTop, STATUS_ACTIVE);
+ }
+ mListener.onStatusChanged(request, STATUS_CANCELED);
+ }
+
+ /**
+ * Cancels all requests that are currently marked sticky and notifies the listener of all
+ * changes to request status as a result of this operation.
+ *
+ * @see #setStickyRequestsAllowed(boolean)
+ */
+ void cancelStickyRequests() {
+ mTmpRequestsToCancel.clear();
+ mTmpRequestsToCancel.addAll(mStickyRequests);
+ cancelRequestsLocked(mTmpRequestsToCancel);
+ }
+
+ /**
+ * Returns {@code true} if this controller is current managing a request with the specified
+ * {@code token}, {@code false} otherwise.
+ */
+ boolean hasRequest(@NonNull IBinder token) {
+ return getRequestIndex(token) != -1;
+ }
+
+ /**
+ * Notifies the controller that the process with the specified {@code pid} has died. The
+ * controller will notify the listener of all changes to request status as a result of this
+ * operation.
+ */
+ void handleProcessDied(int pid) {
+ if (mRequests.isEmpty()) {
+ return;
+ }
+
+ mTmpRequestsToCancel.clear();
+ OverrideRequest prevActiveRequest = getLast(mRequests);
+ for (OverrideRequest request : mRequests) {
+ if (request.getPid() == pid) {
+ mTmpRequestsToCancel.add(request);
+ }
+ }
+
+ if (mStickyRequestsAllowed) {
+ // Do not cancel the requests now because sticky requests are allowed. These
+ // requests will be cancelled on a call to cancelStickyRequests().
+ mStickyRequests.addAll(mTmpRequestsToCancel);
+ return;
+ }
+
+ cancelRequestsLocked(mTmpRequestsToCancel);
+ }
+
+ /**
+ * Notifies the controller that the base state has changed. The controller will notify the
+ * listener of all changes to request status as a result of this change.
+ *
+ * @return {@code true} if calling this method has lead to a new active request, {@code false}
+ * otherwise.
+ */
+ boolean handleBaseStateChanged() {
+ if (mRequests.isEmpty()) {
+ return false;
+ }
+
+ mTmpRequestsToCancel.clear();
+ OverrideRequest prevActiveRequest = getLast(mRequests);
+ for (int i = 0; i < mRequests.size(); i++) {
+ OverrideRequest request = mRequests.get(i);
+ if ((request.getFlags() & DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES) != 0) {
+ mTmpRequestsToCancel.add(request);
+ }
+ }
+
+ final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
+ return newActiveRequest;
+ }
+
+ /**
+ * Notifies the controller that the set of supported states has changed. The controller will
+ * notify the listener of all changes to request status as a result of this change.
+ *
+ * @return {@code true} if calling this method has lead to a new active request, {@code false}
+ * otherwise.
+ */
+ boolean handleNewSupportedStates(int[] newSupportedStates) {
+ if (mRequests.isEmpty()) {
+ return false;
+ }
+
+ mTmpRequestsToCancel.clear();
+ for (int i = 0; i < mRequests.size(); i++) {
+ OverrideRequest request = mRequests.get(i);
+ if (!contains(newSupportedStates, request.getRequestedState())) {
+ mTmpRequestsToCancel.add(request);
+ }
+ }
+
+ final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
+ return newActiveRequest;
+ }
+
+ void dumpInternal(PrintWriter pw) {
+ final int requestCount = mRequests.size();
+ pw.println();
+ pw.println("Override requests: size=" + requestCount);
+ for (int i = 0; i < requestCount; i++) {
+ OverrideRequest overrideRequest = mRequests.get(i);
+ int status = (i == requestCount - 1) ? STATUS_ACTIVE : STATUS_SUSPENDED;
+ pw.println(" " + i + ": mPid=" + overrideRequest.getPid()
+ + ", mRequestedState=" + overrideRequest.getRequestedState()
+ + ", mFlags=" + overrideRequest.getFlags()
+ + ", mStatus=" + statusToString(status));
+ }
+ }
+
+ /**
+ * Handles cancelling a set of requests. If the set of requests to cancel will lead to a new
+ * request becoming active this request will also be notified of its change in state.
+ *
+ * @return {@code true} if calling this method has lead to a new active request, {@code false}
+ * otherwise.
+ */
+ private boolean cancelRequestsLocked(List<OverrideRequest> requestsToCancel) {
+ if (requestsToCancel.isEmpty()) {
+ return false;
+ }
+
+ OverrideRequest prevActiveRequest = getLast(mRequests);
+ boolean causedNewRequestToBecomeActive = false;
+ mRequests.removeAll(requestsToCancel);
+ mStickyRequests.removeAll(requestsToCancel);
+ if (!mRequests.isEmpty()) {
+ OverrideRequest newActiveRequest = getLast(mRequests);
+ if (newActiveRequest != prevActiveRequest) {
+ mListener.onStatusChanged(newActiveRequest, STATUS_ACTIVE);
+ causedNewRequestToBecomeActive = true;
+ }
+ }
+
+ for (int i = 0; i < requestsToCancel.size(); i++) {
+ mListener.onStatusChanged(requestsToCancel.get(i), STATUS_CANCELED);
+ }
+ return causedNewRequestToBecomeActive;
+ }
+
+ private int getRequestIndex(@NonNull IBinder token) {
+ final int numberOfRequests = mRequests.size();
+ if (numberOfRequests == 0) {
+ return -1;
+ }
+
+ for (int i = 0; i < numberOfRequests; i++) {
+ OverrideRequest request = mRequests.get(i);
+ if (request.getToken() == token) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Nullable
+ private static <T> T getLast(List<T> list) {
+ return list.size() > 0 ? list.get(list.size() - 1) : null;
+ }
+
+ private static boolean contains(int[] array, int value) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public interface StatusChangeListener {
+ /**
+ * Notifies the listener of a change in request status. If a change within the controller
+ * causes one request to become active and one to become either suspended or cancelled, this
+ * method is guaranteed to be called with the active request first before the suspended or
+ * cancelled request.
+ */
+ void onStatusChanged(@NonNull OverrideRequest request, @RequestStatus int newStatus);
+ }
+}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1108937..abbe13a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2122,7 +2122,6 @@
private void ignoreProximitySensorUntilChangedInternal() {
if (!mIgnoreProximityUntilChanged
- && mPowerRequest.useProximitySensor
&& mProximity == PROXIMITY_POSITIVE) {
// Only ignore if it is still reporting positive (near)
mIgnoreProximityUntilChanged = true;
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 6af1923..147050c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -411,7 +411,7 @@
* Updates the state of the screen and backlight asynchronously on a separate thread.
*/
private final class PhotonicModulator extends Thread {
- private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
+ private static final int INITIAL_SCREEN_STATE = Display.STATE_UNKNOWN;
private static final float INITIAL_BACKLIGHT_FLOAT = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private final Object mLock = new Object();
@@ -494,7 +494,9 @@
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
- if (!stateChanged && !backlightChanged) {
+ boolean valid = state != Display.STATE_UNKNOWN && !Float.isNaN(brightnessState);
+ boolean changed = stateChanged || backlightChanged;
+ if (!valid || !changed) {
try {
mLock.wait();
} catch (InterruptedException ex) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c477546..140098d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7220,6 +7220,7 @@
t.traceEnd();
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
+ mPermissionManager.readLegacyPermissionStateTEMP();
if (!mOnlyCore && mFirstBoot) {
requestCopyPreoptedFiles(mInjector);
@@ -7635,7 +7636,6 @@
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
- mPermissionManager.readLegacyPermissionStateTEMP();
// If the build fingerprint has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index fcbf40e..62d6717 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1664,6 +1664,19 @@
mContext.enforceCallingPermission(permission, message);
}
+ private void verifyCallerUserId(@UserIdInt int userId) {
+ if (isCallerSystem()) {
+ return; // no check
+ }
+
+ final int callingUid = injectBinderCallingUid();
+
+ // Otherwise, make sure the arguments are valid.
+ if (UserHandle.getUserId(callingUid) != userId) {
+ throw new SecurityException("Invalid user-ID");
+ }
+ }
+
private void verifyCaller(@NonNull String packageName, @UserIdInt int userId) {
Preconditions.checkStringNotEmpty(packageName, "packageName");
@@ -2847,6 +2860,8 @@
@Override
public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
+ verifyCallerUserId(callingUserId);
+
final long token = injectClearCallingIdentity();
try {
return mShortcutRequestPinProcessor
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 1133faa..c11ffb4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1215,6 +1215,7 @@
private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
@NonNull String permName) {
+ final String permissionPackageName;
final boolean isImmutablyRestrictedPermission;
synchronized (mLock) {
final Permission bp = mRegistry.getPermission(permName);
@@ -1222,15 +1223,25 @@
Slog.w(TAG, "No such permissions: " + permName);
return false;
}
+ permissionPackageName = bp.getPackageName();
isImmutablyRestrictedPermission = bp.isHardOrSoftRestricted()
&& bp.isImmutablyRestricted();
}
+
+ final int callingUid = getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ if (mPackageManagerInt.filterAppAccess(permissionPackageName, callingUid, callingUserId)) {
+ EventLog.writeEvent(0x534e4554, "186404356", callingUid, permName);
+ return false;
+ }
+
if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Cannot modify allowlisting of an immutably "
+ "restricted permission: " + permName);
}
+
return true;
}
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index edd5f5f..ff6511f 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -41,6 +41,7 @@
import com.android.server.devicestate.DeviceStateProvider;
import com.android.server.policy.devicestate.config.Conditions;
import com.android.server.policy.devicestate.config.DeviceStateConfig;
+import com.android.server.policy.devicestate.config.Flags;
import com.android.server.policy.devicestate.config.LidSwitchCondition;
import com.android.server.policy.devicestate.config.NumericRange;
import com.android.server.policy.devicestate.config.SensorCondition;
@@ -87,7 +88,7 @@
@VisibleForTesting
static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE,
- "DEFAULT");
+ "DEFAULT", 0 /* flags */);
private static final String VENDOR_CONFIG_FILE_PATH = "etc/devicestate/";
private static final String DATA_CONFIG_FILE_PATH = "system/devicestate/";
@@ -131,7 +132,26 @@
config.getDeviceState()) {
final int state = stateConfig.getIdentifier().intValue();
final String name = stateConfig.getName() == null ? "" : stateConfig.getName();
- deviceStateList.add(new DeviceState(state, name));
+
+ int flags = 0;
+ final Flags configFlags = stateConfig.getFlags();
+ if (configFlags != null) {
+ List<String> configFlagStrings = configFlags.getFlag();
+ for (int i = 0; i < configFlagStrings.size(); i++) {
+ final String configFlagString = configFlagStrings.get(i);
+ switch (configFlagString) {
+ case "FLAG_CANCEL_STICKY_REQUESTS":
+ flags |= DeviceState.FLAG_CANCEL_STICKY_REQUESTS;
+ break;
+ default:
+ Slog.w(TAG, "Parsed unknown flag with name: "
+ + configFlagString);
+ break;
+ }
+ }
+ }
+
+ deviceStateList.add(new DeviceState(state, name, flags));
final Conditions condition = stateConfig.getConditions();
conditionsList.add(condition);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 139ab0c..45f5daa 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -484,6 +484,7 @@
int mLidNavigationAccessibility;
int mShortPressOnPowerBehavior;
int mLongPressOnPowerBehavior;
+ long mLongPressOnPowerAssistantTimeoutMs;
int mVeryLongPressOnPowerBehavior;
int mDoublePressOnPowerBehavior;
int mTriplePressOnPowerBehavior;
@@ -732,6 +733,9 @@
Settings.Global.POWER_BUTTON_LONG_PRESS), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.POWER_BUTTON_VERY_LONG_PRESS), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -1732,6 +1736,8 @@
com.android.internal.R.integer.config_shortPressOnPowerBehavior);
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ mLongPressOnPowerAssistantTimeoutMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerDurationMs);
mVeryLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_veryLongPressOnPowerBehavior);
mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
@@ -1955,7 +1961,7 @@
*/
private final class PowerKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
PowerKeyRule(int gestures) {
- super(KEYCODE_POWER, gestures);
+ super(mContext, KEYCODE_POWER, gestures);
}
@Override
@@ -1970,6 +1976,15 @@
}
@Override
+ long getLongPressTimeoutMs() {
+ if (getResolvedLongPressOnPowerBehavior() == LONG_PRESS_POWER_ASSISTANT) {
+ return mLongPressOnPowerAssistantTimeoutMs;
+ } else {
+ return super.getLongPressTimeoutMs();
+ }
+ }
+
+ @Override
void onLongPress(long eventTime) {
if (mSingleKeyGestureDetector.beganFromNonInteractive()
&& !mSupportLongPressPowerWhenNonInteractive) {
@@ -1997,7 +2012,7 @@
*/
private final class BackKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
BackKeyRule(int gestures) {
- super(KEYCODE_BACK, gestures);
+ super(mContext, KEYCODE_BACK, gestures);
}
@Override
@@ -2017,7 +2032,7 @@
}
private void initSingleKeyGestureRules() {
- mSingleKeyGestureDetector = new SingleKeyGestureDetector(mContext);
+ mSingleKeyGestureDetector = new SingleKeyGestureDetector();
int powerKeyGestures = 0;
if (hasVeryLongPressOnPowerBehavior()) {
@@ -2115,6 +2130,11 @@
Settings.Global.POWER_BUTTON_LONG_PRESS,
mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior));
+ mLongPressOnPowerAssistantTimeoutMs = Settings.Global.getLong(
+ mContext.getContentResolver(),
+ Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
+ mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerDurationMs));
mVeryLongPressOnPowerBehavior = Settings.Global.getInt(resolver,
Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
mContext.getResources().getInteger(
@@ -5331,6 +5351,9 @@
pw.print("mLongPressOnPowerBehavior=");
pw.println(longPressOnPowerBehaviorToString(mLongPressOnPowerBehavior));
pw.print(prefix);
+ pw.print("mLongPressOnPowerAssistantTimeoutMs=");
+ pw.println(mLongPressOnPowerAssistantTimeoutMs);
+ pw.print(prefix);
pw.print("mVeryLongPressOnPowerBehavior=");
pw.println(veryLongPressOnPowerBehaviorToString(mVeryLongPressOnPowerBehavior));
pw.print(prefix);
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index 1ef2bf9..6fee69b 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -44,9 +44,6 @@
private static final int MSG_KEY_VERY_LONG_PRESS = 1;
private static final int MSG_KEY_DELAYED_PRESS = 2;
- private final long mLongPressTimeout;
- private final long mVeryLongPressTimeout;
-
private volatile int mKeyPressCounter;
private boolean mBeganFromNonInteractive = false;
@@ -86,12 +83,19 @@
* </pre>
*/
abstract static class SingleKeyRule {
+
private final int mKeyCode;
private final int mSupportedGestures;
+ private final long mDefaultLongPressTimeout;
+ private final long mDefaultVeryLongPressTimeout;
- SingleKeyRule(int keyCode, @KeyGestureFlag int supportedGestures) {
+ SingleKeyRule(Context context, int keyCode, @KeyGestureFlag int supportedGestures) {
mKeyCode = keyCode;
mSupportedGestures = supportedGestures;
+ mDefaultLongPressTimeout =
+ ViewConfiguration.get(context).getDeviceGlobalActionKeyTimeout();
+ mDefaultVeryLongPressTimeout = context.getResources().getInteger(
+ com.android.internal.R.integer.config_veryLongPressTimeout);
}
/**
@@ -134,10 +138,28 @@
*/
void onMultiPress(long downTime, int count) {}
/**
+ * Returns the timeout in milliseconds for a long press.
+ *
+ * If multipress is also supported, this should always be greater than the multipress
+ * timeout. If very long press is supported, this should always be less than the very long
+ * press timeout.
+ */
+ long getLongPressTimeoutMs() {
+ return mDefaultLongPressTimeout;
+ }
+ /**
* Callback when long press has been detected.
*/
void onLongPress(long eventTime) {}
/**
+ * Returns the timeout in milliseconds for a very long press.
+ *
+ * If long press is supported, this should always be longer than the long press timeout.
+ */
+ long getVeryLongPressTimeoutMs() {
+ return mDefaultVeryLongPressTimeout;
+ }
+ /**
* Callback when very long press has been detected.
*/
void onVeryLongPress(long eventTime) {}
@@ -151,10 +173,7 @@
}
}
- public SingleKeyGestureDetector(Context context) {
- mLongPressTimeout = ViewConfiguration.get(context).getDeviceGlobalActionKeyTimeout();
- mVeryLongPressTimeout = context.getResources().getInteger(
- com.android.internal.R.integer.config_veryLongPressTimeout);
+ public SingleKeyGestureDetector() {
mHandler = new KeyHandler();
}
@@ -225,14 +244,14 @@
final Message msg = mHandler.obtainMessage(MSG_KEY_LONG_PRESS, keyCode, 0,
eventTime);
msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, mLongPressTimeout);
+ mHandler.sendMessageDelayed(msg, mActiveRule.getLongPressTimeoutMs());
}
if (mActiveRule.supportVeryLongPress()) {
final Message msg = mHandler.obtainMessage(MSG_KEY_VERY_LONG_PRESS, keyCode, 0,
eventTime);
msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, mVeryLongPressTimeout);
+ mHandler.sendMessageDelayed(msg, mActiveRule.getVeryLongPressTimeoutMs());
}
} else {
mHandler.removeMessages(MSG_KEY_LONG_PRESS);
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 7555a7f..c91d8de 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -96,6 +96,7 @@
private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4;
private static final int MSG_PROFILE_TIMED_OUT = 5;
private static final int MSG_WIRED_CHARGING_STARTED = 6;
+ private static final int MSG_SCREEN_POLICY = 7;
private static final long[] CHARGING_VIBRATION_TIME = {
40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
@@ -120,6 +121,7 @@
private final SuspendBlocker mSuspendBlocker;
private final WindowManagerPolicy mPolicy;
private final FaceDownDetector mFaceDownDetector;
+ private final ScreenUndimDetector mScreenUndimDetector;
private final ActivityManagerInternal mActivityManagerInternal;
private final InputManagerInternal mInputManagerInternal;
private final InputMethodManagerInternal mInputMethodManagerInternal;
@@ -167,13 +169,14 @@
public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
mContext = context;
mBatteryStats = batteryStats;
mAppOps = mContext.getSystemService(AppOpsManager.class);
mSuspendBlocker = suspendBlocker;
mPolicy = policy;
mFaceDownDetector = faceDownDetector;
+ mScreenUndimDetector = screenUndimDetector;
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
@@ -620,6 +623,22 @@
}
/**
+ * Called when the screen policy changes.
+ */
+ public void onScreenPolicyUpdate(int newPolicy) {
+ if (DEBUG) {
+ Slog.d(TAG, "onScreenPolicyUpdate: newPolicy=" + newPolicy);
+ }
+
+ synchronized (mLock) {
+ Message msg = mHandler.obtainMessage(MSG_SCREEN_POLICY);
+ msg.arg1 = newPolicy;
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ /**
* Dumps data for bugreports.
*
* @param pw The stream to print to.
@@ -659,6 +678,7 @@
tm.notifyUserActivity();
mPolicy.userActivity();
mFaceDownDetector.userActivity(event);
+ mScreenUndimDetector.userActivity();
}
void postEnhancedDischargePredictionBroadcast(long delayMs) {
@@ -812,6 +832,10 @@
mSuspendBlocker.release();
}
+ private void screenPolicyChanging(int screenPolicy) {
+ mScreenUndimDetector.recordScreenPolicy(screenPolicy);
+ }
+
private void lockProfile(@UserIdInt int userId) {
mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
}
@@ -852,6 +876,9 @@
case MSG_WIRED_CHARGING_STARTED:
showWiredChargingStarted(msg.arg1);
break;
+ case MSG_SCREEN_POLICY:
+ screenPolicyChanging(msg.arg1);
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index db69158..688a3b2 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -274,6 +274,7 @@
private final BatterySavingStats mBatterySavingStats;
private final AttentionDetector mAttentionDetector;
private final FaceDownDetector mFaceDownDetector;
+ private final ScreenUndimDetector mScreenUndimDetector;
private final BinderService mBinderService;
private final LocalService mLocalService;
private final NativeWrapper mNativeWrapper;
@@ -533,6 +534,11 @@
// True if the proximity sensor reads a positive result.
private boolean mProximityPositive;
+ // Indicates that we have already intercepted the power key to temporarily ignore the proximity
+ // wake lock and turn the screen back on. This should get reset when prox reads 'far' again
+ // (when {@link #mProximityPositive} is set to false).
+ private boolean mInterceptedPowerKeyForProximity;
+
// Screen brightness setting limits.
public final float mScreenBrightnessMinimum;
public final float mScreenBrightnessMaximum;
@@ -832,9 +838,10 @@
static class Injector {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
return new Notifier(
- looper, context, batteryStats, suspendBlocker, policy, faceDownDetector);
+ looper, context, batteryStats, suspendBlocker, policy, faceDownDetector,
+ screenUndimDetector);
}
SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
@@ -955,6 +962,7 @@
mInjector.createAmbientDisplaySuppressionController(context);
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
mFaceDownDetector = new FaceDownDetector(this::onFlip);
+ mScreenUndimDetector = new ScreenUndimDetector();
mBatterySavingStats = new BatterySavingStats(mLock);
mBatterySaverPolicy =
@@ -1141,7 +1149,7 @@
mBatteryStats = BatteryStatsService.getService();
mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
- mPolicy, mFaceDownDetector);
+ mPolicy, mFaceDownDetector, mScreenUndimDetector);
mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
mInjector.createSuspendBlocker(
@@ -1176,6 +1184,7 @@
mBatterySaverController.systemReady();
mBatterySaverPolicy.systemReady();
mFaceDownDetector.systemReady(mContext);
+ mScreenUndimDetector.systemReady(mContext);
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -3185,6 +3194,7 @@
final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
displayPowerRequest, mRequestWaitForNegativeProximity);
+ mNotifier.onScreenPolicyUpdate(displayPowerRequest.policy);
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
@@ -3318,6 +3328,7 @@
public void onProximityNegative() {
synchronized (mLock) {
mProximityPositive = false;
+ mInterceptedPowerKeyForProximity = false;
mDirty |= DIRTY_PROXIMITY_POSITIVE;
userActivityNoUpdateLocked(Display.DEFAULT_DISPLAY_GROUP, mClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
@@ -4158,6 +4169,8 @@
}
pw.println();
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
+ pw.println(" mInterceptedPowerKeyForProximity="
+ + mInterceptedPowerKeyForProximity);
pw.println(" mSandmanScheduled=" + mSandmanScheduled);
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
pw.println(" mLightDeviceIdleMode=" + mLightDeviceIdleMode);
@@ -5989,8 +6002,9 @@
final DisplayPowerRequest displayPowerRequest =
mDisplayGroupPowerStateMapper.getPowerRequestLocked(
Display.DEFAULT_DISPLAY_GROUP);
- if (displayPowerRequest.useProximitySensor && mProximityPositive) {
+ if (mProximityPositive && !mInterceptedPowerKeyForProximity) {
mDisplayManagerInternal.ignoreProximitySensorUntilChanged();
+ mInterceptedPowerKeyForProximity = true;
return true;
}
}
diff --git a/services/core/java/com/android/server/power/ScreenUndimDetector.java b/services/core/java/com/android/server/power/ScreenUndimDetector.java
new file mode 100644
index 0000000..951bc1f
--- /dev/null
+++ b/services/core/java/com/android/server/power/ScreenUndimDetector.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2020 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;
+
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Detects when user manually undims the screen (x times) and acquires a wakelock to keep the screen
+ * on temporarily (without changing the screen timeout setting).
+ */
+public class ScreenUndimDetector {
+ private static final String TAG = "ScreenUndimDetector";
+ private static final boolean DEBUG = false;
+
+ private static final String UNDIM_DETECTOR_WAKE_LOCK = "UndimDetectorWakeLock";
+
+ /** DeviceConfig flag: is keep screen on feature enabled. */
+ static final String KEY_KEEP_SCREEN_ON_ENABLED = "keep_screen_on_enabled";
+ private static final boolean DEFAULT_KEEP_SCREEN_ON_ENABLED = true;
+ private static final int OUTCOME_POWER_BUTTON =
+ FrameworkStatsLog.TIMEOUT_AUTO_EXTENDED_REPORTED__OUTCOME__POWER_BUTTON;
+ private static final int OUTCOME_TIMEOUT =
+ FrameworkStatsLog.TIMEOUT_AUTO_EXTENDED_REPORTED__OUTCOME__TIMEOUT;
+ private boolean mKeepScreenOnEnabled;
+
+ /** DeviceConfig flag: how long should we keep the screen on. */
+ @VisibleForTesting
+ static final String KEY_KEEP_SCREEN_ON_FOR_MILLIS = "keep_screen_on_for_millis";
+ @VisibleForTesting
+ static final long DEFAULT_KEEP_SCREEN_ON_FOR_MILLIS = TimeUnit.MINUTES.toMillis(10);
+ private long mKeepScreenOnForMillis;
+
+ /** DeviceConfig flag: how many user undims required to trigger keeping the screen on. */
+ @VisibleForTesting
+ static final String KEY_UNDIMS_REQUIRED = "undims_required";
+ @VisibleForTesting
+ static final int DEFAULT_UNDIMS_REQUIRED = 2;
+ private int mUndimsRequired;
+
+ /**
+ * DeviceConfig flag: what is the maximum duration between undims to still consider them
+ * consecutive.
+ */
+ @VisibleForTesting
+ static final String KEY_MAX_DURATION_BETWEEN_UNDIMS_MILLIS =
+ "max_duration_between_undims_millis";
+ @VisibleForTesting
+ static final long DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS = TimeUnit.MINUTES.toMillis(5);
+ private long mMaxDurationBetweenUndimsMillis;
+
+ @VisibleForTesting
+ PowerManager.WakeLock mWakeLock;
+
+ @VisibleForTesting
+ int mCurrentScreenPolicy;
+ @VisibleForTesting
+ int mUndimCounter = 0;
+ @VisibleForTesting
+ long mUndimCounterStartedMillis;
+ private long mUndimOccurredTime = -1;
+ private long mInteractionAfterUndimTime = -1;
+ private InternalClock mClock;
+
+ public ScreenUndimDetector() {
+ mClock = new InternalClock();
+ }
+
+ ScreenUndimDetector(InternalClock clock) {
+ mClock = clock;
+ }
+
+ static class InternalClock {
+ public long getCurrentTime() {
+ return SystemClock.elapsedRealtime();
+ }
+ }
+
+ /** Should be called in parent's systemReady() */
+ public void systemReady(Context context) {
+ readValuesFromDeviceConfig();
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ context.getMainExecutor(),
+ (properties) -> onDeviceConfigChange(properties.getKeyset()));
+
+ final PowerManager powerManager = context.getSystemService(PowerManager.class);
+ mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
+ | PowerManager.ON_AFTER_RELEASE,
+ UNDIM_DETECTOR_WAKE_LOCK);
+ }
+
+ /**
+ * Launches a message that figures out the screen transitions and detects user undims. Must be
+ * called by the parent that is trying to update the screen policy.
+ */
+ public void recordScreenPolicy(int newPolicy) {
+ if (newPolicy == mCurrentScreenPolicy) {
+ return;
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Screen policy transition: " + mCurrentScreenPolicy + " -> " + newPolicy);
+ }
+
+ // update the current policy with the new one immediately so we don't accidentally get
+ // into a loop (which is possible if the switch below triggers a new policy).
+ final int currentPolicy = mCurrentScreenPolicy;
+ mCurrentScreenPolicy = newPolicy;
+
+ if (!mKeepScreenOnEnabled) {
+ return;
+ }
+
+ switch (currentPolicy) {
+ case POLICY_DIM:
+ if (newPolicy == POLICY_BRIGHT) {
+ final long now = mClock.getCurrentTime();
+ final long timeElapsedSinceFirstUndim = now - mUndimCounterStartedMillis;
+ if (timeElapsedSinceFirstUndim >= mMaxDurationBetweenUndimsMillis) {
+ reset();
+ }
+ if (mUndimCounter == 0) {
+ mUndimCounterStartedMillis = now;
+ }
+
+ mUndimCounter++;
+
+ if (DEBUG) {
+ Slog.d(TAG, "User undim, counter=" + mUndimCounter
+ + " (required=" + mUndimsRequired + ")"
+ + ", timeElapsedSinceFirstUndim=" + timeElapsedSinceFirstUndim
+ + " (max=" + mMaxDurationBetweenUndimsMillis + ")");
+ }
+ if (mUndimCounter >= mUndimsRequired) {
+ reset();
+ if (DEBUG) {
+ Slog.d(TAG, "Acquiring a wake lock for " + mKeepScreenOnForMillis);
+ }
+ if (mWakeLock != null) {
+ mUndimOccurredTime = mClock.getCurrentTime();
+ mWakeLock.acquire(mKeepScreenOnForMillis);
+ }
+ }
+ } else {
+ if (newPolicy == POLICY_OFF || newPolicy == POLICY_DOZE) {
+ checkAndLogUndim(OUTCOME_TIMEOUT);
+ }
+ reset();
+ }
+ break;
+ case POLICY_BRIGHT:
+ if (newPolicy == POLICY_OFF || newPolicy == POLICY_DOZE) {
+ checkAndLogUndim(OUTCOME_POWER_BUTTON);
+ }
+ if (newPolicy != POLICY_DIM) {
+ reset();
+ }
+ break;
+ }
+ }
+
+ @VisibleForTesting
+ void reset() {
+ if (DEBUG) {
+ Slog.d(TAG, "Resetting the undim detector");
+ }
+ mUndimCounter = 0;
+ mUndimCounterStartedMillis = 0;
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+
+ private boolean readKeepScreenOnNotificationEnabled() {
+ return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_KEEP_SCREEN_ON_ENABLED,
+ DEFAULT_KEEP_SCREEN_ON_ENABLED);
+ }
+
+ private long readKeepScreenOnForMillis() {
+ return DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_KEEP_SCREEN_ON_FOR_MILLIS,
+ DEFAULT_KEEP_SCREEN_ON_FOR_MILLIS);
+ }
+
+ private int readUndimsRequired() {
+ int undimsRequired = DeviceConfig.getInt(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ DEFAULT_UNDIMS_REQUIRED);
+
+ if (undimsRequired < 1 || undimsRequired > 5) {
+ Slog.e(TAG, "Provided undimsRequired=" + undimsRequired
+ + " is not allowed [1, 5]; using the default=" + DEFAULT_UNDIMS_REQUIRED);
+ return DEFAULT_UNDIMS_REQUIRED;
+ }
+
+ return undimsRequired;
+ }
+
+ private long readMaxDurationBetweenUndimsMillis() {
+ return DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_MAX_DURATION_BETWEEN_UNDIMS_MILLIS,
+ DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS);
+ }
+
+ private void onDeviceConfigChange(@NonNull Set<String> keys) {
+ for (String key : keys) {
+ Slog.i(TAG, "onDeviceConfigChange; key=" + key);
+ switch (key) {
+ case KEY_KEEP_SCREEN_ON_ENABLED:
+ case KEY_KEEP_SCREEN_ON_FOR_MILLIS:
+ case KEY_UNDIMS_REQUIRED:
+ case KEY_MAX_DURATION_BETWEEN_UNDIMS_MILLIS:
+ readValuesFromDeviceConfig();
+ return;
+ default:
+ Slog.i(TAG, "Ignoring change on " + key);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ void readValuesFromDeviceConfig() {
+ mKeepScreenOnEnabled = readKeepScreenOnNotificationEnabled();
+ mKeepScreenOnForMillis = readKeepScreenOnForMillis();
+ mUndimsRequired = readUndimsRequired();
+ mMaxDurationBetweenUndimsMillis = readMaxDurationBetweenUndimsMillis();
+
+ Slog.i(TAG, "readValuesFromDeviceConfig():"
+ + "\nmKeepScreenOnForMillis=" + mKeepScreenOnForMillis
+ + "\nmKeepScreenOnNotificationEnabled=" + mKeepScreenOnEnabled
+ + "\nmUndimsRequired=" + mUndimsRequired);
+
+ }
+
+ /**
+ * The user interacted with the screen after an undim, indicating the phone is in use.
+ * We use this event for logging.
+ */
+ public void userActivity() {
+ if (mUndimOccurredTime != 1 && mInteractionAfterUndimTime == -1) {
+ mInteractionAfterUndimTime = mClock.getCurrentTime();
+ }
+ }
+
+ /**
+ * Checks and logs if an undim occurred.
+ *
+ * A log will occur if an undim seems to have resulted in a timeout or a direct screen off such
+ * as from a power button. Some outcomes may not be correctly assigned to a
+ * TIMEOUT_AUTO_EXTENDED_REPORTED__OUTCOME value.
+ */
+ private void checkAndLogUndim(int outcome) {
+ if (mUndimOccurredTime != -1) {
+ long now = mClock.getCurrentTime();
+ FrameworkStatsLog.write(FrameworkStatsLog.TIMEOUT_AUTO_EXTENDED_REPORTED,
+ outcome,
+ /* time_to_outcome_millis=*/ now - mUndimOccurredTime,
+ /* time_to_first_interaction_millis= */
+ mInteractionAfterUndimTime != -1 ? now - mInteractionAfterUndimTime : -1
+ );
+ mUndimOccurredTime = -1;
+ mInteractionAfterUndimTime = -1;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 7713320..80bc16a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.wallpaper;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.app.WallpaperManager.COMMAND_REAPPLY;
import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
@@ -2045,7 +2046,21 @@
}
}
+ private boolean hasCrossUserPermission() {
+ final int interactPermission =
+ mContext.checkCallingPermission(INTERACT_ACROSS_USERS_FULL);
+ return interactPermission == PackageManager.PERMISSION_GRANTED;
+ }
+
+ @Override
public boolean hasNamedWallpaper(String name) {
+ final int callingUser = UserHandle.getCallingUserId();
+ final boolean allowCrossUser = hasCrossUserPermission();
+ if (DEBUG) {
+ Slog.d(TAG, "hasNamedWallpaper() caller " + Binder.getCallingUid()
+ + " cross-user?: " + allowCrossUser);
+ }
+
synchronized (mLock) {
List<UserInfo> users;
final long ident = Binder.clearCallingIdentity();
@@ -2055,6 +2070,11 @@
Binder.restoreCallingIdentity(ident);
}
for (UserInfo user: users) {
+ if (!allowCrossUser && callingUser != user.id) {
+ // No cross-user information for callers without permission
+ continue;
+ }
+
// ignore managed profiles
if (user.isManagedProfile()) {
continue;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 54d97ee..f1644e9 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -88,6 +88,7 @@
import android.view.ViewConfiguration;
import android.view.WindowInfo;
import android.view.WindowManager;
+import android.view.WindowManagerPolicyConstants;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -1200,7 +1201,7 @@
final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
final int layer =
mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY) *
- WindowManagerService.TYPE_LAYER_MULTIPLIER;
+ WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
t.setLayer(mSurfaceControl, layer).setPosition(mSurfaceControl, 0, 0);
InputMonitor.setTrustedOverlayInputInfo(mSurfaceControl, t,
mDisplayContent.getDisplayId(), "Magnification Overlay");
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 675c7eb..cc0db1d 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -21,6 +21,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.os.Process.INVALID_UID;
+import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -57,6 +59,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
@@ -68,6 +71,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.UserHandle;
import android.service.voice.VoiceInteractionManagerInternal;
import android.util.Slog;
import android.view.RemoteAnimationDefinition;
@@ -79,6 +83,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.LocalServices;
import com.android.server.Watchdog;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.uri.NeededUriGrants;
import com.android.server.vr.VrManagerInternal;
@@ -549,7 +554,9 @@
if (ar == null) {
return null;
}
- final ActivityRecord below = ar.getTask().getActivityBelow(ar);
+ // Exclude finishing activity.
+ final ActivityRecord below = ar.getTask().getActivity((r) -> !r.finishing,
+ ar, false /*includeBoundary*/, true /*traverseTopToBottom*/);
if (below != null && below.getUid() == ar.getUid()) {
return below.appToken.asBinder();
}
@@ -583,20 +590,45 @@
@Override
public int getLaunchedFromUid(IBinder token) {
+ if (!canGetLaunchedFrom()) {
+ return INVALID_UID;
+ }
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- return r != null ? r.launchedFromUid : android.os.Process.INVALID_UID;
+ return r != null ? r.launchedFromUid : INVALID_UID;
}
}
@Override
public String getLaunchedFromPackage(IBinder token) {
+ if (!canGetLaunchedFrom()) {
+ return null;
+ }
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
return r != null ? r.launchedFromPackage : null;
}
}
+ /** Whether the caller can get the package or uid that launched its activity. */
+ private boolean canGetLaunchedFrom() {
+ final int uid = Binder.getCallingUid();
+ if (UserHandle.getAppId(uid) == SYSTEM_UID) {
+ return true;
+ }
+ final PackageManagerInternal pm = mService.mWindowManager.mPmInternal;
+ final AndroidPackage callingPkg = pm.getPackage(uid);
+ if (callingPkg == null) {
+ return false;
+ }
+ if (callingPkg.isSignedWithPlatformKey()) {
+ return true;
+ }
+ final String[] installerNames = pm.getKnownPackageNames(
+ PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.getUserId(uid));
+ return installerNames.length > 0 && callingPkg.getPackageName().equals(installerNames[0]);
+ }
+
@Override
public void setRequestedOrientation(IBinder token, int requestedOrientation) {
final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 60e7d109..856c1e0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7090,7 +7090,7 @@
return;
}
- mDisplayContent.mPinnedTaskController.onCancelFixedRotationTransform(task);
+ mDisplayContent.mPinnedTaskController.onCancelFixedRotationTransform();
// Perform rotation animation according to the rotation of this activity.
startFreezingScreen(originalDisplayRotation);
// This activity may relaunch or perform configuration change so once it has reported drawn,
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index aa7e6c9..18a2c60 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -30,6 +30,7 @@
import android.view.InputApplicationHandle;
import android.view.KeyEvent;
import android.view.WindowManager;
+import android.view.WindowManagerPolicyConstants;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.input.InputManagerService;
@@ -181,8 +182,8 @@
@Override
public int getPointerLayer() {
return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
+ * WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER
+ + WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
}
/** Callback to get pointer display id. */
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c716deb..c8373df 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -289,6 +289,7 @@
inputWindowHandle.setInputFeatures(w.mAttrs.inputFeatures);
inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused);
inputWindowHandle.setVisible(w.isVisible());
+ inputWindowHandle.setWindowToken(w.mClient);
final boolean focusable = w.canReceiveKeys()
&& (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
diff --git a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
index 7a4d13c..0a24d3c 100644
--- a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
+++ b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.graphics.Region;
import android.os.IBinder;
+import android.view.IWindow;
import android.view.InputApplicationHandle;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
@@ -275,6 +276,14 @@
mChanged = true;
}
+ void setWindowToken(IWindow windowToken) {
+ if (mHandle.getWindow() == windowToken) {
+ return;
+ }
+ mHandle.setWindowToken(windowToken);
+ mChanged = true;
+ }
+
@Override
public String toString() {
return mHandle + ", changed=" + mChanged;
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 4f7c9a4..6014a87 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -319,15 +319,11 @@
}
/** Resets the states which were used to perform fixed rotation with PiP task. */
- void onCancelFixedRotationTransform(Task task) {
+ void onCancelFixedRotationTransform() {
mFreezingTaskConfig = false;
mDeferOrientationChanging = false;
mDestRotatedBounds = null;
mPipTransaction = null;
- if (!task.isOrganized()) {
- // Force clearing Task#mForceNotOrganized because the display didn't rotate.
- task.onConfigurationChanged(task.getParent().getConfiguration());
- }
}
/**
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 58363f2..d440a14 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -18,6 +18,7 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.RotationUtils.deltaRotation;
+import static android.view.WindowManagerPolicyConstants.SCREEN_FREEZE_LAYER_BASE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
@@ -30,8 +31,6 @@
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
-import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
import android.animation.ArgbEvaluator;
import android.content.Context;
@@ -91,13 +90,6 @@
class ScreenRotationAnimation {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ScreenRotationAnimation" : TAG_WM;
- /*
- * Layers for screen rotation animation. We put these layers above
- * WINDOW_FREEZE_LAYER so that screen freeze will cover all windows.
- */
- private static final int SCREEN_FREEZE_LAYER_BASE = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER;
- private static final int SCREEN_FREEZE_LAYER_ENTER = SCREEN_FREEZE_LAYER_BASE;
-
private final Context mContext;
private final DisplayContent mDisplayContent;
private final float[] mTmpFloats = new float[9];
@@ -423,7 +415,7 @@
finalWidth * 2, finalHeight * 2);
Rect inner = new Rect(0, 0, finalWidth, finalHeight);
mEnteringBlackFrame = new BlackFrame(mService.mTransactionFactory, t, outer, inner,
- SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false, mEnterBlackFrameLayer);
+ SCREEN_FREEZE_LAYER_BASE, mDisplayContent, false, mEnterBlackFrameLayer);
} catch (OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
}
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index 48a7bde..cdf6b08 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -27,6 +27,7 @@
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import android.view.WindowManagerPolicyConstants;
class StrictModeFlash {
private static final String TAG = TAG_WITH_CLASS_NAME ? "StrictModeFlash" : TAG_WM;
@@ -52,7 +53,7 @@
.build();
// one more than Watermark? arbitrary.
- t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);
+ t.setLayer(ctrl, WindowManagerPolicyConstants.STRICT_MODE_LAYER);
t.setPosition(ctrl, 0, 0);
t.show(ctrl);
// Ensure we aren't considered as obscuring for Input purposes.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e35579b..73dda74 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -590,16 +590,6 @@
// false.
private boolean mDeferTaskAppear;
- /**
- * Forces this task to be unorganized. Currently it is used for deferring the control of
- * organizer when windowing mode is changing from PiP to fullscreen with orientation change.
- * It is true only during Task#setWindowingMode ~ DisplayRotation#continueRotation.
- *
- * TODO(b/179235349): Remove this field by making surface operations from task organizer sync
- * with display rotation.
- */
- private boolean mForceNotOrganized;
-
// Tracking cookie for the creation of this task.
IBinder mLaunchCookie;
@@ -1932,19 +1922,16 @@
}
}
- if (pipChanging) {
- // If the top activity is using fixed rotation, it should be changing from PiP to
- // fullscreen with display orientation change. Do not notify fullscreen task organizer
- // because the restoration of task surface and the transformation of activity surface
- // need to be done synchronously.
+ if (pipChanging && wasInPictureInPicture) {
+ // If the top activity is changing from PiP to fullscreen with fixed rotation,
+ // clear the crop and rotation matrix of task because fixed rotation will handle
+ // the transformation on activity level. This also avoids flickering caused by the
+ // latency of fullscreen task organizer configuring the surface.
final ActivityRecord r = topRunningActivity();
if (r != null && mDisplayContent.isFixedRotationLaunchingApp(r)) {
- mForceNotOrganized = true;
+ getSyncTransaction().setWindowCrop(mSurfaceControl, null)
+ .setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9]);
}
- } else {
- // If the display orientation change is done, let the corresponding task organizer take
- // back the control of this task.
- mForceNotOrganized = false;
}
saveLaunchingStateIfNeeded();
@@ -3672,9 +3659,6 @@
pw.print(" isResizeable="); pw.println(isResizeable());
pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
- if (mForceNotOrganized) {
- pw.print(prefix); pw.println("mForceNotOrganized=true");
- }
}
@Override
@@ -4150,9 +4134,6 @@
}
private boolean canBeOrganized() {
- if (mForceNotOrganized) {
- return false;
- }
// All root tasks can be organized
if (isRootTask()) {
return true;
@@ -4305,7 +4286,6 @@
return setTaskOrganizer(null);
}
- final int windowingMode = getWindowingMode();
final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
final ITaskOrganizer organizer = controller.getTaskOrganizer();
if (!forceUpdate && mTaskOrganizer == organizer) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index cfad936..c7ca180 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -32,6 +32,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
@@ -112,7 +113,6 @@
private final ArrayList<WindowContainer> mTmpNormalChildren = new ArrayList<>();
private final ArrayList<WindowContainer> mTmpHomeChildren = new ArrayList<>();
private final IntArray mTmpNeedsZBoostIndexes = new IntArray();
- private int mTmpLayerForSplitScreenDividerAnchor;
private int mTmpLayerForAnimationLayer;
private ArrayList<Task> mTmpTasks = new ArrayList<>();
@@ -855,26 +855,23 @@
layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer, false /* normalRootTasks */);
// The home animation layer is between the root home tasks and the normal root tasks.
final int layerForHomeAnimationLayer = layer++;
- mTmpLayerForSplitScreenDividerAnchor = layer++;
mTmpLayerForAnimationLayer = layer++;
layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer, true /* normalRootTasks */);
// The boosted animation layer is between the normal root tasks and the always on top
// root tasks.
final int layerForBoostedAnimationLayer = layer++;
+ // Always on top tasks layer should higher than split divider layer so set it as start.
+ layer = SPLIT_DIVIDER_LAYER + 1;
adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer, false /* normalRootTasks */);
t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer);
- t.setLayer(mSplitScreenDividerAnchor, mTmpLayerForSplitScreenDividerAnchor);
+ t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
}
private int adjustNormalRootTaskLayer(WindowContainer child, int layer) {
- if (child.asTask() != null && child.inSplitScreenWindowingMode()) {
- // The split screen divider anchor is located above the split screen window.
- mTmpLayerForSplitScreenDividerAnchor = layer++;
- }
if ((child.asTask() != null && child.asTask().isAnimatingByRecents())
|| child.isAppTransitioning()) {
// The animation layer is located above the highest animating root task and no
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 66ab094..9780d33 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -31,6 +31,7 @@
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import android.view.WindowManagerPolicyConstants;
/**
* Displays a watermark on top of the window manager's windows.
@@ -117,7 +118,7 @@
.setFormat(PixelFormat.TRANSLUCENT)
.setCallsite(TITLE)
.build();
- t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
+ t.setLayer(ctrl, WindowManagerPolicyConstants.WATERMARK_LAYER)
.setPosition(ctrl, 0, 0)
.show(ctrl);
// Ensure we aren't considered as obscuring for Input purposes.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 501ae1b..81f9f6f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -85,6 +85,7 @@
import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
+import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
import static android.window.WindowProviderService.isWindowProviderService;
@@ -340,27 +341,6 @@
static final boolean PROFILE_ORIENTATION = false;
- /** How much to multiply the policy's type layer, to reserve room
- * for multiple windows of the same type and Z-ordering adjustment
- * with TYPE_LAYER_OFFSET. */
- static final int TYPE_LAYER_MULTIPLIER = 10000;
-
- /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
- * or below others in the same layer. */
- static final int TYPE_LAYER_OFFSET = 1000;
-
- /** How much to increment the layer for each window, to reserve room
- * for effect surfaces between them.
- */
- static final int WINDOW_LAYER_MULTIPLIER = 5;
-
- /**
- * Animation thumbnail is as far as possible below the window above
- * the thumbnail (or in other words as far as possible above the window
- * below it).
- */
- static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
-
/** The maximum length we will accept for a loaded animation duration:
* this is 10 seconds.
*/
@@ -8256,7 +8236,7 @@
}
updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
- name, applicationHandle, flags, privateFlags, type, null /* region */);
+ name, applicationHandle, flags, privateFlags, type, null /* region */, window);
clientChannel.copyTo(outInputChannel);
}
@@ -8264,9 +8244,10 @@
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
int displayId, SurfaceControl surface, String name,
InputApplicationHandle applicationHandle, int flags,
- int privateFlags, int type, Region region) {
+ int privateFlags, int type, Region region, IWindow window) {
InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
h.token = channelToken;
+ h.setWindowToken(window);
h.name = name;
final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
@@ -8322,7 +8303,7 @@
}
updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
- applicationHandle, flags, privateFlags, win.mWindowType, region);
+ applicationHandle, flags, privateFlags, win.mWindowType, region, win.mClient);
}
/** Return whether layer tracing is enabled */
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 65b065a..cd29f0e 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -730,11 +730,14 @@
canUpdate = true;
}
- // Compare the z-order of ActivityStacks if both activities landed on same display.
- if (display == topDisplay
- && mPreQTopResumedActivity.getRootTask().compareTo(
- activity.getRootTask()) <= 0) {
- canUpdate = true;
+ // Update the topmost activity if the activity has higher z-order than the current
+ // top-resumed activity.
+ if (!canUpdate) {
+ final ActivityRecord ar = topDisplay.getActivity(r -> r == activity,
+ true /* traverseTopToBottom */, mPreQTopResumedActivity);
+ if (ar != null && ar != mPreQTopResumedActivity) {
+ canUpdate = true;
+ }
}
if (canUpdate) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0091b61..1ca0c7e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -107,6 +107,8 @@
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
+import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
+import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -153,8 +155,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
-import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
-import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8094196..f25706a 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -41,7 +41,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
@@ -71,7 +70,6 @@
**/
class WindowStateAnimator {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
- static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
static final int PRESERVED_SURFACE_LAYER = 1;
/**
diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd
index 94a398f..86f4176 100644
--- a/services/core/xsd/device-state-config/device-state-config.xsd
+++ b/services/core/xsd/device-state-config/device-state-config.xsd
@@ -40,10 +40,19 @@
<xs:element name="name" type="xs:string" minOccurs="0">
<xs:annotation name="nullable" />
</xs:element>
+ <xs:element name="flags" type="flags" />
<xs:element name="conditions" type="conditions" />
</xs:sequence>
</xs:complexType>
+ <xs:complexType name="flags">
+ <xs:sequence>
+ <xs:element name="flag" type="xs:string" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation name="nullable" />
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
<xs:complexType name="conditions">
<xs:sequence>
<xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0">
diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt
index 08fccf8..a98d4e5 100644
--- a/services/core/xsd/device-state-config/schema/current.txt
+++ b/services/core/xsd/device-state-config/schema/current.txt
@@ -11,9 +11,11 @@
public class DeviceState {
ctor public DeviceState();
method public com.android.server.policy.devicestate.config.Conditions getConditions();
+ method public com.android.server.policy.devicestate.config.Flags getFlags();
method public java.math.BigInteger getIdentifier();
method @Nullable public String getName();
method public void setConditions(com.android.server.policy.devicestate.config.Conditions);
+ method public void setFlags(com.android.server.policy.devicestate.config.Flags);
method public void setIdentifier(java.math.BigInteger);
method public void setName(@Nullable String);
}
@@ -23,6 +25,11 @@
method public java.util.List<com.android.server.policy.devicestate.config.DeviceState> getDeviceState();
}
+ public class Flags {
+ ctor public Flags();
+ method @Nullable public java.util.List<java.lang.String> getFlag();
+ }
+
public class LidSwitchCondition {
ctor public LidSwitchCondition();
method public boolean getOpen();
diff --git a/services/tests/PackageManager/packageinstaller/Android.bp b/services/tests/PackageManager/packageinstaller/Android.bp
new file mode 100644
index 0000000..35d754b
--- /dev/null
+++ b/services/tests/PackageManager/packageinstaller/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "PackageInstallerTests",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.runner",
+ "junit",
+ "kotlin-test",
+ "truth-prebuilt",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+}
diff --git a/services/tests/PackageManager/packageinstaller/AndroidManifest.xml b/services/tests/PackageManager/packageinstaller/AndroidManifest.xml
new file mode 100644
index 0000000..d706258
--- /dev/null
+++ b/services/tests/PackageManager/packageinstaller/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.packageinstaller.test">
+
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.packageinstaller.test"
+ />
+
+</manifest>
+
diff --git a/services/tests/PackageManager/packageinstaller/AndroidTest.xml b/services/tests/PackageManager/packageinstaller/AndroidTest.xml
new file mode 100644
index 0000000..c39285ff
--- /dev/null
+++ b/services/tests/PackageManager/packageinstaller/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<configuration description="Test module config for PackageInstallerTests">
+ <option name="test-tag" value="PackageInstallerTests" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="PackageInstallerTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.packageinstaller.test" />
+ </test>
+</configuration>
diff --git a/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt b/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt
new file mode 100644
index 0000000..d7d2726
--- /dev/null
+++ b/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.packageinstaller.test
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import androidx.test.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+
+class ExportedComponentTest {
+
+ private val context: Context = InstrumentationRegistry.getContext()
+
+ @Test
+ fun verifyNoExportedReceivers() {
+ val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
+ data = Uri.parse("content://mockForTest")
+ }
+ val packageInstallers = context.packageManager.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_DISABLED_COMPONENTS)
+ .map { it.activityInfo.packageName }
+ .distinct()
+ .map { context.packageManager.getPackageInfo(it, PackageManager.GET_RECEIVERS) }
+
+ assertThat(packageInstallers).isNotEmpty()
+
+ packageInstallers.forEach {
+ val exported = it.receivers.filter { it.exported }
+ assertWithMessage("Receivers should not be exported").that(exported).isEmpty()
+ }
+ }
+}
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 17a5dcc..3cab5ec 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -28,6 +28,7 @@
<uses-permission android:name="android.permission.MANAGE_APPOPS"/>
<uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"/>
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission
android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index acf50b45..e472b06 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -323,6 +323,7 @@
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
doNothing().when(mWakeLock).acquire();
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
+ doNothing().when(mAlarmManager).setExact(anyInt(), anyLong(), anyString(), any(), any());
doNothing().when(mAlarmManager)
.setWindow(anyInt(), anyLong(), anyLong(), anyString(), any(), any());
doReturn(mock(Sensor.class)).when(mSensorManager)
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
new file mode 100644
index 0000000..f94377f
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2020 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;
+
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_VR;
+import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+
+import static com.android.server.power.ScreenUndimDetector.DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS;
+import static com.android.server.power.ScreenUndimDetector.KEY_KEEP_SCREEN_ON_ENABLED;
+import static com.android.server.power.ScreenUndimDetector.KEY_MAX_DURATION_BETWEEN_UNDIMS_MILLIS;
+import static com.android.server.power.ScreenUndimDetector.KEY_UNDIMS_REQUIRED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.testing.TestableContext;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.testables.TestableDeviceConfig;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for {@link com.android.server.power.ScreenUndimDetector}
+ */
+@RunWith(JUnit4.class)
+public class ScreenUndimDetectorTest {
+ private static final List<Integer> ALL_POLICIES =
+ Arrays.asList(POLICY_OFF,
+ POLICY_DOZE,
+ POLICY_DIM,
+ POLICY_BRIGHT,
+ POLICY_VR);
+
+ @ClassRule
+ public static final TestableContext sContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+ @Rule
+ public TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ private ScreenUndimDetector mScreenUndimDetector;
+
+ private final TestClock mClock = new TestClock();
+
+ private static class TestClock extends ScreenUndimDetector.InternalClock {
+ long mCurrentTime = 0;
+ @Override
+ public long getCurrentTime() {
+ return mCurrentTime;
+ }
+
+ public void advanceTime(long millisAdvanced) {
+ mCurrentTime += millisAdvanced;
+ }
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(1), false /*makeDefault*/);
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_MAX_DURATION_BETWEEN_UNDIMS_MILLIS,
+ Long.toString(DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS),
+ false /*makeDefault*/);
+
+ mScreenUndimDetector = new ScreenUndimDetector(mClock);
+ mScreenUndimDetector.systemReady(sContext);
+ }
+
+ @Test
+ public void recordScreenPolicy_disabledByFlag_noop() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_KEEP_SCREEN_ON_ENABLED, Boolean.FALSE.toString(), false /*makeDefault*/);
+
+ setup();
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ }
+
+ @Test
+ public void recordScreenPolicy_samePolicy_noop() {
+ for (int policy : ALL_POLICIES) {
+ setup();
+ mScreenUndimDetector.recordScreenPolicy(policy);
+ mScreenUndimDetector.recordScreenPolicy(policy);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ }
+ }
+
+ @Test
+ public void recordScreenPolicy_dimToBright_extends() {
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
+ }
+
+ @Test
+ public void recordScreenPolicy_otherTransitions_doesNotExtend() {
+ for (int from : ALL_POLICIES) {
+ for (int to : ALL_POLICIES) {
+ if (from == POLICY_DIM && to == POLICY_BRIGHT) {
+ continue;
+ }
+ setup();
+ mScreenUndimDetector.recordScreenPolicy(from);
+ mScreenUndimDetector.recordScreenPolicy(to);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ }
+ }
+ }
+
+ @Test
+ public void recordScreenPolicy_dimToBright_twoUndimsNeeded_extends() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
+ }
+
+ @Test
+ public void recordScreenPolicy_dimBrightDimOff_resetsCounter_doesNotExtend() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ }
+
+ @Test
+ public void recordScreenPolicy_undimToOff_resetsCounter() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ }
+
+ @Test
+ public void recordScreenPolicy_undimOffUndim_doesNotExtend() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ // undim
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ // off
+ mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+ // second undim
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(1);
+ }
+
+ @Test
+ public void recordScreenPolicy_dimToBright_tooFarApart_doesNotExtend() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ mClock.advanceTime(DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS + 5);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(1);
+ }
+
+ @Test
+ public void recordScreenPolicy_dimToNonBright_resets() {
+ for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE, POLICY_VR)) {
+ setup();
+ mScreenUndimDetector.mUndimCounter = 1;
+ mScreenUndimDetector.mUndimCounterStartedMillis = 123;
+ mScreenUndimDetector.mWakeLock.acquire();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(to);
+
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isEqualTo(0);
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ }
+
+ }
+
+ @Test
+ public void recordScreenPolicy_brightToNonDim_resets() {
+ for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE, POLICY_VR)) {
+ setup();
+ mScreenUndimDetector.mUndimCounter = 1;
+ mScreenUndimDetector.mUndimCounterStartedMillis = 123;
+ mScreenUndimDetector.mWakeLock.acquire();
+
+ mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(to);
+
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isEqualTo(0);
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ }
+ }
+
+ @Test
+ public void recordScreenPolicy_otherTransitions_doesNotReset() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(3),
+ false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ for (int from : ALL_POLICIES) {
+ for (int to : ALL_POLICIES) {
+ if (from == POLICY_DIM && to != POLICY_BRIGHT) {
+ continue;
+ }
+ if (from == POLICY_BRIGHT && to != POLICY_DIM) {
+ continue;
+ }
+ mScreenUndimDetector.mCurrentScreenPolicy = POLICY_OFF;
+ mScreenUndimDetector.mUndimCounter = 1;
+ mScreenUndimDetector.mUndimCounterStartedMillis =
+ SystemClock.currentThreadTimeMillis();
+
+ mScreenUndimDetector.recordScreenPolicy(from);
+ mScreenUndimDetector.recordScreenPolicy(to);
+
+ assertThat(mScreenUndimDetector.mUndimCounter).isNotEqualTo(0);
+ assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isNotEqualTo(0);
+ }
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index ff8fbda..b1b6e53 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -18,6 +18,7 @@
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
@@ -35,6 +36,11 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import static org.mockito.Mockito.mock;
+
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.WindowProcessController;
+
import junit.framework.Assert;
import org.junit.Before;
@@ -55,10 +61,15 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public final class DeviceStateManagerServiceTest {
- private static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(0, "DEFAULT");
- private static final DeviceState OTHER_DEVICE_STATE = new DeviceState(1, "OTHER");
+ private static final DeviceState DEFAULT_DEVICE_STATE =
+ new DeviceState(0, "DEFAULT", 0 /* flags */);
+ private static final DeviceState OTHER_DEVICE_STATE =
+ new DeviceState(1, "OTHER", 0 /* flags */);
// A device state that is not reported as being supported for the default test provider.
- private static final DeviceState UNSUPPORTED_DEVICE_STATE = new DeviceState(255, "UNSUPPORTED");
+ private static final DeviceState UNSUPPORTED_DEVICE_STATE =
+ new DeviceState(255, "UNSUPPORTED", 0 /* flags */);
+
+ private static final int FAKE_PROCESS_ID = 100;
private TestDeviceStatePolicy mPolicy;
private TestDeviceStateProvider mProvider;
@@ -69,6 +80,25 @@
mProvider = new TestDeviceStateProvider();
mPolicy = new TestDeviceStatePolicy(mProvider);
mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy);
+
+ // Necessary to allow us to check for top app process id in tests
+ mService.mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
+ WindowProcessController windowProcessController = mock(WindowProcessController.class);
+ when(mService.mActivityTaskManagerInternal.getTopApp())
+ .thenReturn(windowProcessController);
+ when(windowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
+
+ flushHandler(); // Flush the handler to ensure the initial values are committed.
+ }
+
+ private void flushHandler() {
+ flushHandler(1);
+ }
+
+ private void flushHandler(int count) {
+ for (int i = 0; i < count; i++) {
+ mService.getHandler().runWithScissors(() -> {}, 0);
+ }
}
@Test
@@ -80,6 +110,7 @@
DEFAULT_DEVICE_STATE.getIdentifier());
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+ flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
@@ -92,6 +123,7 @@
mPolicy.blockConfigure();
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+ flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
@@ -99,6 +131,7 @@
OTHER_DEVICE_STATE.getIdentifier());
mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
+ flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -106,6 +139,7 @@
OTHER_DEVICE_STATE.getIdentifier());
mPolicy.resumeConfigure();
+ flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -149,6 +183,7 @@
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE });
+ flushHandler();
// The current committed and requests states do not change because the current state remains
// supported.
@@ -166,6 +201,7 @@
mService.getBinderService().registerCallback(callback);
// An initial callback will be triggered on registration, so we clear it here.
+ flushHandler();
callback.clearLastNotifiedInfo();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -174,6 +210,7 @@
mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE });
+ flushHandler();
// The current committed and requests states do not change because the current state remains
// supported.
@@ -203,12 +240,14 @@
mService.getBinderService().registerCallback(callback);
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+ flushHandler();
assertEquals(callback.getLastNotifiedInfo().baseState,
OTHER_DEVICE_STATE.getIdentifier());
assertEquals(callback.getLastNotifiedInfo().currentState,
OTHER_DEVICE_STATE.getIdentifier());
mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
+ flushHandler();
assertEquals(callback.getLastNotifiedInfo().baseState,
DEFAULT_DEVICE_STATE.getIdentifier());
assertEquals(callback.getLastNotifiedInfo().currentState,
@@ -216,6 +255,7 @@
mPolicy.blockConfigure();
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+ flushHandler();
// The callback should not have been notified of the state change as the policy is still
// pending callback.
assertEquals(callback.getLastNotifiedInfo().baseState,
@@ -224,6 +264,7 @@
DEFAULT_DEVICE_STATE.getIdentifier());
mPolicy.resumeConfigure();
+ flushHandler();
// Now that the policy is finished processing the callback should be notified of the state
// change.
assertEquals(callback.getLastNotifiedInfo().baseState,
@@ -236,6 +277,7 @@
public void registerCallback_emitsInitialValue() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
assertNotNull(callback.getLastNotifiedInfo());
assertEquals(callback.getLastNotifiedInfo().baseState,
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -247,6 +289,7 @@
public void requestState() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
final IBinder token = new Binder();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -254,6 +297,10 @@
mService.getBinderService().requestState(token, OTHER_DEVICE_STATE.getIdentifier(),
0 /* flags */);
+ // Flush the handler twice. The first flush ensures the request is added and the policy is
+ // notified, while the second flush ensures the callback is notified once the change is
+ // committed.
+ flushHandler(2 /* count */);
assertEquals(callback.getLastNotifiedStatus(token),
TestDeviceStateManagerCallback.STATUS_ACTIVE);
@@ -271,6 +318,7 @@
OTHER_DEVICE_STATE.getIdentifier());
mService.getBinderService().cancelRequest(token);
+ flushHandler();
assertEquals(callback.getLastNotifiedStatus(token),
TestDeviceStateManagerCallback.STATUS_CANCELED);
@@ -291,6 +339,7 @@
public void requestState_pendingStateAtRequest() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
mPolicy.blockConfigure();
@@ -303,6 +352,10 @@
mService.getBinderService().requestState(firstRequestToken,
OTHER_DEVICE_STATE.getIdentifier(), 0 /* flags */);
+ // Flush the handler twice. The first flush ensures the request is added and the policy is
+ // notified, while the second flush ensures the callback is notified once the change is
+ // committed.
+ flushHandler(2 /* count */);
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
@@ -312,8 +365,8 @@
mService.getBinderService().requestState(secondRequestToken,
DEFAULT_DEVICE_STATE.getIdentifier(), 0 /* flags */);
-
mPolicy.resumeConfigureOnce();
+ flushHandler();
// First request status is now suspended as there is another pending request.
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
@@ -330,6 +383,7 @@
DEFAULT_DEVICE_STATE.getIdentifier());
mPolicy.resumeConfigure();
+ flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
@@ -339,6 +393,7 @@
// Now cancel the second request to make the first request active.
mService.getBinderService().cancelRequest(secondRequestToken);
+ flushHandler();
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
TestDeviceStateManagerCallback.STATUS_ACTIVE);
@@ -356,6 +411,7 @@
public void requestState_sameAsBaseState() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
final IBinder token = new Binder();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -363,6 +419,7 @@
mService.getBinderService().requestState(token, DEFAULT_DEVICE_STATE.getIdentifier(),
0 /* flags */);
+ flushHandler();
assertEquals(callback.getLastNotifiedStatus(token),
TestDeviceStateManagerCallback.STATUS_ACTIVE);
@@ -372,6 +429,7 @@
public void requestState_flagCancelWhenBaseChanges() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
final IBinder token = new Binder();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -379,6 +437,10 @@
mService.getBinderService().requestState(token, OTHER_DEVICE_STATE.getIdentifier(),
DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES);
+ // Flush the handler twice. The first flush ensures the request is added and the policy is
+ // notified, while the second flush ensures the callback is notified once the change is
+ // committed.
+ flushHandler(2 /* count */);
assertEquals(callback.getLastNotifiedStatus(token),
TestDeviceStateManagerCallback.STATUS_ACTIVE);
@@ -391,6 +453,7 @@
OTHER_DEVICE_STATE.getIdentifier());
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
+ flushHandler();
// Request is canceled because the base state changed.
assertEquals(callback.getLastNotifiedStatus(token),
@@ -407,6 +470,7 @@
public void requestState_becomesUnsupported() throws RemoteException {
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
+ flushHandler();
final IBinder token = new Binder();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -414,6 +478,7 @@
mService.getBinderService().requestState(token, OTHER_DEVICE_STATE.getIdentifier(),
0 /* flags */);
+ flushHandler();
assertEquals(callback.getLastNotifiedStatus(token),
TestDeviceStateManagerCallback.STATUS_ACTIVE);
@@ -425,6 +490,7 @@
OTHER_DEVICE_STATE.getIdentifier());
mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE });
+ flushHandler();
// Request is canceled because the state is no longer supported.
assertEquals(callback.getLastNotifiedStatus(token),
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateTest.java
index b5c8053..e286cb2 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateTest.java
@@ -41,24 +41,26 @@
@Test
public void testConstruct() {
final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE /* identifier */,
- "CLOSED" /* name */);
+ "CLOSED" /* name */, DeviceState.FLAG_CANCEL_STICKY_REQUESTS /* flags */);
assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE);
assertEquals(state.getName(), "CLOSED");
+ assertEquals(state.getFlags(), DeviceState.FLAG_CANCEL_STICKY_REQUESTS);
}
@Test
public void testConstruct_nullName() {
final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE /* identifier */,
- null /* name */);
+ null /* name */, 0/* flags */);
assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE);
assertNull(state.getName());
+ assertEquals(state.getFlags(), 0);
}
@Test
public void testConstruct_tooLargeIdentifier() {
assertThrows(IllegalArgumentException.class, () -> {
final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE + 1 /* identifier */,
- null /* name */);
+ null /* name */, 0 /* flags */);
});
}
@@ -66,7 +68,7 @@
public void testConstruct_tooSmallIdentifier() {
assertThrows(IllegalArgumentException.class, () -> {
final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE - 1 /* identifier */,
- null /* name */);
+ null /* name */, 0 /* flags */);
});
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
new file mode 100644
index 0000000..c9cf2f0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2021 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.devicestate;
+
+import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
+import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
+import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import android.annotation.Nullable;
+import android.hardware.devicestate.DeviceStateRequest;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.annotation.NonNull;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link OverrideRequestController}.
+ * <p/>
+ * Run with <code>atest OverrideRequestControllerTest</code>.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public final class OverrideRequestControllerTest {
+ private TestStatusChangeListener mStatusListener;
+ private OverrideRequestController mController;
+
+ @Before
+ public void setup() {
+ mStatusListener = new TestStatusChangeListener();
+ mController = new OverrideRequestController(mStatusListener);
+ }
+
+ @Test
+ public void addRequest() {
+ OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ assertNull(mStatusListener.getLastStatus(request));
+
+ mController.addRequest(request);
+ assertEquals(mStatusListener.getLastStatus(request).intValue(), STATUS_ACTIVE);
+ }
+
+ @Test
+ public void addRequest_suspendExistingRequest() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ assertNull(mStatusListener.getLastStatus(firstRequest));
+
+ mController.addRequest(firstRequest);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ assertNull(mStatusListener.getLastStatus(secondRequest));
+
+ mController.addRequest(secondRequest);
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ }
+
+ @Test
+ public void addRequest_cancelActiveRequest() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.cancelRequest(secondRequest.getToken());
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+ }
+
+ @Test
+ public void addRequest_cancelSuspendedRequest() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.cancelRequest(firstRequest.getToken());
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
+ }
+
+ @Test
+ public void handleBaseStateChanged() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */,
+ DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.handleBaseStateChanged();
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+ }
+
+ @Test
+ public void handleProcessDied() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.handleProcessDied(1);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+
+ mController.handleProcessDied(0);
+
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
+ }
+
+ @Test
+ public void handleProcessDied_stickyRequests() {
+ mController.setStickyRequestsAllowed(true);
+
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
+ 0 /* requestedState */, 0 /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.handleProcessDied(1);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.cancelStickyRequests();
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+ }
+
+ @Test
+ public void handleNewSupportedStates() {
+ OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 1 /* requestedState */, 0 /* flags */);
+ OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+ 2 /* requestedState */, 0 /* flags */);
+
+ mController.addRequest(firstRequest);
+ mController.addRequest(secondRequest);
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+
+ mController.handleNewSupportedStates(new int[]{ 0, 1 });
+
+ assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+
+ mController.handleNewSupportedStates(new int[]{ 0 });
+
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
+ }
+
+ private static final class TestStatusChangeListener implements
+ OverrideRequestController.StatusChangeListener {
+ private Map<OverrideRequest, Integer> mLastStatusMap = new HashMap<>();
+
+ @Override
+ public void onStatusChanged(@NonNull OverrideRequest request, int newStatus) {
+ mLastStatusMap.put(request, newStatus);
+ }
+
+ @Nullable
+ public Integer getLastStatus(OverrideRequest request) {
+ return mLastStatusMap.get(request);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
index 4d2d2f1..8e2c1f0 100644
--- a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
@@ -150,8 +150,9 @@
provider.setListener(listener);
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
- final DeviceState[] expectedStates = new DeviceState[]{ new DeviceState(1, ""),
- new DeviceState(2, "") };
+ final DeviceState[] expectedStates = new DeviceState[]{
+ new DeviceState(1, "", 0 /* flags */),
+ new DeviceState(2, "", 0 /* flags */) };
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
verify(listener).onStateChanged(mIntegerCaptor.capture());
@@ -187,8 +188,9 @@
provider.setListener(listener);
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
- final DeviceState[] expectedStates = new DeviceState[]{ new DeviceState(1, ""),
- new DeviceState(2, "CLOSED") };
+ final DeviceState[] expectedStates = new DeviceState[]{
+ new DeviceState(1, "", 0 /* flags */),
+ new DeviceState(2, "CLOSED", 0 /* flags */) };
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider has not yet been notified of
@@ -264,8 +266,11 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
assertArrayEquals(
- new DeviceState[]{ new DeviceState(1, "CLOSED"), new DeviceState(2, "HALF_OPENED"),
- new DeviceState(3, "OPENED") }, mDeviceStateArrayCaptor.getValue());
+ new DeviceState[]{
+ new DeviceState(1, "CLOSED", 0 /* flags */),
+ new DeviceState(2, "HALF_OPENED", 0 /* flags */),
+ new DeviceState(3, "OPENED", 0 /* flags */) },
+ mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider has not yet been notified of
// the initial sensor state.
verify(listener, never()).onStateChanged(mIntegerCaptor.capture());
@@ -350,8 +355,10 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
assertArrayEquals(
- new DeviceState[]{ new DeviceState(1, "CLOSED"), new DeviceState(2, "HALF_OPENED"),
- }, mDeviceStateArrayCaptor.getValue());
+ new DeviceState[]{
+ new DeviceState(1, "CLOSED", 0 /* flags */),
+ new DeviceState(2, "HALF_OPENED", 0 /* flags */)
+ }, mDeviceStateArrayCaptor.getValue());
// onStateChanged() should be called because the provider could not find the sensor.
verify(listener).onStateChanged(mIntegerCaptor.capture());
assertEquals(1, mIntegerCaptor.getValue().intValue());
diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
index 5012ca9..6e3f754 100644
--- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
@@ -210,7 +210,7 @@
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
return mNotifierMock;
}
@@ -298,6 +298,7 @@
BatteryStats.SERVICE_NAME)),
mInjector.createSuspendBlocker(mService, "testBlocker"),
null,
+ null,
null);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 5eabc1b..3d64d4b 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -215,7 +215,7 @@
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
return mNotifierMock;
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index 222c692..6b36fe8 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -69,7 +69,7 @@
@Before
public void setUp() {
- mDetector = new SingleKeyGestureDetector(mContext);
+ mDetector = new SingleKeyGestureDetector();
initSingleKeyGestureRules();
mWaitTimeout = ViewConfiguration.getMultiPressTimeout() + 50;
mLongPressTime = ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout() + 50;
@@ -78,7 +78,7 @@
}
private void initSingleKeyGestureRules() {
- mDetector.addRule(new SingleKeyGestureDetector.SingleKeyRule(KEYCODE_POWER,
+ mDetector.addRule(new SingleKeyGestureDetector.SingleKeyRule(mContext, KEYCODE_POWER,
KEY_LONGPRESS | KEY_VERYLONGPRESS) {
@Override
int getMaxMultiPressCount() {