diff options
author | Eric Arseneau <earseneau@google.com> | 2021-12-19 22:49:43 -0800 |
---|---|---|
committer | Eric Arseneau <earseneau@google.com> | 2021-12-22 12:52:50 -0800 |
commit | 3e8cb98421761bb7dfafe59a22a15fe2e176f272 (patch) | |
tree | 754d2b985bde4574c8789e254b120866cf23002a | |
parent | 48cbb14e1815430efd7ff5086e7a4c70e75d475f (diff) | |
parent | 6c2cb6876a30dee0b94d946ca529e06cd96b9642 (diff) |
Merge s-mpr-2021-12-05
Change-Id: Ic2889f5eb531008340529eadc36ec8efc62b1984
883 files changed, 23800 insertions, 5222 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 9eb7bb7149ef..84d05c8b4144 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -2918,6 +2918,13 @@ public class DeviceIdleController extends SystemService reasonCode, reason).sendToTarget(); } reportTempWhitelistChangedLocked(uid, true); + } else { + // The uid is already temp allowlisted, only need to update AMS for temp allowlist + // duration. + if (mLocalActivityManager != null) { + mLocalActivityManager.updateDeviceIdleTempAllowlist(null, uid, true, + duration, tempAllowListType, reasonCode, reason, callingUid); + } } } if (informWhitelistChanged) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 591e8ba859fc..4becc6b7c44a 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1008,13 +1008,21 @@ public class JobSchedulerService extends com.android.server.SystemService } @Override - public void onUserUnlocked(@NonNull TargetUser user) { + public void onUserStarting(@NonNull TargetUser user) { synchronized (mLock) { - // Note that the user has started after its unlocked instead of when the user - // actually starts because the storage won't be decrypted until unlock. mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier()); } - // Let's kick any outstanding jobs for this user. + // The user is starting but credential encrypted storage is still locked. + // Only direct-boot-aware jobs can safely run. + // Let's kick off any eligible jobs for this user. + mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); + } + + @Override + public void onUserUnlocked(@NonNull TargetUser user) { + // The user is fully unlocked and credential encrypted storage is now decrypted. + // Direct-boot-UNaware jobs can now safely run. + // Let's kick off any outstanding jobs for this user. mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); } diff --git a/apex/media/OWNERS b/apex/media/OWNERS index ced2fb5e2dcd..73f02d32ce13 100644 --- a/apex/media/OWNERS +++ b/apex/media/OWNERS @@ -1,10 +1,10 @@ -andrewlewis@google.com -aquilescanta@google.com -chz@google.com +# Bug component: 1344 hdmoon@google.com hkuang@google.com jinpark@google.com klhyun@google.com lnilsson@google.com -marcone@google.com sungsoo@google.com + +# go/android-fwk-media-solutions for info on areas of ownership. +include platform/frameworks/av:/media/janitors/media_solutions_OWNERS diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp index b2b66c27f795..3534624a58a2 100644 --- a/cmds/bootanimation/Android.bp +++ b/cmds/bootanimation/Android.bp @@ -71,7 +71,7 @@ cc_library_shared { "libui", "libjnigraphics", "libEGL", - "libGLESv1_CM", + "libGLESv2", "libgui", ], } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 25a8e482fd00..53a2ebcdb061 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -52,9 +52,8 @@ #include <gui/DisplayEventReceiver.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #include <EGL/eglext.h> #include "BootAnimation.h" @@ -108,6 +107,93 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; 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"( + precision mediump float; + attribute vec4 aPosition; + attribute highp vec2 aUv; + varying highp vec2 vUv; + void main() { + gl_Position = aPosition; + vUv = aUv; + })"; +static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( + precision mediump float; + const float cWhiteMaskThreshold = 0.05; + 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); + float r = mask.r; + float g = mask.g; + float b = mask.b; + float a = mask.a; + // If all channels have values, render pixel as a shade of white. + float useWhiteMask = step(cWhiteMaskThreshold, r) + * step(cWhiteMaskThreshold, g) + * step(cWhiteMaskThreshold, b) + * step(cWhiteMaskThreshold, a); + vec4 color = r * mix(uStartColor0, uEndColor0, uColorProgress) + + g * mix(uStartColor1, uEndColor1, uColorProgress) + + b * mix(uStartColor2, uEndColor2, uColorProgress) + + a * mix(uStartColor3, uEndColor3, uColorProgress); + color = mix(color, vec4(vec3((r + g + b + a) * 0.25), 1.0), useWhiteMask); + 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; + uniform float uFade; + varying highp vec2 vUv; + void main() { + vec4 color = texture2D(uTexture, vUv); + 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; + uniform sampler2D uTexture; + uniform vec4 uCropArea; + varying highp vec2 vUv; + void main() { + vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x), + mix(uCropArea.y, uCropArea.w, vUv.y)); + gl_FragColor = texture2D(uTexture, uv); + })"; + +static GLfloat quadPositions[] = { + -0.5f, -0.5f, + +0.5f, -0.5f, + +0.5f, +0.5f, + +0.5f, +0.5f, + -0.5f, +0.5f, + -0.5f, -0.5f +}; +static GLfloat quadUVs[] = { + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f +}; // --------------------------------------------------------------------------- @@ -163,7 +249,8 @@ void BootAnimation::binderDied(const wp<IBinder>&) { 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) { @@ -177,6 +264,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm 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); @@ -192,13 +283,14 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm } 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(); @@ -211,7 +303,6 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; @@ -239,18 +330,19 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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. @@ -265,7 +357,6 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { const int w = bitmapInfo.width; const int h = bitmapInfo.height; - GLint crop[4] = { 0, h, w, -h }; int tw = 1 << (31 - __builtin_clz(w)); int th = 1 << (31 - __builtin_clz(h)); if (tw < w) tw <<= 1; @@ -299,7 +390,10 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { break; } - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); *width = w; *height = h; @@ -472,7 +566,9 @@ status_t BootAnimation::readyToRun() { eglInitialize(display, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); - EGLContext context = eglCreateContext(display, config, nullptr, nullptr); + // Initialize egl context with client version number 2.0. + EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -505,11 +601,6 @@ status_t BootAnimation::readyToRun() { void BootAnimation::projectSceneToWindow() { glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, static_cast<float>(mWidth), 0, static_cast<float>(mHeight), -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); } void BootAnimation::resizeSurface(int newWidth, int newHeight) { @@ -613,8 +704,76 @@ void BootAnimation::findBootAnimationFile() { } } +GLuint compileShader(GLenum shaderType, const GLchar *source) { + GLuint shader = glCreateShader(shaderType); + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + GLint isCompiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); + if (isCompiled == GL_FALSE) { + SLOGE("Compile shader failed. Shader type: %d", shaderType); + GLint maxLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + std::vector<GLchar> errorLog(maxLength); + glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]); + SLOGE("Shader compilation error: %s", &errorLog[0]); + return 0; + } + return shader; +} + +GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { + GLuint program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + GLint isLinked = 0; + glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked); + if (isLinked == GL_FALSE) { + SLOGE("Linking shader failed. Shader handles: vert %d, frag %d", + vertexShader, fragmentShader); + return 0; + } + return program; +} + +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, 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); + + // Initialize image shader. + mImageShader = linkShader(vertexShader, imageFragmentShader); + GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION); + GLint uvLocation = glGetAttribLocation(mImageShader, A_UV); + mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE); + mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); + + // Initialize text shader. + mTextShader = linkShader(vertexShader, textFragmentShader); + positionLocation = glGetAttribLocation(mTextShader, A_POSITION); + uvLocation = glGetAttribLocation(mTextShader, A_UV); + mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE); + mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA); + glEnableVertexAttribArray(positionLocation); + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs); + glEnableVertexAttribArray(uvLocation); +} + bool BootAnimation::threadLoop() { bool result; + initShaders(); + // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { @@ -636,6 +795,8 @@ bool BootAnimation::threadLoop() { } bool BootAnimation::android() { + glActiveTexture(GL_TEXTURE0); + SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); @@ -644,19 +805,16 @@ bool BootAnimation::android() { mCallbacks->init({}); // clear screen - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); + glUseProgram(mImageShader); + glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); - glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { @@ -679,12 +837,12 @@ bool BootAnimation::android() { glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); - glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); - glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h); + drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); - glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); + drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) @@ -779,6 +937,20 @@ static bool parseColor(const char str[7], float color[3]) { 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); @@ -811,10 +983,10 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { status = initTexture(font->map, &font->texture.w, &font->texture.h); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else if (fallback != nullptr) { status = initTexture(&font->texture, mAssets, fallback); } else { @@ -829,40 +1001,11 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) { return status; } -void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth, - const int frameHeight, const Animation::Part& part, - const int fadedFramesCount) { - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); - glDisable(GL_TEXTURE_2D); - // avoid creating a hole due to mixing result alpha with GL_REPLACE texture - glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - - const float alpha = static_cast<float>(fadedFramesCount) / part.framesToFadeCount; - glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha); - - const float frameStartX = static_cast<float>(frameLeft); - const float frameStartY = static_cast<float>(frameBottom); - const float frameEndX = frameStartX + frameWidth; - const float frameEndY = frameStartY + frameHeight; - const GLfloat frameRect[] = { - frameStartX, frameStartY, - frameEndX, frameStartY, - frameEndX, frameEndY, - frameStartX, frameEndY - }; - glVertexPointer(2, GL_FLOAT, 0, frameRect); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); -} - void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { glEnable(GL_BLEND); // Allow us to draw on top of the animation glBindTexture(GL_TEXTURE_2D, font.texture.name); + glUseProgram(mTextShader); + glUniform1i(mTextTextureLocation, 0); const int len = strlen(str); const int strWidth = font.char_width * len; @@ -878,8 +1021,6 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* *y = mHeight + *y - font.char_height; } - int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; - for (int i = 0; i < len; i++) { char c = str[i]; @@ -891,13 +1032,13 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters const int row = charPos / FONT_NUM_COLS; const int col = charPos % FONT_NUM_COLS; - cropRect[0] = col * font.char_width; // Left of column - cropRect[1] = row * font.char_height * 2; // Top of row - // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line - cropRect[1] += bold ? 2 * font.char_height : font.char_height; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); - - glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); + // Bold fonts are expected in the second half of each row. + float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS; + float u0 = ((float)col) / FONT_NUM_COLS; + float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2; + float u1 = u0 + 1.0f / FONT_NUM_COLS; + glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1); + drawTexturedQuad(*x, *y, font.char_width, font.char_height); *x += font.char_width; } @@ -951,6 +1092,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); + std::string dynamicColoringPartName = ""; + bool postDynamicColoring = false; // Parse the description file for (;;) { @@ -965,11 +1108,19 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { int pause = 0; int progress = 0; int framesToFadeCount = 0; + int colorTransitionStart = 0; + int colorTransitionEnd = 0; char path[ANIM_ENTRY_NAME_MAX]; 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; @@ -984,6 +1135,18 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } + } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s %d %d", + dynamicColoringPartNameBuffer, + start_color_0, start_color_1, start_color_2, start_color_3, + &colorTransitionStart, &colorTransitionEnd)) { + 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]); + animation.colorTransitionStart = colorTransitionStart; + animation.colorTransitionEnd = colorTransitionEnd; + 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') { @@ -996,6 +1159,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "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; @@ -1179,19 +1352,16 @@ bool BootAnimation::movie() { // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); bool clockFontInitialized = false; if (mClockEnabled) { clockFontInitialized = @@ -1206,6 +1376,10 @@ bool BootAnimation::movie() { mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } + if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) { + initDynamicColors(); + } + playAnimation(*mAnimation); if (mTimeCheckThread != nullptr) { @@ -1231,6 +1405,55 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part, (lastDisplayedProgress == 0 || lastDisplayedProgress == 100); } +// Linear mapping from range <a1, a2> to range <b1, b2> +float mapLinear(float x, float a1, float a2, float b1, float b2) { + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); +} + +void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) { + // Map coordinates from screen space to world space. + float x0 = mapLinear(xStart, 0, mWidth, -1, 1); + float y0 = mapLinear(yStart, 0, mHeight, -1, 1); + float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1); + float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1); + // Update quad vertex positions. + quadPositions[0] = x0; + quadPositions[1] = y0; + quadPositions[2] = x1; + quadPositions[3] = y0; + quadPositions[4] = x1; + quadPositions[5] = y1; + quadPositions[6] = x1; + quadPositions[7] = y1; + quadPositions[8] = x0; + quadPositions[9] = y1; + quadPositions[10] = x0; + quadPositions[11] = y0; + glDrawArrays(GL_TRIANGLES, 0, + 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; @@ -1243,7 +1466,6 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); - glBindTexture(GL_TEXTURE_2D, 0); // Handle animation package if (part.animation != nullptr) { @@ -1274,6 +1496,19 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j<fcount ; j++) { if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break; + // Color progress is + // - the animation progress, normalized from + // [colorTransitionStart,colorTransitionEnd] to [0, 1] for the dynamic coloring + // part. + // - 0 for parts that come before, + // - 1 for parts that come after. + float colorProgress = part.useDynamicColoring + ? fmin(fmax( + ((float)j - animation.colorTransitionStart) / + fmax(animation.colorTransitionEnd - + animation.colorTransitionStart, 1.0f), 0.0f), 1.0f) + : (part.postDynamicColoring ? 1 : 0); + processDisplayEvents(); const int animationX = (mWidth - animation.width) / 2; @@ -1285,44 +1520,38 @@ bool BootAnimation::playAnimation(const Animation& animation) { if (r > 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { - if (part.count != 1) { - glGenTextures(1, &frame.tid); - glBindTexture(GL_TEXTURE_2D, frame.tid); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } + 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); - glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight); + float fade = 0; // if the part hasn't been stopped yet then continue fading if necessary if (exitPending() && part.hasFadingPhase()) { - fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part, - ++fadedFramesCount); + fade = static_cast<float>(++fadedFramesCount) / part.framesToFadeCount; if (fadedFramesCount >= part.framesToFadeCount) { fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading } } + glUseProgram(mImageShader); + glUniform1i(mImageTextureLocation, 0); + glUniform1f(mImageFadeLocation, fade); + if (animation.dynamicColoringEnabled) { + glUniform1f(mImageColorProgressLocation, colorProgress); + } + glEnable(GL_BLEND); + drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); + glDisable(GL_BLEND); if (mClockEnabled && mTimeIsAccurate && validClock(part)) { drawClock(animation.clockFont, part.clockPosX, part.clockPosY); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index f8a31c6d8790..7a597da533ee 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -31,7 +31,7 @@ #include <binder/IBinder.h> #include <EGL/egl.h> -#include <GLES/gl.h> +#include <GLES2/gl2.h> namespace android { @@ -53,7 +53,7 @@ public: }; struct Font { - FileMap* map; + FileMap* map = nullptr; Texture texture; int char_width; int char_height; @@ -62,7 +62,7 @@ public: struct Animation { struct Frame { String8 name; - FileMap* map; + FileMap* map = nullptr; int trimX; int trimY; int trimWidth; @@ -90,6 +90,10 @@ public: 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,12 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; + // Controls if dynamic coloring is enabled for the whole animation. + bool dynamicColoringEnabled = false; + int colorTransitionStart = 0; // Start frame of dynamic color transition. + int colorTransitionEnd = 0; // End frame of dynamic color transition. + 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,9 +173,12 @@ private: 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(); bool movie(); void drawText(const char* str, const Font& font, bool bold, int* x, int* y); @@ -173,6 +186,7 @@ private: void drawProgress(int percent, const Font& font, const int xPos, const int yPos); void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight, const Animation::Part& part, int fadedFramesCount); + void drawTexturedQuad(float xStart, float yStart, float width, float height); bool validClock(const Animation::Part& part); Animation* loadAnimation(const String8&); bool playAnimation(const Animation&); @@ -192,6 +206,7 @@ private: void checkExit(); void handleViewport(nsecs_t timestep); + void initDynamicColors(); sp<SurfaceComposerClient> mSession; AssetManager mAssets; @@ -218,6 +233,13 @@ private: sp<TimeCheckThread> mTimeCheckThread = nullptr; sp<Callbacks> mCallbacks; Animation* mAnimation = nullptr; + GLuint mImageShader; + GLuint mTextShader; + GLuint mImageFadeLocation; + GLuint mImageTextureLocation; + GLuint mTextCropAreaLocation; + GLuint mTextTextureLocation; + GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- diff --git a/cmds/bootanimation/OWNERS b/cmds/bootanimation/OWNERS new file mode 100644 index 000000000000..b6fb007bea52 --- /dev/null +++ b/cmds/bootanimation/OWNERS @@ -0,0 +1,3 @@ +dupin@google.com +shanh@google.com +jreck@google.com diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 4376d225e676..f53c5b6c9748 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -771,6 +771,11 @@ public class ActivityManager { return procState >= PROCESS_STATE_TRANSIENT_BACKGROUND; } + /** @hide Should this process state be considered in the cache? */ + public static final boolean isProcStateCached(int procState) { + return procState >= PROCESS_STATE_CACHED_ACTIVITY; + } + /** @hide Is this a foreground service type? */ public static boolean isForegroundService(int procState) { return procState == PROCESS_STATE_FOREGROUND_SERVICE; diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index fe75415968aa..98ffb197f311 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -156,6 +156,7 @@ public abstract class ActivityManagerInternal { /** * Update information about which app IDs are on the temp allowlist. * @param appids the updated list of appIds in temp allowlist. + * If null, it is to update only changingUid. * @param changingUid uid to add or remove to temp allowlist. * @param adding true to add to temp allowlist, false to remove from temp allowlist. * @param durationMs when adding is true, the duration to be in temp allowlist. @@ -165,7 +166,7 @@ public abstract class ActivityManagerInternal { * @param callingUid the callingUid that setup this temp allowlist, only valid when param adding * is true. */ - public abstract void updateDeviceIdleTempAllowlist(int[] appids, int changingUid, + public abstract void updateDeviceIdleTempAllowlist(@Nullable int[] appids, int changingUid, boolean adding, long durationMs, @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason, int callingUid); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4db1f71e8256..1397f5ea10dc 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2721,10 +2721,13 @@ class ContextImpl extends Context { // need to override their display in ResourcesManager. baseContext.mForceDisplayOverrideInResources = false; baseContext.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; - baseContext.mDisplay = display; final Resources windowContextResources = createWindowContextResources(baseContext); baseContext.setResources(windowContextResources); + // Associate the display with window context resources so that configuration update from + // the server side will also apply to the display's metrics. + baseContext.mDisplay = ResourcesManager.getInstance() + .getAdjustedDisplay(display.getDisplayId(), windowContextResources); return baseContext; } diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java index 5964f71d28db..babeb08caff7 100644 --- a/core/java/android/app/GameManager.java +++ b/core/java/android/app/GameManager.java @@ -135,6 +135,7 @@ public final class GameManager { throw e.rethrowFromSystemServer(); } } + /** * Returns a list of supported game modes for a given package. * <p> @@ -151,4 +152,20 @@ public final class GameManager { } } + /** + * Returns if ANGLE is enabled for a given package. + * <p> + * The caller must have {@link android.Manifest.permission#MANAGE_GAME_MODE}. + * + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) + public @GameMode boolean isAngleEnabled(@NonNull String packageName) { + try { + return mService.getAngleEnabled(packageName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl index 4bf8a3f77bca..189f0a2fca23 100644 --- a/core/java/android/app/IGameManagerService.aidl +++ b/core/java/android/app/IGameManagerService.aidl @@ -23,4 +23,5 @@ interface IGameManagerService { int getGameMode(String packageName, int userId); void setGameMode(String packageName, int gameMode, int userId); int[] getAvailableGameModes(String packageName); + boolean getAngleEnabled(String packageName, int userId); }
\ No newline at end of file diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4b054f49d910..61b1abe25ca2 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1884,6 +1884,14 @@ public class Notification implements Parcelable * clicks. To launch an activity in those cases, provide a {@link PendingIntent} for the * activity itself. * + * <p>How an Action is displayed, including whether the {@code icon}, {@code text}, or + * both are displayed or required, depends on where and how the action is used, and the + * {@link Style} applied to the Notification. + * + * <p>When the {@code title} is a {@link android.text.Spanned}, any colors set by a + * {@link ForegroundColorSpan} or {@link TextAppearanceSpan} may be removed or displayed + * with an altered in luminance to ensure proper contrast within the Notification. + * * @param icon icon to show for this action * @param title the title of the action * @param intent the {@link PendingIntent} to fire when users trigger this action @@ -5387,8 +5395,8 @@ public class Notification implements Parcelable contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor); // Use different highlighted colors for conversations' unread count if (p.mHighlightExpander) { - pillColor = Colors.flattenAlpha(getPrimaryAccentColor(p), bgColor); - textColor = Colors.flattenAlpha(bgColor, pillColor); + pillColor = Colors.flattenAlpha(getColors(p).getTertiaryAccentColor(), bgColor); + textColor = Colors.flattenAlpha(getColors(p).getOnAccentTextColor(), pillColor); } contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor); contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor); @@ -6121,21 +6129,22 @@ public class Notification implements Parcelable if (emphasizedMode) { // change the background bgColor CharSequence title = action.title; - ColorStateList[] outResultColor = new ColorStateList[1]; int buttonFillColor = getColors(p).getSecondaryAccentColor(); if (isLegacy()) { title = ContrastColorUtil.clearColorSpans(title); } else { - int notifBackgroundColor = getColors(p).getBackgroundColor(); - title = ensureColorSpanContrast(title, notifBackgroundColor, outResultColor); + // Check for a full-length span color to use as the button fill color. + Integer fullLengthColor = getFullLengthSpanColor(title); + if (fullLengthColor != null) { + // Ensure the custom button fill has 1.3:1 contrast w/ notification bg. + int notifBackgroundColor = getColors(p).getBackgroundColor(); + buttonFillColor = ensureButtonFillContrast( + fullLengthColor, notifBackgroundColor); + } + // Remove full-length color spans and ensure text contrast with the button fill. + title = ensureColorSpanContrast(title, buttonFillColor); } button.setTextViewText(R.id.action0, processTextSpans(title)); - boolean hasColorOverride = outResultColor[0] != null; - if (hasColorOverride) { - // There's a span spanning the full text, let's take it and use it as the - // background color - buttonFillColor = outResultColor[0].getDefaultColor(); - } final int textColor = ContrastColorUtil.resolvePrimaryColor(mContext, buttonFillColor, mInNightMode); button.setTextColor(R.id.action0, textColor); @@ -6168,17 +6177,58 @@ public class Notification implements Parcelable } /** - * Ensures contrast on color spans against a background color. also returns the color of the - * text if a span was found that spans over the whole text. + * Extract the color from a full-length span from the text. + * + * @param charSequence the charSequence containing spans + * @return the raw color of the text's last full-length span containing a color, or null if + * no full-length span sets the text color. + * @hide + */ + @VisibleForTesting + @Nullable + public static Integer getFullLengthSpanColor(CharSequence charSequence) { + // NOTE: this method preserves the functionality that for a CharSequence with multiple + // full-length spans, the color of the last one is used. + Integer result = null; + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + // First read through all full-length spans to get the button fill color, which will + // be used as the background color for ensuring contrast of non-full-length spans. + for (Object span : spans) { + int spanStart = ss.getSpanStart(span); + int spanEnd = ss.getSpanEnd(span); + boolean fullLength = (spanEnd - spanStart) == charSequence.length(); + if (!fullLength) { + continue; + } + if (span instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) span; + ColorStateList textColor = originalSpan.getTextColor(); + if (textColor != null) { + result = textColor.getDefaultColor(); + } + } else if (span instanceof ForegroundColorSpan) { + ForegroundColorSpan originalSpan = (ForegroundColorSpan) span; + result = originalSpan.getForegroundColor(); + } + } + } + return result; + } + + /** + * Ensures contrast on color spans against a background color. + * Note that any full-length color spans will be removed instead of being contrasted. * * @param charSequence the charSequence on which the spans are * @param background the background color to ensure the contrast against - * @param outResultColor an array in which a color will be returned as the first element if - * there exists a full length color span. * @return the contrasted charSequence + * @hide */ - private static CharSequence ensureColorSpanContrast(CharSequence charSequence, - int background, ColorStateList[] outResultColor) { + @VisibleForTesting + public static CharSequence ensureColorSpanContrast(CharSequence charSequence, + int background) { if (charSequence instanceof Spanned) { Spanned ss = (Spanned) charSequence; Object[] spans = ss.getSpans(0, ss.length(), Object.class); @@ -6195,19 +6245,19 @@ public class Notification implements Parcelable TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; ColorStateList textColor = originalSpan.getTextColor(); if (textColor != null) { - int[] colors = textColor.getColors(); - int[] newColors = new int[colors.length]; - for (int i = 0; i < newColors.length; i++) { - boolean isBgDark = isColorDark(background); - newColors[i] = ContrastColorUtil.ensureLargeTextContrast( - colors[i], background, isBgDark); - } - textColor = new ColorStateList(textColor.getStates().clone(), - newColors); if (fullLength) { - outResultColor[0] = textColor; // Let's drop the color from the span textColor = null; + } else { + int[] colors = textColor.getColors(); + int[] newColors = new int[colors.length]; + for (int i = 0; i < newColors.length; i++) { + boolean isBgDark = isColorDark(background); + newColors[i] = ContrastColorUtil.ensureLargeTextContrast( + colors[i], background, isBgDark); + } + textColor = new ColorStateList(textColor.getStates().clone(), + newColors); } resultSpan = new TextAppearanceSpan( originalSpan.getFamily(), @@ -6217,15 +6267,14 @@ public class Notification implements Parcelable originalSpan.getLinkTextColor()); } } else if (resultSpan instanceof ForegroundColorSpan) { - ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan; - int foregroundColor = originalSpan.getForegroundColor(); - boolean isBgDark = isColorDark(background); - foregroundColor = ContrastColorUtil.ensureLargeTextContrast( - foregroundColor, background, isBgDark); if (fullLength) { - outResultColor[0] = ColorStateList.valueOf(foregroundColor); resultSpan = null; } else { + ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan; + int foregroundColor = originalSpan.getForegroundColor(); + boolean isBgDark = isColorDark(background); + foregroundColor = ContrastColorUtil.ensureLargeTextContrast( + foregroundColor, background, isBgDark); resultSpan = new ForegroundColorSpan(foregroundColor); } } else { @@ -6247,13 +6296,29 @@ public class Notification implements Parcelable * * @param color the color to check * @return true if the color has higher contrast with white than black + * @hide */ - private static boolean isColorDark(int color) { + public static boolean isColorDark(int color) { // as per ContrastColorUtil.shouldUseDark, this uses the color contrast midpoint. return ContrastColorUtil.calculateLuminance(color) <= 0.17912878474; } /** + * Finds a button fill color with sufficient contrast over bg (1.3:1) that has the same hue + * as the original color, but is lightened or darkened depending on whether the background + * is dark or light. + * + * @hide + */ + @VisibleForTesting + public static int ensureButtonFillContrast(int color, int bg) { + return isColorDark(bg) + ? ContrastColorUtil.findContrastColorAgainstDark(color, bg, true, 1.3) + : ContrastColorUtil.findContrastColor(color, bg, true, 1.3); + } + + + /** * @return Whether we are currently building a notification from a legacy (an app that * doesn't create material notifications by itself) app. */ @@ -6441,25 +6506,34 @@ public class Notification implements Parcelable if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N && !styleDisplaysCustomViewInline()) { - if (mN.contentView == null) { - mN.contentView = createContentView(); + RemoteViews newContentView = mN.contentView; + RemoteViews newBigContentView = mN.bigContentView; + RemoteViews newHeadsUpContentView = mN.headsUpContentView; + if (newContentView == null) { + newContentView = createContentView(); mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, - mN.contentView.getSequenceNumber()); + newContentView.getSequenceNumber()); } - if (mN.bigContentView == null) { - mN.bigContentView = createBigContentView(); - if (mN.bigContentView != null) { + if (newBigContentView == null) { + newBigContentView = createBigContentView(); + if (newBigContentView != null) { mN.extras.putInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, - mN.bigContentView.getSequenceNumber()); + newBigContentView.getSequenceNumber()); } } - if (mN.headsUpContentView == null) { - mN.headsUpContentView = createHeadsUpContentView(); - if (mN.headsUpContentView != null) { + if (newHeadsUpContentView == null) { + newHeadsUpContentView = createHeadsUpContentView(); + if (newHeadsUpContentView != null) { mN.extras.putInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, - mN.headsUpContentView.getSequenceNumber()); + newHeadsUpContentView.getSequenceNumber()); } } + // Don't set any of the content views until after they have all been generated, + // to avoid the generated .contentView triggering the logic which skips generating + // the .bigContentView. + mN.contentView = newContentView; + mN.bigContentView = newBigContentView; + mN.headsUpContentView = newHeadsUpContentView; } if ((mN.defaults & DEFAULT_LIGHTS) != 0) { @@ -12305,6 +12379,8 @@ public class Notification implements Parcelable private int mSecondaryTextColor = COLOR_INVALID; private int mPrimaryAccentColor = COLOR_INVALID; private int mSecondaryAccentColor = COLOR_INVALID; + private int mTertiaryAccentColor = COLOR_INVALID; + private int mOnAccentTextColor = COLOR_INVALID; private int mErrorColor = COLOR_INVALID; private int mContrastColor = COLOR_INVALID; private int mRippleAlpha = 0x33; @@ -12362,7 +12438,7 @@ public class Notification implements Parcelable if (isColorized) { if (rawColor == COLOR_DEFAULT) { - int[] attrs = {R.attr.colorAccentTertiary}; + int[] attrs = {R.attr.colorAccentSecondary}; try (TypedArray ta = obtainDayNightAttributes(ctx, attrs)) { mBackgroundColor = getColor(ta, 0, Color.WHITE); } @@ -12379,6 +12455,8 @@ public class Notification implements Parcelable mContrastColor = mPrimaryTextColor; mPrimaryAccentColor = mPrimaryTextColor; mSecondaryAccentColor = mSecondaryTextColor; + mTertiaryAccentColor = flattenAlpha(mPrimaryTextColor, mBackgroundColor); + mOnAccentTextColor = mBackgroundColor; mErrorColor = mPrimaryTextColor; mRippleAlpha = 0x33; } else { @@ -12389,6 +12467,8 @@ public class Notification implements Parcelable R.attr.textColorSecondary, R.attr.colorAccent, R.attr.colorAccentSecondary, + R.attr.colorAccentTertiary, + R.attr.textColorOnAccent, R.attr.colorError, R.attr.colorControlHighlight }; @@ -12399,8 +12479,10 @@ public class Notification implements Parcelable mSecondaryTextColor = getColor(ta, 3, COLOR_INVALID); mPrimaryAccentColor = getColor(ta, 4, COLOR_INVALID); mSecondaryAccentColor = getColor(ta, 5, COLOR_INVALID); - mErrorColor = getColor(ta, 6, COLOR_INVALID); - mRippleAlpha = Color.alpha(getColor(ta, 7, 0x33ffffff)); + mTertiaryAccentColor = getColor(ta, 6, COLOR_INVALID); + mOnAccentTextColor = getColor(ta, 7, COLOR_INVALID); + mErrorColor = getColor(ta, 8, COLOR_INVALID); + mRippleAlpha = Color.alpha(getColor(ta, 9, 0x33ffffff)); } mContrastColor = calculateContrastColor(ctx, rawColor, mPrimaryAccentColor, mBackgroundColor, nightMode); @@ -12420,6 +12502,14 @@ public class Notification implements Parcelable if (mSecondaryAccentColor == COLOR_INVALID) { mSecondaryAccentColor = mContrastColor; } + if (mTertiaryAccentColor == COLOR_INVALID) { + mTertiaryAccentColor = mContrastColor; + } + if (mOnAccentTextColor == COLOR_INVALID) { + mOnAccentTextColor = ColorUtils.setAlphaComponent( + ContrastColorUtil.resolvePrimaryColor( + ctx, mTertiaryAccentColor, nightMode), 0xFF); + } if (mErrorColor == COLOR_INVALID) { mErrorColor = mPrimaryTextColor; } @@ -12485,6 +12575,16 @@ public class Notification implements Parcelable return mSecondaryAccentColor; } + /** @return the theme's tertiary accent color for colored UI elements. */ + public @ColorInt int getTertiaryAccentColor() { + return mTertiaryAccentColor; + } + + /** @return the theme's text color to be used on the tertiary accent color. */ + public @ColorInt int getOnAccentTextColor() { + return mOnAccentTextColor; + } + /** * @return the contrast-adjusted version of the color provided by the app, or the * primary text color when colorized. diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 1837fb860b73..6553b61ebbc2 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -260,8 +260,6 @@ public final class NotificationChannel implements Parcelable { private boolean mDemoted = false; private boolean mImportantConvo = false; private long mDeletedTime = DEFAULT_DELETION_TIME_MS; - // If the sound for this channel is missing, e.g. after restore. - private boolean mIsSoundMissing; /** * Creates a notification channel. @@ -717,13 +715,6 @@ public final class NotificationChannel implements Parcelable { } /** - * @hide - */ - public boolean isSoundMissing() { - return mIsSoundMissing; - } - - /** * Returns the audio attributes for sound played by notifications posted to this channel. */ public AudioAttributes getAudioAttributes() { @@ -1007,9 +998,8 @@ public final class NotificationChannel implements Parcelable { // according to the docs because canonicalize method has to handle canonical uris as well. Uri canonicalizedUri = contentResolver.canonicalize(uri); if (canonicalizedUri == null) { - // We got a null because the uri in the backup does not exist here. - mIsSoundMissing = true; - return null; + // We got a null because the uri in the backup does not exist here, so we return default + return Settings.System.DEFAULT_NOTIFICATION_URI; } return contentResolver.uncanonicalize(canonicalizedUri); } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 0faecdbedf67..20d475cd5c4e 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -559,6 +559,53 @@ public class WallpaperManager { return null; } + public Rect peekWallpaperDimensions(Context context, boolean returnDefault, int userId) { + if (mService != null) { + try { + if (!mService.isWallpaperSupported(context.getOpPackageName())) { + return new Rect(); + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + Rect dimensions = null; + synchronized (this) { + try { + Bundle params = new Bundle(); + // Let's peek user wallpaper first. + ParcelFileDescriptor pfd = mService.getWallpaperWithFeature( + context.getOpPackageName(), context.getAttributionTag(), this, + FLAG_SYSTEM, params, userId); + if (pfd != null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options); + dimensions = new Rect(0, 0, options.outWidth, options.outHeight); + } + } catch (RemoteException ex) { + Log.w(TAG, "peek wallpaper dimensions failed", ex); + } + } + // If user wallpaper is unavailable, may be the default one instead. + if ((dimensions == null || dimensions.width() == 0 || dimensions.height() == 0) + && returnDefault) { + InputStream is = openDefaultWallpaper(context, FLAG_SYSTEM); + if (is != null) { + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + dimensions = new Rect(0, 0, options.outWidth, options.outHeight); + } finally { + IoUtils.closeQuietly(is); + } + } + } + return dimensions; + } + void forgetLoadedWallpaper() { synchronized (this) { mCachedWallpaper = null; @@ -1039,6 +1086,17 @@ public class WallpaperManager { } /** + * Peek the dimensions of system wallpaper of the user without decoding it. + * + * @return the dimensions of system wallpaper + * @hide + */ + public Rect peekBitmapDimensions() { + return sGlobals.peekWallpaperDimensions( + mContext, true /* returnDefault */, mContext.getUserId()); + } + + /** * Get an open, readable file descriptor to the given wallpaper image file. * The caller is responsible for closing the file descriptor when done ingesting the file. * diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0e04ad3768c7..0fe80c45ad2a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -9734,6 +9734,27 @@ public class DevicePolicyManager { } /** + * @param userId The user for whom to retrieve information. + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + * @return Details of admin and user which enforced the restriction for the userId. If + * restriction is null, profile owner for the user or device owner info is returned. + * @hide + */ + public @Nullable Bundle getEnforcingAdminAndUserDetails(int userId, + @Nullable String restriction) { + if (mService != null) { + try { + return mService.getEnforcingAdminAndUserDetails(userId, restriction); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return null; + } + + /** * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and * actual package file remain. This function can be called by a device owner, profile owner, or * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index b6c48a1c057b..b5b3934035e0 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -251,6 +251,7 @@ interface IDevicePolicyManager { boolean isNotificationListenerServicePermitted(in String packageName, int userId); Intent createAdminSupportIntent(in String restriction); + Bundle getEnforcingAdminAndUserDetails(int userId,String restriction); boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index dae565e12fd7..67f631f98f0b 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -281,6 +281,32 @@ public class BackupManager { } /** + * 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/app/search/Query.java b/core/java/android/app/search/Query.java index c64e10723ca6..f073b4e50555 100644 --- a/core/java/android/app/search/Query.java +++ b/core/java/android/app/search/Query.java @@ -70,7 +70,7 @@ public final class Query implements Parcelable { @NonNull Bundle extras) { mInput = input; mTimestampMillis = timestampMillis; - mExtras = extras == null ? extras : new Bundle(); + mExtras = extras != null ? extras : new Bundle(); } /** diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 063ba1174cdc..2e94dd1a47c4 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -143,7 +143,7 @@ public class AppWidgetProviderInfo implements Parcelable { public ComponentName provider; /** - * The default height of the widget when added to a host, in dp. The widget will get + * The default height of the widget when added to a host, in px. The widget will get * at least this width, and will often be given more, depending on the host. * * <p>This field corresponds to the <code>android:minWidth</code> attribute in @@ -152,7 +152,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minWidth; /** - * The default height of the widget when added to a host, in dp. The widget will get + * The default height of the widget when added to a host, in px. The widget will get * at least this height, and will often be given more, depending on the host. * * <p>This field corresponds to the <code>android:minHeight</code> attribute in @@ -161,7 +161,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minHeight; /** - * Minimum width (in dp) which the widget can be resized to. This field has no effect if it + * Minimum width (in px) which the widget can be resized to. This field has no effect if it * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in @@ -170,7 +170,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minResizeWidth; /** - * Minimum height (in dp) which the widget can be resized to. This field has no effect if it + * Minimum height (in px) which the widget can be resized to. This field has no effect if it * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in @@ -179,7 +179,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minResizeHeight; /** - * Maximum width (in dp) which the widget can be resized to. This field has no effect if it is + * Maximum width (in px) which the widget can be resized to. This field has no effect if it is * smaller than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:maxResizeWidth</code> attribute in the @@ -189,7 +189,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int maxResizeWidth; /** - * Maximum height (in dp) which the widget can be resized to. This field has no effect if it is + * Maximum height (in px) which the widget can be resized to. This field has no effect if it is * smaller than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:maxResizeHeight</code> attribute in the diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 27027721109d..c3ec09466de6 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3195,7 +3195,7 @@ public abstract class Context { * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#O} * or higher are not allowed to start background services from the background. * See - * <a href="{@docRoot}/about/versions/oreo/background"> + * <a href="/about/versions/oreo/background"> * Background Execution Limits</a> * for more details. * @@ -3204,7 +3204,7 @@ public abstract class Context { * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#S} * or higher are not allowed to start foreground services from the background. * See - * <a href="{@docRoot}/about/versions/12/behavior-changes-12"> + * <a href="/about/versions/12/behavior-changes-12"> * Behavior changes: Apps targeting Android 12 * </a> * for more details. @@ -3258,7 +3258,7 @@ public abstract class Context { * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#S} * or higher are not allowed to start foreground services from the background. * See - * <a href="{@docRoot}/about/versions/12/behavior-changes-12"> + * <a href="/about/versions/12/behavior-changes-12"> * Behavior changes: Apps targeting Android 12 * </a> * for more details. @@ -5935,6 +5935,10 @@ public abstract class Context { * more general access to the URI's content provider then this check will * always fail. * + * <strong>Note:</strong> On SDK Version {@link android.os.Build.VERSION_CODES#S}, + * calling this method from a secondary-user's context will incorrectly return + * {@link PackageManager#PERMISSION_DENIED} for all {code uris}. + * * @param uris The list of URIs that is being checked. * @param pid The process ID being checked against. Must be > 0. * @param uid The user ID being checked against. A uid of 0 is the root diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9a8dc6a2975f..75d2634ca2f9 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2738,6 +2738,22 @@ public class Intent implements Parcelable, Cloneable { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED"; + /** + * Broadcast Action: One of the suspend conditions have been modified for the packages. + * <p>Includes the following extras: + * <ul> + * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been modified + * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been modified + * </ul> + * + * <p class="note">This is a protected intent that can only be sent + * by the system. It is only sent to registered receivers. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGES_SUSPENSION_CHANGED = + "android.intent.action.PACKAGES_SUSPENSION_CHANGED"; /** * Broadcast Action: Distracting packages have been changed. diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index 3f3db29ed0fd..c8c122da4ab8 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -438,9 +438,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } private class OnAuthenticationCancelListener implements CancellationSignal.OnCancelListener { + private final long mAuthRequestId; + + OnAuthenticationCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelAuthentication(); + Log.d(TAG, "Cancel BP authentication requested for: " + mAuthRequestId); + cancelAuthentication(mAuthRequestId); } } @@ -853,10 +860,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * @param userId The user to authenticate * @param operationId The keystore operation associated with authentication * + * @return A requestId that can be used to cancel this operation. + * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void authenticateUserForOperation( + public long authenticateUserForOperation( @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, @@ -871,7 +880,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan if (callback == null) { throw new IllegalArgumentException("Must supply a callback"); } - authenticateInternal(operationId, cancel, executor, callback, userId); + + return authenticateInternal(operationId, cancel, executor, callback, userId); } /** @@ -1002,10 +1012,10 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId()); } - private void cancelAuthentication() { + private void cancelAuthentication(long requestId) { if (mService != null) { try { - mService.cancelAuthentication(mToken, mContext.getOpPackageName()); + mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId); } catch (RemoteException e) { Log.e(TAG, "Unable to cancel authentication", e); } @@ -1024,7 +1034,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan authenticateInternal(operationId, cancel, executor, callback, userId); } - private void authenticateInternal( + private long authenticateInternal( long operationId, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @@ -1040,9 +1050,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan try { if (cancel.isCanceled()) { Log.w(TAG, "Authentication already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnAuthenticationCancelListener()); + return -1; } mExecutor = executor; @@ -1065,14 +1073,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan promptInfo = mPromptInfo; } - mService.authenticate(mToken, operationId, userId, mBiometricServiceReceiver, - mContext.getOpPackageName(), promptInfo); - + final long authId = mService.authenticate(mToken, operationId, userId, + mBiometricServiceReceiver, mContext.getOpPackageName(), promptInfo); + cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); + return authId; } catch (RemoteException e) { Log.e(TAG, "Remote exception while authenticating", e); mExecutor.execute(() -> callback.onAuthenticationError( BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, mContext.getString(R.string.biometric_error_hw_unavailable))); + return -1; } } diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl index 4c2a9ae10cbd..91f794c161bf 100644 --- a/core/java/android/hardware/biometrics/IAuthService.aidl +++ b/core/java/android/hardware/biometrics/IAuthService.aidl @@ -41,13 +41,14 @@ interface IAuthService { // Retrieve the package where BIometricOrompt's UI is implemented String getUiPackage(); - // Requests authentication. The service choose the appropriate biometric to use, and show - // the corresponding BiometricDialog. - void authenticate(IBinder token, long sessionId, int userId, + // Requests authentication. The service chooses the appropriate biometric to use, and shows + // the corresponding BiometricDialog. A requestId is returned that can be used to cancel + // this operation. + long authenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo); - // Cancel authentication for the given sessionId - void cancelAuthentication(IBinder token, String opPackageName); + // Cancel authentication for the given requestId. + void cancelAuthentication(IBinder token, String opPackageName, long requestId); // TODO(b/141025588): Make userId the first arg to be consistent with hasEnrolledBiometrics. // Checks if biometrics can be used. diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl index 876513f266e8..addd622eef35 100644 --- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl +++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl @@ -48,13 +48,13 @@ interface IBiometricAuthenticator { // startPreparedClient(). void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, - int cookie, boolean allowBackgroundAuthentication); + long requestId, int cookie, boolean allowBackgroundAuthentication); // Starts authentication with the previously prepared client. void startPreparedClient(int cookie); - // Cancels authentication. - void cancelAuthenticationFromService(IBinder token, String opPackageName); + // Cancels authentication for the given requestId. + void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId); // Determine if HAL is loaded and ready boolean isHardwareDetected(String opPackageName); diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index 64b51183a170..2c3c8c353e8c 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -36,13 +36,14 @@ interface IBiometricService { // Retrieve static sensor properties for all biometric sensors List<SensorPropertiesInternal> getSensorProperties(String opPackageName); - // Requests authentication. The service choose the appropriate biometric to use, and show - // the corresponding BiometricDialog. - void authenticate(IBinder token, long operationId, int userId, + // Requests authentication. The service chooses the appropriate biometric to use, and shows + // the corresponding BiometricDialog. A requestId is returned that can be used to cancel + // this operation. + long authenticate(IBinder token, long operationId, int userId, IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo); - // Cancel authentication for the given session. - void cancelAuthentication(IBinder token, String opPackageName); + // Cancel authentication for the given requestId. + void cancelAuthentication(IBinder token, String opPackageName, long requestId); // Checks if biometrics can be used. int canAuthenticate(String opPackageName, int userId, int callingUserId, int authenticators); diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index 5cfba3d945cd..395c655ddf7c 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -263,12 +263,12 @@ public final class CameraExtensionCharacteristics { @Override public void onServiceConnected(ComponentName component, IBinder binder) { mProxy = ICameraExtensionsProxyService.Stub.asInterface(binder); - mInitFuture.setStatus(true); try { mSupportsAdvancedExtensions = mProxy.advancedExtensionsSupported(); } catch (RemoteException e) { Log.e(TAG, "Remote IPC failed!"); } + mInitFuture.setStatus(true); } }; ctx.bindService(intent, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT | diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java index 20ca4a338f01..032ed7e4db62 100644 --- a/core/java/android/hardware/camera2/CaptureFailure.java +++ b/core/java/android/hardware/camera2/CaptureFailure.java @@ -59,7 +59,7 @@ public class CaptureFailure { private final CaptureRequest mRequest; private final int mReason; - private final boolean mDropped; + private final boolean mWasImageCaptured; private final int mSequenceId; private final long mFrameNumber; private final String mErrorPhysicalCameraId; @@ -68,10 +68,11 @@ public class CaptureFailure { * @hide */ public CaptureFailure(CaptureRequest request, int reason, - boolean dropped, int sequenceId, long frameNumber, String errorPhysicalCameraId) { + boolean wasImageCaptured, int sequenceId, long frameNumber, + String errorPhysicalCameraId) { mRequest = request; mReason = reason; - mDropped = dropped; + mWasImageCaptured = wasImageCaptured; mSequenceId = sequenceId; mFrameNumber = frameNumber; mErrorPhysicalCameraId = errorPhysicalCameraId; @@ -141,7 +142,7 @@ public class CaptureFailure { * @return boolean True if the image was captured, false otherwise. */ public boolean wasImageCaptured() { - return !mDropped; + return mWasImageCaptured; } /** diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java index 8da6551f3d15..b8443fb6d14b 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -873,21 +873,19 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes @Override public int submitBurst(List<Request> requests, IRequestCallback callback) { int seqId = -1; - synchronized (mInterfaceLock) { - try { - CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback); - ArrayList<CaptureRequest> captureRequests = new ArrayList<>(); - for (Request request : requests) { - captureRequests.add(initializeCaptureRequest(mCameraDevice, request, - mCameraConfigMap)); - } - seqId = mCaptureSession.captureBurstRequests(captureRequests, - new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback); - } catch (CameraAccessException e) { - Log.e(TAG, "Failed to submit capture requests!"); - } catch (IllegalStateException e) { - Log.e(TAG, "Capture session closed!"); + try { + CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback); + ArrayList<CaptureRequest> captureRequests = new ArrayList<>(); + for (Request request : requests) { + captureRequests.add(initializeCaptureRequest(mCameraDevice, request, + mCameraConfigMap)); } + seqId = mCaptureSession.captureBurstRequests(captureRequests, + new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback); + } catch (CameraAccessException e) { + Log.e(TAG, "Failed to submit capture requests!"); + } catch (IllegalStateException e) { + Log.e(TAG, "Capture session closed!"); } return seqId; @@ -896,18 +894,16 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes @Override public int setRepeating(Request request, IRequestCallback callback) { int seqId = -1; - synchronized (mInterfaceLock) { - try { - CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice, - request, mCameraConfigMap); - CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback); - seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest, - new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback); - } catch (CameraAccessException e) { - Log.e(TAG, "Failed to enable repeating request!"); - } catch (IllegalStateException e) { - Log.e(TAG, "Capture session closed!"); - } + try { + CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice, + request, mCameraConfigMap); + CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback); + seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest, + new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback); + } catch (CameraAccessException e) { + Log.e(TAG, "Failed to enable repeating request!"); + } catch (IllegalStateException e) { + Log.e(TAG, "Capture session closed!"); } return seqId; @@ -915,27 +911,23 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes @Override public void abortCaptures() { - synchronized (mInterfaceLock) { - try { - mCaptureSession.abortCaptures(); - } catch (CameraAccessException e) { - Log.e(TAG, "Failed during capture abort!"); - } catch (IllegalStateException e) { - Log.e(TAG, "Capture session closed!"); - } + try { + mCaptureSession.abortCaptures(); + } catch (CameraAccessException e) { + Log.e(TAG, "Failed during capture abort!"); + } catch (IllegalStateException e) { + Log.e(TAG, "Capture session closed!"); } } @Override public void stopRepeating() { - synchronized (mInterfaceLock) { - try { - mCaptureSession.stopRepeating(); - } catch (CameraAccessException e) { - Log.e(TAG, "Failed during repeating capture stop!"); - } catch (IllegalStateException e) { - Log.e(TAG, "Capture session closed!"); - } + try { + mCaptureSession.stopRepeating(); + } catch (CameraAccessException e) { + Log.e(TAG, "Failed during repeating capture stop!"); + } catch (IllegalStateException e) { + Log.e(TAG, "Capture session closed!"); } } } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 4a7d3b772bd4..9361d2caa85f 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -109,6 +109,9 @@ public class CameraDeviceImpl extends CameraDevice private SparseArray<CaptureCallbackHolder> mCaptureCallbackMap = new SparseArray<CaptureCallbackHolder>(); + /** map request IDs which have batchedOutputs to requestCount*/ + private HashMap<Integer, Integer> mBatchOutputMap = new HashMap<>(); + private int mRepeatingRequestId = REQUEST_ID_NONE; // Latest repeating request list's types private int[] mRepeatingRequestTypes; @@ -985,6 +988,7 @@ public class CameraDeviceImpl extends CameraDevice mConfiguredInput = new SimpleEntry<Integer, InputConfiguration>(REQUEST_ID_NONE, null); mIdle = true; mCaptureCallbackMap = new SparseArray<CaptureCallbackHolder>(); + mBatchOutputMap = new HashMap<>(); mFrameNumberTracker = new FrameNumberTracker(); mCurrentSession.closeWithoutDraining(); @@ -1191,6 +1195,41 @@ public class CameraDeviceImpl extends CameraDevice return requestTypes; } + private boolean hasBatchedOutputs(List<CaptureRequest> requestList) { + boolean hasBatchedOutputs = true; + for (int i = 0; i < requestList.size(); i++) { + CaptureRequest request = requestList.get(i); + if (!request.isPartOfCRequestList()) { + hasBatchedOutputs = false; + break; + } + if (i == 0) { + Collection<Surface> targets = request.getTargets(); + if (targets.size() != 2) { + hasBatchedOutputs = false; + break; + } + } + } + return hasBatchedOutputs; + } + + private void updateTracker(int requestId, long frameNumber, + int requestType, CaptureResult result, boolean isPartialResult) { + int requestCount = 1; + // If the request has batchedOutputs update each frame within the batch. + if (mBatchOutputMap.containsKey(requestId)) { + requestCount = mBatchOutputMap.get(requestId); + for (int i = 0; i < requestCount; i++) { + mFrameNumberTracker.updateTracker(frameNumber - (requestCount - 1 - i), + result, isPartialResult, requestType); + } + } else { + mFrameNumberTracker.updateTracker(frameNumber, result, + isPartialResult, requestType); + } + } + private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback, Executor executor, boolean repeating) throws CameraAccessException { @@ -1236,6 +1275,14 @@ public class CameraDeviceImpl extends CameraDevice request.recoverStreamIdToSurface(); } + // If the request has batched outputs, then store the + // requestCount and requestId in the map. + boolean hasBatchedOutputs = hasBatchedOutputs(requestList); + if (hasBatchedOutputs) { + int requestCount = requestList.size(); + mBatchOutputMap.put(requestInfo.getRequestId(), requestCount); + } + if (callback != null) { mCaptureCallbackMap.put(requestInfo.getRequestId(), new CaptureCallbackHolder( @@ -1861,7 +1908,7 @@ public class CameraDeviceImpl extends CameraDevice final CaptureFailure failure = new CaptureFailure( request, reason, - /*dropped*/ mayHaveBuffers, + mayHaveBuffers, requestId, frameNumber, errorPhysicalCameraId); @@ -1880,8 +1927,18 @@ public class CameraDeviceImpl extends CameraDevice if (DEBUG) { Log.v(TAG, String.format("got error frame %d", frameNumber)); } - mFrameNumberTracker.updateTracker(frameNumber, - /*error*/true, request.getRequestType()); + + // Update FrameNumberTracker for every frame during HFR mode. + if (mBatchOutputMap.containsKey(requestId)) { + for (int i = 0; i < mBatchOutputMap.get(requestId); i++) { + mFrameNumberTracker.updateTracker(frameNumber - (subsequenceId - i), + /*error*/true, request.getRequestType()); + } + } else { + mFrameNumberTracker.updateTracker(frameNumber, + /*error*/true, request.getRequestType()); + } + checkAndFireSequenceComplete(); // Dispatch the failure callback @@ -2064,7 +2121,6 @@ public class CameraDeviceImpl extends CameraDevice public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[]) throws RemoteException { - int requestId = resultExtras.getRequestId(); long frameNumber = resultExtras.getFrameNumber(); @@ -2105,8 +2161,8 @@ public class CameraDeviceImpl extends CameraDevice + frameNumber); } - mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, /*result*/null, + isPartialResult); return; } @@ -2118,8 +2174,9 @@ public class CameraDeviceImpl extends CameraDevice + frameNumber); } - mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, /*result*/null, + isPartialResult); + return; } @@ -2225,9 +2282,7 @@ public class CameraDeviceImpl extends CameraDevice Binder.restoreCallingIdentity(ident); } - // Collect the partials for a total result; or mark the frame as totally completed - mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, finalResult, isPartialResult); // Fire onCaptureSequenceCompleted if (!isPartialResult) { diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java index 3b1cb94a6619..425f22c31306 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java @@ -58,7 +58,7 @@ public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl { private static final class JpegParameters { public HashSet<Long> mTimeStamps = new HashSet<>(); - public int mRotation = JPEG_DEFAULT_ROTATION; // CCW multiple of 90 degrees + public int mRotation = JPEG_DEFAULT_ROTATION; // CW multiple of 90 degrees public int mQuality = JPEG_DEFAULT_QUALITY; // [0..100] } @@ -100,7 +100,8 @@ public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl { Integer orientation = captureBundles.get(0).captureResult.get( CaptureResult.JPEG_ORIENTATION); if (orientation != null) { - ret.mRotation = orientation / 90; + // The jpeg encoder expects CCW rotation, convert from CW + ret.mRotation = (360 - (orientation % 360)) / 90; } else { Log.w(TAG, "No jpeg rotation set, using default: " + JPEG_DEFAULT_ROTATION); } diff --git a/core/java/android/hardware/display/BrightnessInfo.java b/core/java/android/hardware/display/BrightnessInfo.java index c5d37c2d0b90..0dc8f92967fb 100644 --- a/core/java/android/hardware/display/BrightnessInfo.java +++ b/core/java/android/hardware/display/BrightnessInfo.java @@ -60,12 +60,18 @@ public final class BrightnessInfo implements Parcelable { /** Brightness */ public final float brightness; + /** Brightness after {@link DisplayPowerController} adjustments */ + public final float adjustedBrightness; + /** Current minimum supported brightness. */ public final float brightnessMinimum; /** Current maximum supported brightness. */ public final float brightnessMaximum; + /** Brightness values greater than this point are only used in High Brightness Mode. */ + public final float highBrightnessTransitionPoint; + /** * Current state of high brightness mode. * Can be any of HIGH_BRIGHTNESS_MODE_* values. @@ -73,11 +79,20 @@ public final class BrightnessInfo implements Parcelable { public final int highBrightnessMode; public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum, - @HighBrightnessMode int highBrightnessMode) { + @HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint) { + this(brightness, brightness, brightnessMinimum, brightnessMaximum, highBrightnessMode, + highBrightnessTransitionPoint); + } + + public BrightnessInfo(float brightness, float adjustedBrightness, float brightnessMinimum, + float brightnessMaximum, @HighBrightnessMode int highBrightnessMode, + float highBrightnessTransitionPoint) { this.brightness = brightness; + this.adjustedBrightness = adjustedBrightness; this.brightnessMinimum = brightnessMinimum; this.brightnessMaximum = brightnessMaximum; this.highBrightnessMode = highBrightnessMode; + this.highBrightnessTransitionPoint = highBrightnessTransitionPoint; } /** @@ -103,9 +118,11 @@ public final class BrightnessInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeFloat(brightness); + dest.writeFloat(adjustedBrightness); dest.writeFloat(brightnessMinimum); dest.writeFloat(brightnessMaximum); dest.writeInt(highBrightnessMode); + dest.writeFloat(highBrightnessTransitionPoint); } public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR = @@ -123,9 +140,11 @@ public final class BrightnessInfo implements Parcelable { private BrightnessInfo(Parcel source) { brightness = source.readFloat(); + adjustedBrightness = source.readFloat(); brightnessMinimum = source.readFloat(); brightnessMaximum = source.readFloat(); highBrightnessMode = source.readInt(); + highBrightnessTransitionPoint = source.readFloat(); } } diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 385ad2d3577f..56f81423db4e 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -58,7 +58,7 @@ import java.util.List; public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants { private static final String TAG = "FaceManager"; - private static final boolean DEBUG = true; + private static final int MSG_ENROLL_RESULT = 100; private static final int MSG_ACQUIRED = 101; private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; @@ -207,13 +207,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan throw new IllegalArgumentException("Must supply an authentication callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "authentication already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto)); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "authentication already canceled"); + return; } if (mService != null) { @@ -223,17 +219,18 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan mCryptoObject = crypto; final long operationId = crypto != null ? crypto.getOpId() : 0; Trace.beginSection("FaceManager#authenticate"); - mService.authenticate(mToken, operationId, userId, mServiceReceiver, - mContext.getOpPackageName(), isKeyguardBypassEnabled); + final long authId = mService.authenticate(mToken, operationId, userId, + mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled); + if (cancel != null) { + cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception while authenticating: ", e); - if (callback != null) { - // Though this may not be a hardware issue, it will cause apps to give up or - // try again later. - callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE, - getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE, - 0 /* vendorCode */)); - } + // Though this may not be a hardware issue, it will cause apps to give up or + // try again later. + callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE, + getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */)); } finally { Trace.endSection(); } @@ -255,14 +252,14 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan if (cancel.isCanceled()) { Slog.w(TAG, "Detection already cancelled"); return; - } else { - cancel.setOnCancelListener(new OnFaceDetectionCancelListener()); } mFaceDetectionCallback = callback; try { - mService.detectFace(mToken, userId, mServiceReceiver, mContext.getOpPackageName()); + final long authId = mService.detectFace( + mToken, userId, mServiceReceiver, mContext.getOpPackageName()); + cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId)); } catch (RemoteException e) { Slog.w(TAG, "Remote exception when requesting finger detect", e); } @@ -726,23 +723,23 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } } - private void cancelAuthentication(CryptoObject cryptoObject) { + private void cancelAuthentication(long requestId) { if (mService != null) { try { - mService.cancelAuthentication(mToken, mContext.getOpPackageName()); + mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } - private void cancelFaceDetect() { + private void cancelFaceDetect(long requestId) { if (mService == null) { return; } try { - mService.cancelFaceDetect(mToken, mContext.getOpPackageName()); + mService.cancelFaceDetect(mToken, mContext.getOpPackageName(), requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -794,9 +791,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan // This is used as a last resort in case a vendor string is missing // It should not happen for anything other than FACE_ERROR_VENDOR, but // warn and use the default if all else fails. - // TODO(b/196639965): update string Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode); - return ""; + return context.getString( + com.android.internal.R.string.face_error_vendor_unknown); } /** @@ -1110,22 +1107,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } private class OnAuthenticationCancelListener implements OnCancelListener { - private final CryptoObject mCrypto; + private final long mAuthRequestId; - OnAuthenticationCancelListener(CryptoObject crypto) { - mCrypto = crypto; + OnAuthenticationCancelListener(long id) { + mAuthRequestId = id; } @Override public void onCancel() { - cancelAuthentication(mCrypto); + Slog.d(TAG, "Cancel face authentication requested for: " + mAuthRequestId); + cancelAuthentication(mAuthRequestId); } } private class OnFaceDetectionCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + OnFaceDetectionCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelFaceDetect(); + Slog.d(TAG, "Cancel face detect requested for: " + mAuthRequestId); + cancelFaceDetect(mAuthRequestId); } } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index db02a0ef2a10..e9198246dee3 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -44,34 +44,36 @@ interface IFaceService { // Retrieve static sensor properties for the specified sensor FaceSensorPropertiesInternal getSensorProperties(int sensorId, String opPackageName); - // Authenticate the given sessionId with a face - void authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver, + // Authenticate with a face. A requestId is returned that can be used to cancel this operation. + long authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver, String opPackageName, boolean isKeyguardBypassEnabled); // Uses the face hardware to detect for the presence of a face, without giving details - // about accept/reject/lockout. - void detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName); + // about accept/reject/lockout. A requestId is returned that can be used to cancel this + // operation. + long detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName); // This method prepares the service to start authenticating, but doesn't start authentication. // This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be // called from BiometricService. The additional uid, pid, userId arguments should be determined // by BiometricService. To start authentication after the clients are ready, use // startPreparedClient(). - void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, long operationId, - int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, - int cookie, boolean allowBackgroundAuthentication); + void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, + long operationId, int userId, IBiometricSensorReceiver sensorReceiver, + String opPackageName, long requestId, int cookie, + boolean allowBackgroundAuthentication); // Starts authentication with the previously prepared client. void startPreparedClient(int sensorId, int cookie); - // Cancel authentication for the given sessionId - void cancelAuthentication(IBinder token, String opPackageName); + // Cancel authentication for the given requestId. + void cancelAuthentication(IBinder token, String opPackageName, long requestId); - // Cancel face detection - void cancelFaceDetect(IBinder token, String opPackageName); + // Cancel face detection for the given requestId. + void cancelFaceDetect(IBinder token, String opPackageName, long requestId); // Same as above, with extra arguments. - void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName); + void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start face enrollment void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 87d45b9de745..a3d595c23095 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -146,6 +146,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing private CryptoObject mCryptoObject; @Nullable private RemoveTracker mRemoveTracker; private Handler mHandler; + @Nullable private float[] mEnrollStageThresholds; /** * Retrieves a list of properties for all fingerprint sensors on the device. @@ -189,22 +190,30 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } private class OnAuthenticationCancelListener implements OnCancelListener { - private android.hardware.biometrics.CryptoObject mCrypto; + private final long mAuthRequestId; - public OnAuthenticationCancelListener(android.hardware.biometrics.CryptoObject crypto) { - mCrypto = crypto; + OnAuthenticationCancelListener(long id) { + mAuthRequestId = id; } @Override public void onCancel() { - cancelAuthentication(mCrypto); + Slog.d(TAG, "Cancel fingerprint authentication requested for: " + mAuthRequestId); + cancelAuthentication(mAuthRequestId); } } private class OnFingerprintDetectionCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + OnFingerprintDetectionCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelFingerprintDetect(); + Slog.d(TAG, "Cancel fingerprint detect requested for: " + mAuthRequestId); + cancelFingerprintDetect(mAuthRequestId); } } @@ -552,13 +561,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing throw new IllegalArgumentException("Must supply an authentication callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "authentication already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto)); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "authentication already canceled"); + return; } if (mService != null) { @@ -567,8 +572,11 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing mAuthenticationCallback = callback; mCryptoObject = crypto; final long operationId = crypto != null ? crypto.getOpId() : 0; - mService.authenticate(mToken, operationId, sensorId, userId, mServiceReceiver, - mContext.getOpPackageName()); + final long authId = mService.authenticate(mToken, operationId, sensorId, userId, + mServiceReceiver, mContext.getOpPackageName()); + if (cancel != null) { + cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception while authenticating: ", e); // Though this may not be a hardware issue, it will cause apps to give up or try @@ -595,15 +603,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing if (cancel.isCanceled()) { Slog.w(TAG, "Detection already cancelled"); return; - } else { - cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener()); } mFingerprintDetectionCallback = callback; try { - mService.detectFingerprint(mToken, userId, mServiceReceiver, + final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver, mContext.getOpPackageName()); + cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId)); } catch (RemoteException e) { Slog.w(TAG, "Remote exception when requesting finger detect", e); } @@ -844,26 +851,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** - * Checks if the specified user has enrollments in any of the specified sensors. - * @hide - */ - @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public boolean hasEnrolledTemplatesForAnySensor(int userId, - @NonNull List<FingerprintSensorPropertiesInternal> sensors) { - if (mService == null) { - Slog.w(TAG, "hasEnrolledTemplatesForAnySensor: no fingerprint service"); - return false; - } - - try { - return mService.hasEnrolledTemplatesForAnySensor(userId, sensors, - mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @@ -1320,21 +1307,21 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } - private void cancelAuthentication(android.hardware.biometrics.CryptoObject cryptoObject) { + private void cancelAuthentication(long requestId) { if (mService != null) try { - mService.cancelAuthentication(mToken, mContext.getOpPackageName()); + mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - private void cancelFingerprintDetect() { + private void cancelFingerprintDetect(long requestId) { if (mService == null) { return; } try { - mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName()); + mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName(), requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1343,6 +1330,46 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** * @hide */ + public int getEnrollStageCount() { + if (mEnrollStageThresholds == null) { + mEnrollStageThresholds = createEnrollStageThresholds(mContext); + } + return mEnrollStageThresholds.length + 1; + } + + /** + * @hide + */ + public float getEnrollStageThreshold(int index) { + if (mEnrollStageThresholds == null) { + mEnrollStageThresholds = createEnrollStageThresholds(mContext); + } + + if (index < 0 || index > mEnrollStageThresholds.length) { + Slog.w(TAG, "Unsupported enroll stage index: " + index); + return index < 0 ? 0f : 1f; + } + + // The implicit threshold for the final stage is always 1. + return index == mEnrollStageThresholds.length ? 1f : mEnrollStageThresholds[index]; + } + + @NonNull + private static float[] createEnrollStageThresholds(@NonNull Context context) { + // TODO(b/200604947): Fetch this value from FingerprintService, rather than internal config + final String[] enrollStageThresholdStrings = context.getResources().getStringArray( + com.android.internal.R.array.config_udfps_enroll_stage_thresholds); + + final float[] enrollStageThresholds = new float[enrollStageThresholdStrings.length]; + for (int i = 0; i < enrollStageThresholds.length; i++) { + enrollStageThresholds[i] = Float.parseFloat(enrollStageThresholdStrings[i]); + } + return enrollStageThresholds; + } + + /** + * @hide + */ public static String getErrorString(Context context, int errMsg, int vendorCode) { switch (errMsg) { case FINGERPRINT_ERROR_HW_UNAVAILABLE: @@ -1390,9 +1417,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing // This is used as a last resort in case a vendor string is missing // It should not happen for anything other than FINGERPRINT_ERROR_VENDOR, but // warn and use the default if all else fails. - // TODO(b/196639965): update string Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode); - return ""; + return context.getString( + com.android.internal.R.string.fingerprint_error_vendor_unknown); } /** diff --git a/core/java/android/hardware/fingerprint/FingerprintStateListener.java b/core/java/android/hardware/fingerprint/FingerprintStateListener.java index 6e607a269cb2..cf914c5acd1a 100644 --- a/core/java/android/hardware/fingerprint/FingerprintStateListener.java +++ b/core/java/android/hardware/fingerprint/FingerprintStateListener.java @@ -49,5 +49,10 @@ public abstract class FingerprintStateListener extends IFingerprintStateListener * Defines behavior in response to state update * @param newState new state of fingerprint sensor */ - public abstract void onStateChanged(@FingerprintStateListener.State int newState); + public void onStateChanged(@FingerprintStateListener.State int newState) {}; + + /** + * Invoked when enrollment state changes for the specified user + */ + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {}; } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 3979afe80d17..de94b2fbb5b5 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -48,15 +48,16 @@ interface IFingerprintService { // Retrieve static sensor properties for the specified sensor FingerprintSensorPropertiesInternal getSensorProperties(int sensorId, String opPackageName); - // Authenticate the given sessionId with a fingerprint. This is protected by - // USE_FINGERPRINT/USE_BIOMETRIC permission. This is effectively deprecated, since it only comes - // through FingerprintManager now. - void authenticate(IBinder token, long operationId, int sensorId, int userId, + // Authenticate with a fingerprint. This is protected by USE_FINGERPRINT/USE_BIOMETRIC + // permission. This is effectively deprecated, since it only comes through FingerprintManager + // now. A requestId is returned that can be used to cancel this operation. + long authenticate(IBinder token, long operationId, int sensorId, int userId, IFingerprintServiceReceiver receiver, String opPackageName); // Uses the fingerprint hardware to detect for the presence of a finger, without giving details - // about accept/reject/lockout. - void detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver, + // about accept/reject/lockout. A requestId is returned that can be used to cancel this + // operation. + long detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver, String opPackageName); // This method prepares the service to start authenticating, but doesn't start authentication. @@ -65,21 +66,21 @@ interface IFingerprintService { // by BiometricService. To start authentication after the clients are ready, use // startPreparedClient(). void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId, - IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie, - boolean allowBackgroundAuthentication); + IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId, + int cookie, boolean allowBackgroundAuthentication); // Starts authentication with the previously prepared client. void startPreparedClient(int sensorId, int cookie); - // Cancel authentication for the given sessionId - void cancelAuthentication(IBinder token, String opPackageName); + // Cancel authentication for the given requestId. + void cancelAuthentication(IBinder token, String opPackageName, long requestId); - // Cancel finger detection - void cancelFingerprintDetect(IBinder token, String opPackageName); + // Cancel finger detection for the given requestId. + void cancelFingerprintDetect(IBinder token, String opPackageName, long requestId); // Same as above, except this is protected by the MANAGE_BIOMETRIC signature permission. Takes // an additional uid, pid, userid. - void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName); + void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start fingerprint enrollment void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver, @@ -119,9 +120,6 @@ interface IFingerprintService { // Determine if a user has at least one enrolled fingerprint. boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName); - // Determine if a user has at least one enrolled fingerprint in any of the specified sensors - boolean hasEnrolledTemplatesForAnySensor(int userId, in List<FingerprintSensorPropertiesInternal> sensors, String opPackageName); - // Return the LockoutTracker status for the specified user int getLockoutModeForUser(int sensorId, int userId); diff --git a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl b/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl index 56dba7ea1d9a..1aa6fa197066 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl @@ -24,4 +24,5 @@ import android.hardware.fingerprint.Fingerprint; */ oneway interface IFingerprintStateListener { void onStateChanged(int newState); + void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments); } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 881e0cfb58d7..74cb42db7858 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1749,12 +1749,12 @@ public class InputMethodService extends AbstractInputMethodService { if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) { return false; } - if ((mInputEditorInfo != null - && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) + if (mInputEditorInfo != null + && ((mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0 // If app window has portrait orientation, regardless of what display orientation // is, IME shouldn't use fullscreen-mode. || (mInputEditorInfo.internalImeOptions - & EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT) != 0) { + & EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT) != 0)) { return false; } return true; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 249154aa9129..762816dd9f11 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -782,8 +782,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * <p> @@ -798,8 +798,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * @@ -811,7 +811,12 @@ public class NetworkTemplate implements Parcelable { * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { - if (!template.isMatchRuleMobile()) return template; + // Now there are several types of network which uses SubscriberId to store network + // information. For instances: + // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. + // The TYPE_CARRIER means that the network associate to specific carrier network. + + if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index f48375246616..0f94cbef3886 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -271,6 +271,16 @@ public final class BatteryUsageStats implements Parcelable { } /** + * Returns the names of custom power components in order, so the first name in the array + * corresponds to the custom componentId + * {@link BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID}. + */ + @NonNull + public String[] getCustomPowerComponentNames() { + return mCustomPowerComponentNames; + } + + /** * Returns an iterator for {@link android.os.BatteryStats.HistoryItem}'s. */ @NonNull diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index 3d466a0bf007..c6466235e5d1 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -74,7 +74,7 @@ public final class BinderProxy implements IBinder { private static final int MAIN_INDEX_SIZE = 1 << LOG_MAIN_INDEX_SIZE; private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1; // Debuggable builds will throw an AssertionError if the number of map entries exceeds: - private static final int CRASH_AT_SIZE = 20_000; + private static final int CRASH_AT_SIZE = 25_000; /** * We next warn when we exceed this bucket size. diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index be21fea1d0df..1cceea30868c 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -17,6 +17,7 @@ package android.os; import android.app.Activity; +import android.app.GameManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -26,8 +27,6 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.res.AssetFileDescriptor; -import android.content.res.AssetManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -37,9 +36,6 @@ import dalvik.system.VMRuntime; import java.io.BufferedReader; import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; @@ -88,9 +84,6 @@ public class GraphicsEnvironment { private static final String UPDATABLE_DRIVER_ALLOWLIST_ALL = "*"; private static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; - // ANGLE related properties. - private static final String ANGLE_RULES_FILE = "a4a_rules.json"; - private static final String ANGLE_TEMP_RULES = "debug.angle.rules"; private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID"; private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE = "android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE"; @@ -121,6 +114,7 @@ public class GraphicsEnvironment { private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; + private GameManager mGameManager; private int mAngleOptInIndex = -1; @@ -133,6 +127,8 @@ public class GraphicsEnvironment { final ApplicationInfo appInfoWithMetaData = getAppInfoWithMetadata(context, pm, packageName); + mGameManager = context.getSystemService(GameManager.class); + Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupGpuLayers"); setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData); Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); @@ -151,6 +147,23 @@ public class GraphicsEnvironment { } /** + * Query to determine if the Game Mode has enabled ANGLE. + */ + private boolean isAngleEnabledByGameMode(Context context, String packageName) { + try { + final boolean gameModeEnabledAngle = + (mGameManager != null) && mGameManager.isAngleEnabled(packageName); + Log.v(TAG, "ANGLE GameManagerService for " + packageName + ": " + gameModeEnabledAngle); + return gameModeEnabledAngle; + } catch (SecurityException e) { + Log.e(TAG, "Caught exception while querying GameManagerService if ANGLE is enabled " + + "for package: " + packageName); + } + + return false; + } + + /** * Query to determine if ANGLE should be used */ private boolean shouldUseAngle(Context context, Bundle coreSettings, @@ -164,21 +177,16 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " + "set to: '" + devOptIn + "'"); - // We only want to use ANGLE if the app is in the allowlist, or the developer has - // explicitly chosen something other than default driver. - // The allowlist will be generated by the ANGLE APK at both boot time and - // ANGLE update time. It will only include apps mentioned in the rules file. - final boolean allowed = checkAngleAllowlist(context, coreSettings, packageName); + // We only want to use ANGLE if the developer has explicitly chosen something other than + // default driver. final boolean requested = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE); - - if (allowed) { - Log.v(TAG, "ANGLE allowlist includes " + packageName); - } if (requested) { Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn); } - return allowed || requested; + final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); + + return requested || gameModeEnabledAngle; } private int getVulkanVersion(PackageManager pm) { @@ -475,117 +483,6 @@ public class GraphicsEnvironment { } /** - * Attempt to setup ANGLE with a temporary rules file. - * True: Temporary rules file was loaded. - * False: Temporary rules file was *not* loaded. - */ - private boolean setupAngleWithTempRulesFile(Context context, - String packageName, - String paths, - String devOptIn) { - /** - * We only want to load a temp rules file for: - * - apps that are marked 'debuggable' in their manifest - * - devices that are running a userdebug build (ro.debuggable) or can inject libraries for - * debugging (PR_SET_DUMPABLE). - */ - if (!isDebuggable()) { - Log.v(TAG, "Skipping loading temporary rules file"); - return false; - } - - final String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES); - - if (TextUtils.isEmpty(angleTempRules)) { - Log.v(TAG, "System property '" + ANGLE_TEMP_RULES + "' is not set or is empty"); - return false; - } - - Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules); - - final File tempRulesFile = new File(angleTempRules); - if (tempRulesFile.exists()) { - Log.i(TAG, angleTempRules + " exists, loading file."); - try { - final FileInputStream stream = new FileInputStream(angleTempRules); - - try { - final FileDescriptor rulesFd = stream.getFD(); - final long rulesOffset = 0; - final long rulesLength = stream.getChannel().size(); - Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules); - - setAngleInfo(paths, packageName, devOptIn, null, - rulesFd, rulesOffset, rulesLength); - - stream.close(); - - // We successfully setup ANGLE, so return with good status - return true; - } catch (IOException e) { - Log.w(TAG, "Hit IOException thrown by FileInputStream: " + e); - } - } catch (FileNotFoundException e) { - Log.w(TAG, "Temp ANGLE rules file not found: " + e); - } catch (SecurityException e) { - Log.w(TAG, "Temp ANGLE rules file not accessible: " + e); - } - } - - return false; - } - - /** - * Attempt to setup ANGLE with a rules file loaded from the ANGLE APK. - * True: APK rules file was loaded. - * False: APK rules file was *not* loaded. - */ - private boolean setupAngleRulesApk(String anglePkgName, - ApplicationInfo angleInfo, - PackageManager pm, - String packageName, - String paths, - String devOptIn, - String[] features) { - // Pass the rules file to loader for ANGLE decisions - try { - final AssetManager angleAssets = pm.getResourcesForApplication(angleInfo).getAssets(); - - try { - final AssetFileDescriptor assetsFd = angleAssets.openFd(ANGLE_RULES_FILE); - - setAngleInfo(paths, packageName, devOptIn, features, assetsFd.getFileDescriptor(), - assetsFd.getStartOffset(), assetsFd.getLength()); - - assetsFd.close(); - - return true; - } catch (IOException e) { - Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE - + " from '" + anglePkgName + "': " + e); - } - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Failed to get AssetManager for '" + anglePkgName + "': " + e); - } - - return false; - } - - /** - * Pull ANGLE allowlist from GlobalSettings and compare against current package - */ - private boolean checkAngleAllowlist(Context context, Bundle bundle, String packageName) { - final ContentResolver contentResolver = context.getContentResolver(); - final List<String> angleAllowlist = - getGlobalSettingsString(contentResolver, bundle, - Settings.Global.ANGLE_ALLOWLIST); - - if (DEBUG) Log.v(TAG, "ANGLE allowlist: " + angleAllowlist); - - return angleAllowlist.contains(packageName); - } - - /** * Pass ANGLE details down to trigger enable logic * * @param context @@ -647,28 +544,21 @@ public class GraphicsEnvironment { if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths); - // If the user has set the developer option to something other than default, - // we need to call setupAngleRulesApk() with the package name and the developer - // option value (native/angle/other). Then later when we are actually trying to - // load a driver, GraphicsEnv::getShouldUseAngle() has seen the package name before - // and can confidently answer yes/no based on the previously set developer - // option value. - final String devOptIn = getDriverForPackage(context, bundle, packageName); - - if (setupAngleWithTempRulesFile(context, packageName, paths, devOptIn)) { - // We setup ANGLE with a temp rules file, so we're done here. - return true; - } - - String[] features = getAngleEglFeatures(context, bundle); - - if (setupAngleRulesApk( - anglePkgName, angleInfo, pm, packageName, paths, devOptIn, features)) { - // ANGLE with rules is set up from the APK, hence return. - return true; + // We need to call setAngleInfo() with the package name and the developer option value + //(native/angle/other). Then later when we are actually trying to load a driver, + //GraphicsEnv::getShouldUseAngle() has seen the package name before and can confidently + //answer yes/no based on the previously set developer option value. + final String devOptIn; + final String[] features = getAngleEglFeatures(context, bundle); + final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); + if (gameModeEnabledAngle) { + devOptIn = ANGLE_GL_DRIVER_CHOICE_ANGLE; + } else { + devOptIn = getDriverForPackage(context, bundle, packageName); } + setAngleInfo(paths, packageName, devOptIn, features); - return false; + return true; } /** @@ -956,7 +846,7 @@ public class GraphicsEnvironment { private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion); private static native void setAngleInfo(String path, String appPackage, String devOptIn, - String[] features, FileDescriptor rulesFd, long rulesOffset, long rulesLength); + String[] features); private static native boolean getShouldUseAngle(String packageName); private static native boolean setInjectLayersPrSetDumpable(); diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java index 54905ec6eaeb..8928a423c6cb 100644 --- a/core/java/android/os/storage/StorageManagerInternal.java +++ b/core/java/android/os/storage/StorageManagerInternal.java @@ -18,6 +18,7 @@ package android.os.storage; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.os.IVold; import java.util.List; @@ -135,4 +136,19 @@ public abstract class StorageManagerInternal { * {@link VolumeInfo#isPrimary()} */ public abstract List<String> getPrimaryVolumeIds(); + + /** + * Tells StorageManager that CE storage for this user has been prepared. + * + * @param userId userId for which CE storage has been prepared + */ + public abstract void markCeStoragePrepared(@UserIdInt int userId); + + /** + * Returns true when CE storage for this user has been prepared. + * + * When the user key is unlocked and CE storage has been prepared, + * it's ok to access and modify CE directories on volumes for this user. + */ + public abstract boolean isCeStoragePrepared(@UserIdInt int userId); } diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 431bf4c54b4b..217e17ddd7b4 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -258,6 +258,13 @@ public final class DeviceConfig { public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; /** + * Namespace for all lmkd related features. + * + * @hide + */ + public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native"; + + /** * Namespace for all location related features. * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 636911c5bd15..c16e1115ca94 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2242,6 +2242,21 @@ public final class Settings { public static final String ACTION_TETHER_SETTINGS = "android.settings.TETHER_SETTINGS"; /** + * Activity Action: Show screen that lets user configure wifi tethering. + * <p> + * In some cases, a matching Activity may not exist, so ensure you safeguard against this. + * <p> + * Input: Nothing + * <p> + * Output: Nothing + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_WIFI_TETHER_SETTING = + "com.android.settings.WIFI_TETHER_SETTINGS"; + + /** * Broadcast to trigger notification of asking user to enable MMS. * Need to specify {@link #EXTRA_ENABLE_MMS_DATA_REQUEST_REASON} and {@link #EXTRA_SUB_ID}. * @@ -11868,6 +11883,12 @@ public final class Settings { public static final String WIFI_MIGRATION_COMPLETED = "wifi_migration_completed"; /** + * Whether UWB should be enabled. + * @hide + */ + public static final String UWB_ENABLED = "uwb_enabled"; + + /** * Value to specify whether network quality scores and badging should be shown in the UI. * * Type: int (0 for false, 1 for true) @@ -13693,13 +13714,6 @@ public final class Settings { "angle_gl_driver_selection_values"; /** - * List of package names that should check ANGLE rules - * @hide - */ - @Readable - public static final String ANGLE_ALLOWLIST = "angle_allowlist"; - - /** * Lists of ANGLE EGL features for debugging. * Each list of features is separated by a comma, each feature in each list is separated by * a colon. @@ -14938,6 +14952,16 @@ public final class Settings { "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/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 8e4a68e52697..40041486f6a6 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -436,7 +436,7 @@ public class StatusBarNotification implements Parcelable { try { ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, - getUserId()); + getNormalizedUserId()); mContext = context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); } catch (PackageManager.NameNotFoundException e) { diff --git a/core/java/android/service/translation/ITranslationService.aidl b/core/java/android/service/translation/ITranslationService.aidl index e9dd2c3bd70b..4cc732ab5a30 100644 --- a/core/java/android/service/translation/ITranslationService.aidl +++ b/core/java/android/service/translation/ITranslationService.aidl @@ -24,7 +24,7 @@ import com.android.internal.os.IResultReceiver; /** * System-wide on-device translation service. * - * <p>Services requests to translate text between different languages. The primary use case for this + * <p>Services requests to translate data between different languages. The primary use case for this * service is automatic translation of text and web views, when the auto Translate feature is * enabled. * diff --git a/core/java/android/service/translation/TranslationService.java b/core/java/android/service/translation/TranslationService.java index 93c006aff435..d454c393a7ce 100644 --- a/core/java/android/service/translation/TranslationService.java +++ b/core/java/android/service/translation/TranslationService.java @@ -48,6 +48,7 @@ import android.view.translation.TranslationManager; import android.view.translation.TranslationRequest; import android.view.translation.TranslationResponse; import android.view.translation.TranslationSpec; +import android.view.translation.Translator; import com.android.internal.os.IResultReceiver; @@ -81,7 +82,10 @@ public abstract class TranslationService extends Service { * android.R.styleable#TranslationService translation-service}></code> tag. * * <p>Here's an example of how to use it on {@code AndroidManifest.xml}: - * TODO: fill in doc example (check CCService/AFService). + * <pre> <translation-service + * android:settingsActivity="foo.bar.SettingsActivity" + * . . . + * /></pre> */ public static final String SERVICE_META_DATA = "android.translation_service"; @@ -148,7 +152,6 @@ public abstract class TranslationService extends Service { void onTranslationSuccess(@NonNull TranslationResponse response); /** - * TODO: implement javadoc * @removed use {@link #onTranslationSuccess} with an error response instead. */ @Deprecated @@ -225,7 +228,7 @@ public abstract class TranslationService extends Service { * should call back with {@code false}.</p> * * @param translationContext the {@link TranslationContext} of the session being created. - * @param sessionId the int id of the session. + * @param sessionId the id of the session. * @param callback {@link Consumer} to notify whether the session was successfully created. */ // TODO(b/176464808): the session id won't be unique cross client/server process. Need to find @@ -234,8 +237,6 @@ public abstract class TranslationService extends Service { int sessionId, @NonNull Consumer<Boolean> callback); /** - * TODO: fill in javadoc. - * * @removed use {@link #onCreateTranslationSession(TranslationContext, int, Consumer)} * instead. */ @@ -246,19 +247,16 @@ public abstract class TranslationService extends Service { } /** - * TODO: fill in javadoc. + * Called when a translation session is finished. + * + * <p>The translation session is finished when the client calls {@link Translator#destroy()} on + * the corresponding translator. * - * @param sessionId + * @param sessionId id of the session that finished. */ public abstract void onFinishTranslationSession(int sessionId); /** - * TODO: fill in javadoc. - * - * @param request - * @param sessionId - * @param callback - * @param cancellationSignal * @removed use * {@link #onTranslationRequest(TranslationRequest, int, CancellationSignal, Consumer)} instead. */ @@ -276,23 +274,29 @@ public abstract class TranslationService extends Service { * {@link TranslationRequest#FLAG_PARTIAL_RESPONSES} was set, the service may call * {@code callback.accept()} multiple times with partial responses.</p> * - * @param request - * @param sessionId - * @param callback - * @param cancellationSignal + * @param request The translation request containing the data to be translated. + * @param sessionId id of the session that sent the translation request. + * @param cancellationSignal A {@link CancellationSignal} that notifies when a client has + * cancelled the operation in progress. + * @param callback {@link Consumer} to pass back the translation response. */ public abstract void onTranslationRequest(@NonNull TranslationRequest request, int sessionId, @Nullable CancellationSignal cancellationSignal, @NonNull Consumer<TranslationResponse> callback); /** - * TODO: fill in javadoc + * Called to request a set of {@link TranslationCapability}s that are supported by the service. + * + * <p>The set of translation capabilities are limited to those supporting the source and target + * {@link TranslationSpec.DataFormat}. e.g. Calling this with + * {@link TranslationSpec#DATA_FORMAT_TEXT} as source and target returns only capabilities that + * translates text to text.</p> * * <p>Must call {@code callback.accept} to pass back the set of translation capabilities.</p> * - * @param sourceFormat - * @param targetFormat - * @param callback + * @param sourceFormat data format restriction of the translation source spec. + * @param targetFormat data format restriction of the translation target spec. + * @param callback {@link Consumer} to pass back the set of translation capabilities. */ public abstract void onTranslationCapabilitiesRequest( @TranslationSpec.DataFormat int sourceFormat, diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 88c9dbe9e0ab..4d49454350d7 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -96,6 +96,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -152,6 +153,7 @@ public abstract class WallpaperService extends Service { private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050; private static final int MSG_ZOOM = 10100; private static final int MSG_SCALE_PREVIEW = 10110; + private static final int MSG_REPORT_SHOWN = 10150; private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY); @@ -527,6 +529,39 @@ public abstract class WallpaperService extends Service { } /** + * This will be called in the end of {@link #updateSurface(boolean, boolean, boolean)}. + * If true is returned, the engine will not report shown until rendering finished is + * reported. Otherwise, the engine will report shown immediately right after redraw phase + * in {@link #updateSurface(boolean, boolean, boolean)}. + * + * @hide + */ + public boolean shouldWaitForEngineShown() { + return false; + } + + /** + * Reports the rendering is finished, stops waiting, then invokes + * {@link IWallpaperEngineWrapper#reportShown()}. + * + * @hide + */ + public void reportEngineShown(boolean waitForEngineShown) { + if (mIWallpaperEngine.mShownReported) return; + if (!waitForEngineShown) { + Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN); + mCaller.removeMessages(MSG_REPORT_SHOWN); + mCaller.sendMessage(message); + } else { + // if we are already waiting, no need to reset the timeout. + if (!mCaller.hasMessages(MSG_REPORT_SHOWN)) { + Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN); + mCaller.sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(5)); + } + } + } + + /** * Control whether this wallpaper will receive raw touch events * from the window manager as the user interacts with the window * that is currently displaying the wallpaper. By default they @@ -930,7 +965,7 @@ public abstract class WallpaperService extends Service { void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) { if (mDestroyed) { - Log.w(TAG, "Ignoring updateSurface: destroyed"); + Log.w(TAG, "Ignoring updateSurface due to destroyed"); return; } @@ -1198,7 +1233,6 @@ public abstract class WallpaperService extends Service { + this); onVisibilityChanged(false); } - } finally { mIsCreating = false; mSurfaceCreated = true; @@ -1208,7 +1242,7 @@ public abstract class WallpaperService extends Service { processLocalColors(mPendingXOffset, mPendingXOffsetStep); } reposition(); - mIWallpaperEngine.reportShown(); + reportEngineShown(shouldWaitForEngineShown()); } } catch (RemoteException ex) { } @@ -2049,6 +2083,8 @@ public abstract class WallpaperService extends Service { mShownReported = true; try { mConnection.engineShown(this); + Log.d(TAG, "Wallpaper has updated the surface:" + + mWallpaperManager.getWallpaperInfo()); } catch (RemoteException e) { Log.w(TAG, "Wallpaper host disappeared", e); return; @@ -2202,6 +2238,9 @@ public abstract class WallpaperService extends Service { // Connection went away, nothing to do in here. } } break; + case MSG_REPORT_SHOWN: { + reportShown(); + } break; default : Log.w(TAG, "Unknown message type " + message.what); } diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java index 362ea8c87f7f..5e647a4531bc 100644 --- a/core/java/android/speech/RecognitionService.java +++ b/core/java/android/speech/RecognitionService.java @@ -115,7 +115,7 @@ public abstract class RecognitionService extends Service { @NonNull AttributionSource attributionSource) { try { if (mCurrentCallback == null) { - boolean preflightPermissionCheckPassed = checkPermissionForPreflight( + boolean preflightPermissionCheckPassed = checkPermissionForPreflightNotHardDenied( attributionSource); if (preflightPermissionCheckPassed) { if (DBG) { @@ -470,10 +470,11 @@ public abstract class RecognitionService extends Service { return mStartedDataDelivery; } - private boolean checkPermissionForPreflight(AttributionSource attributionSource) { - return PermissionChecker.checkPermissionForPreflight(RecognitionService.this, - Manifest.permission.RECORD_AUDIO, attributionSource) - == PermissionChecker.PERMISSION_GRANTED; + private boolean checkPermissionForPreflightNotHardDenied(AttributionSource attributionSource) { + int result = PermissionChecker.checkPermissionForPreflight(RecognitionService.this, + Manifest.permission.RECORD_AUDIO, attributionSource); + return result == PermissionChecker.PERMISSION_GRANTED + || result == PermissionChecker.PERMISSION_SOFT_DENIED; } void finishDataDelivery() { diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 1f11d10052fe..1a7ec7f99c95 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -782,7 +782,7 @@ public class TextLine { int spanStart = runStart; int spanLimit; - if (mSpanned == null) { + if (mSpanned == null || runStart == runLimit) { spanLimit = runLimit; } else { int target = after ? offset + 1 : offset; diff --git a/core/java/android/text/method/TranslationTransformationMethod.java b/core/java/android/text/method/TranslationTransformationMethod.java index 80387aa8d66d..43d186ee9d21 100644 --- a/core/java/android/text/method/TranslationTransformationMethod.java +++ b/core/java/android/text/method/TranslationTransformationMethod.java @@ -62,6 +62,13 @@ public class TranslationTransformationMethod implements TransformationMethod2 { return mOriginalTranslationMethod; } + /** + * Returns the {@link TextView}'s {@link ViewTranslationResponse}. + */ + public ViewTranslationResponse getViewTranslationResponse() { + return mTranslationResponse; + } + @Override public CharSequence getTransformation(CharSequence source, View view) { if (!mAllowLengthChanges) { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 802163617b3b..a7ecf1f2a81d 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -814,9 +814,10 @@ interface IWindowManager * @param displayId The display associated with the window context * @param options A bundle used to pass window-related options and choose the right DisplayArea * - * @return {@code true} if the WindowContext is attached to the DisplayArea successfully. + * @return the DisplayArea's {@link android.app.res.Configuration} if the WindowContext is + * attached to the DisplayArea successfully. {@code null}, otherwise. */ - boolean attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, + Configuration attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, in Bundle options); /** diff --git a/core/java/android/view/ScrollCaptureResponse.java b/core/java/android/view/ScrollCaptureResponse.java index 8808827b248a..758f9ab935cf 100644 --- a/core/java/android/view/ScrollCaptureResponse.java +++ b/core/java/android/view/ScrollCaptureResponse.java @@ -53,6 +53,10 @@ public class ScrollCaptureResponse implements Parcelable { @Nullable private String mWindowTitle = null; + /** The package which owns the window. */ + @Nullable + private String mPackageName = null; + /** Carries additional logging and debugging information when enabled. */ @NonNull @DataClass.PluralOf("message") @@ -77,7 +81,7 @@ public class ScrollCaptureResponse implements Parcelable { - // Code below generated by codegen v1.0.22. + // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -97,6 +101,7 @@ public class ScrollCaptureResponse implements Parcelable { @Nullable Rect windowBounds, @Nullable Rect boundsInWindow, @Nullable String windowTitle, + @Nullable String packageName, @NonNull ArrayList<String> messages) { this.mDescription = description; com.android.internal.util.AnnotationValidations.validate( @@ -105,6 +110,7 @@ public class ScrollCaptureResponse implements Parcelable { this.mWindowBounds = windowBounds; this.mBoundsInWindow = boundsInWindow; this.mWindowTitle = windowTitle; + this.mPackageName = packageName; this.mMessages = messages; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mMessages); @@ -153,6 +159,14 @@ public class ScrollCaptureResponse implements Parcelable { } /** + * The package name of the process the window is owned by. + */ + @DataClass.Generated.Member + public @Nullable String getPackageName() { + return mPackageName; + } + + /** * Carries additional logging and debugging information when enabled. */ @DataClass.Generated.Member @@ -172,6 +186,7 @@ public class ScrollCaptureResponse implements Parcelable { "windowBounds = " + mWindowBounds + ", " + "boundsInWindow = " + mBoundsInWindow + ", " + "windowTitle = " + mWindowTitle + ", " + + "packageName = " + mPackageName + ", " + "messages = " + mMessages + " }"; } @@ -187,12 +202,14 @@ public class ScrollCaptureResponse implements Parcelable { if (mWindowBounds != null) flg |= 0x4; if (mBoundsInWindow != null) flg |= 0x8; if (mWindowTitle != null) flg |= 0x10; + if (mPackageName != null) flg |= 0x20; dest.writeByte(flg); dest.writeString(mDescription); if (mConnection != null) dest.writeStrongInterface(mConnection); if (mWindowBounds != null) dest.writeTypedObject(mWindowBounds, flags); if (mBoundsInWindow != null) dest.writeTypedObject(mBoundsInWindow, flags); if (mWindowTitle != null) dest.writeString(mWindowTitle); + if (mPackageName != null) dest.writeString(mPackageName); dest.writeStringList(mMessages); } @@ -213,6 +230,7 @@ public class ScrollCaptureResponse implements Parcelable { Rect windowBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR); Rect boundsInWindow = (flg & 0x8) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR); String windowTitle = (flg & 0x10) == 0 ? null : in.readString(); + String packageName = (flg & 0x20) == 0 ? null : in.readString(); ArrayList<String> messages = new ArrayList<>(); in.readStringList(messages); @@ -223,6 +241,7 @@ public class ScrollCaptureResponse implements Parcelable { this.mWindowBounds = windowBounds; this.mBoundsInWindow = boundsInWindow; this.mWindowTitle = windowTitle; + this.mPackageName = packageName; this.mMessages = messages; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mMessages); @@ -256,6 +275,7 @@ public class ScrollCaptureResponse implements Parcelable { private @Nullable Rect mWindowBounds; private @Nullable Rect mBoundsInWindow; private @Nullable String mWindowTitle; + private @Nullable String mPackageName; private @NonNull ArrayList<String> mMessages; private long mBuilderFieldsSet = 0L; @@ -319,12 +339,23 @@ public class ScrollCaptureResponse implements Parcelable { } /** + * The package name of the process the window is owned by. + */ + @DataClass.Generated.Member + public @NonNull Builder setPackageName(@NonNull String value) { + checkNotUsed(); + mBuilderFieldsSet |= 0x20; + mPackageName = value; + return this; + } + + /** * Carries additional logging and debugging information when enabled. */ @DataClass.Generated.Member public @NonNull Builder setMessages(@NonNull ArrayList<String> value) { checkNotUsed(); - mBuilderFieldsSet |= 0x20; + mBuilderFieldsSet |= 0x40; mMessages = value; return this; } @@ -340,7 +371,7 @@ public class ScrollCaptureResponse implements Parcelable { /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull ScrollCaptureResponse build() { checkNotUsed(); - mBuilderFieldsSet |= 0x40; // Mark builder used + mBuilderFieldsSet |= 0x80; // Mark builder used if ((mBuilderFieldsSet & 0x1) == 0) { mDescription = ""; @@ -358,6 +389,9 @@ public class ScrollCaptureResponse implements Parcelable { mWindowTitle = null; } if ((mBuilderFieldsSet & 0x20) == 0) { + mPackageName = null; + } + if ((mBuilderFieldsSet & 0x40) == 0) { mMessages = new ArrayList<>(); } ScrollCaptureResponse o = new ScrollCaptureResponse( @@ -366,12 +400,13 @@ public class ScrollCaptureResponse implements Parcelable { mWindowBounds, mBoundsInWindow, mWindowTitle, + mPackageName, mMessages); return o; } private void checkNotUsed() { - if ((mBuilderFieldsSet & 0x40) != 0) { + if ((mBuilderFieldsSet & 0x80) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } @@ -379,10 +414,10 @@ public class ScrollCaptureResponse implements Parcelable { } @DataClass.Generated( - time = 1614833185795L, - codegenVersion = "1.0.22", + time = 1628630366187L, + codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/view/ScrollCaptureResponse.java", - inputSignatures = "private @android.annotation.NonNull java.lang.String mDescription\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.MaySetToNull android.view.IScrollCaptureConnection mConnection\nprivate @android.annotation.Nullable android.graphics.Rect mWindowBounds\nprivate @android.annotation.Nullable android.graphics.Rect mBoundsInWindow\nprivate @android.annotation.Nullable java.lang.String mWindowTitle\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"message\") java.util.ArrayList<java.lang.String> mMessages\npublic boolean isConnected()\npublic void close()\nclass ScrollCaptureResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genGetters=true)") + inputSignatures = "private @android.annotation.NonNull java.lang.String mDescription\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.MaySetToNull android.view.IScrollCaptureConnection mConnection\nprivate @android.annotation.Nullable android.graphics.Rect mWindowBounds\nprivate @android.annotation.Nullable android.graphics.Rect mBoundsInWindow\nprivate @android.annotation.Nullable java.lang.String mWindowTitle\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"message\") java.util.ArrayList<java.lang.String> mMessages\npublic boolean isConnected()\npublic void close()\nclass ScrollCaptureResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genGetters=true)") @Deprecated private void __metadata() {} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a48cafcf74bb..0f4556fa02c4 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -20834,13 +20834,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; } + notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); + mAttachInfo = null; if (mOverlay != null) { mOverlay.getOverlayView().dispatchDetachedFromWindow(); } notifyEnterOrExitForAutoFillIfNeeded(false); - notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a5d3a925febd..e08420b75329 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -9507,6 +9507,7 @@ public final class ViewRootImpl implements ViewParent, ScrollCaptureResponse.Builder response = new ScrollCaptureResponse.Builder(); response.setWindowTitle(getTitle().toString()); + response.setPackageName(mContext.getPackageName()); StringWriter writer = new StringWriter(); IndentingPrintWriter pw = new IndentingPrintWriter(writer); diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java index ec55a0273999..3365c70b5b34 100644 --- a/core/java/android/view/animation/TranslateAnimation.java +++ b/core/java/android/view/animation/TranslateAnimation.java @@ -57,6 +57,9 @@ public class TranslateAnimation extends Animation { /** @hide */ protected float mToYDelta; + private int mWidth; + private int mParentWidth; + /** * Constructor used when a TranslateAnimation is loaded from a resource. * @@ -179,5 +182,60 @@ public class TranslateAnimation extends Animation { mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth); mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight); mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight); + + mWidth = width; + mParentWidth = parentWidth; + } + + /** + * Checks whether or not the translation is exclusively an x axis translation. + * + * @hide + */ + public boolean isXAxisTransition() { + return mFromXDelta - mToXDelta != 0 && mFromYDelta - mToYDelta == 0; + } + + /** + * Checks whether or not the translation is a full width x axis slide in or out translation. + * + * @hide + */ + public boolean isFullWidthTranslate() { + boolean isXAxisSlideTransition = + isSlideInLeft() || isSlideOutRight() || isSlideInRight() || isSlideOutLeft(); + return mWidth == mParentWidth && isXAxisSlideTransition; + } + + private boolean isSlideInLeft() { + boolean startsOutOfParentOnLeft = mFromXDelta <= -mWidth; + return startsOutOfParentOnLeft && endsXEnclosedWithinParent(); + } + + private boolean isSlideOutRight() { + boolean endOutOfParentOnRight = mToXDelta >= mParentWidth; + return startsXEnclosedWithinParent() && endOutOfParentOnRight; + } + + private boolean isSlideInRight() { + boolean startsOutOfParentOnRight = mFromXDelta >= mParentWidth; + return startsOutOfParentOnRight && endsXEnclosedWithinParent(); + } + + private boolean isSlideOutLeft() { + boolean endOutOfParentOnLeft = mToXDelta <= -mWidth; + return startsXEnclosedWithinParent() && endOutOfParentOnLeft; + } + + private boolean endsXEnclosedWithinParent() { + return mWidth <= mParentWidth + && mToXDelta + mWidth <= mParentWidth + && mToXDelta >= 0; + } + + private boolean startsXEnclosedWithinParent() { + return mWidth <= mParentWidth + && mFromXDelta + mWidth <= mParentWidth + && mFromXDelta >= 0; } } diff --git a/core/java/android/view/translation/TranslationCapability.java b/core/java/android/view/translation/TranslationCapability.java index 65b749add1b2..b7e13dda9ff6 100644 --- a/core/java/android/view/translation/TranslationCapability.java +++ b/core/java/android/view/translation/TranslationCapability.java @@ -40,15 +40,18 @@ import java.util.function.Consumer; public final class TranslationCapability implements Parcelable { /** - * TODO: fill in javadoc + * The translation service supports translation between the source and target specs, and it is + * ready to be downloaded onto the device. */ public static final @ModelState int STATE_AVAILABLE_TO_DOWNLOAD = 1; /** - * TODO: fill in javadoc + * The translation service supports translation between the source and target specs, and it is + * being downloaded onto the device currently. */ public static final @ModelState int STATE_DOWNLOADING = 2; /** - * TODO: fill in javadoc + * The translation service supports translation between the source and target specs, and it is + * downloaded and ready to use on device. */ public static final @ModelState int STATE_ON_DEVICE = 3; /** @@ -305,7 +308,7 @@ public final class TranslationCapability implements Parcelable { }; @DataClass.Generated( - time = 1624307114468L, + time = 1629158466039L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/view/translation/TranslationCapability.java", inputSignatures = "public static final @android.view.translation.TranslationCapability.ModelState int STATE_AVAILABLE_TO_DOWNLOAD\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_DOWNLOADING\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_ON_DEVICE\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_NOT_AVAILABLE\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_REMOVED_AND_AVAILABLE\nprivate final @android.view.translation.TranslationCapability.ModelState int mState\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final boolean mUiTranslationEnabled\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mSupportedTranslationFlags\nclass TranslationCapability extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genConstructor=false)") diff --git a/core/java/android/view/translation/TranslationRequest.java b/core/java/android/view/translation/TranslationRequest.java index df4836ebde46..0d41851ca704 100644 --- a/core/java/android/view/translation/TranslationRequest.java +++ b/core/java/android/view/translation/TranslationRequest.java @@ -39,12 +39,16 @@ public final class TranslationRequest implements Parcelable { public static final @RequestFlags int FLAG_TRANSLATION_RESULT = 0x1; /** * Indicates this request wants to receive the dictionary result. - * TODO: describe the structure of the result. + * + * <p>See {@link TranslationResponseValue#EXTRA_DEFINITIONS} for more detail on the structure + * of the returned data. */ public static final @RequestFlags int FLAG_DICTIONARY_RESULT = 0x2; /** * Indicates this request wants to receive the transliteration result. - * TODO: describe the structure of the result. + * + * <p>This returns a CharSequence representation of the transliteration of the translated text. + * See {@link TranslationResponseValue#getTransliteration()}. */ public static final @RequestFlags int FLAG_TRANSLITERATION_RESULT = 0x4; /** @@ -327,7 +331,8 @@ public final class TranslationRequest implements Parcelable { return this; } - /** @see #setTranslationRequestValues + /** + * @see #setTranslationRequestValues * @removed */ @DataClass.Generated.Member @@ -352,7 +357,8 @@ public final class TranslationRequest implements Parcelable { return this; } - /** @see #setViewTranslationRequests + /** + * @see #setViewTranslationRequests * @removed */ @DataClass.Generated.Member @@ -394,7 +400,7 @@ public final class TranslationRequest implements Parcelable { } @DataClass.Generated( - time = 1620429997487L, + time = 1629159107226L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/view/translation/TranslationRequest.java", inputSignatures = "public static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_DICTIONARY_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLITERATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_PARTIAL_RESPONSES\nprivate final @android.view.translation.TranslationRequest.RequestFlags int mFlags\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.List<android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"viewTranslationRequest\") java.util.List<android.view.translation.ViewTranslationRequest> mViewTranslationRequests\nprivate static int defaultFlags()\nprivate static java.util.List<android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nprivate static java.util.List<android.view.translation.ViewTranslationRequest> defaultViewTranslationRequests()\nclass TranslationRequest extends java.lang.Object implements [android.os.Parcelable]\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genBuilder=true)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []") diff --git a/core/java/android/view/translation/TranslationResponseValue.java b/core/java/android/view/translation/TranslationResponseValue.java index a24dbc3ae4f8..9dff2d56322b 100644 --- a/core/java/android/view/translation/TranslationResponseValue.java +++ b/core/java/android/view/translation/TranslationResponseValue.java @@ -93,9 +93,11 @@ public final class TranslationResponseValue implements Parcelable { @NonNull private final Bundle mExtras; + // TODO: Add example of transliteration. /** * The transliteration result of the translated text. - * TODO: Describe the result structure. + * + * <p>This returns a CharSequence representation of the transliteration of the translated text. */ @Nullable private final CharSequence mTransliteration; @@ -223,7 +225,8 @@ public final class TranslationResponseValue implements Parcelable { /** * The transliteration result of the translated text. - * TODO: Describe the result structure. + * + * <p>This returns a CharSequence representation of the transliteration of the translated text. */ @DataClass.Generated.Member public @Nullable CharSequence getTransliteration() { @@ -407,7 +410,8 @@ public final class TranslationResponseValue implements Parcelable { /** * The transliteration result of the translated text. - * TODO: Describe the result structure. + * + * <p>This returns a CharSequence representation of the transliteration of the translated text. */ @DataClass.Generated.Member public @NonNull Builder setTransliteration(@NonNull CharSequence value) { @@ -448,7 +452,7 @@ public final class TranslationResponseValue implements Parcelable { } @DataClass.Generated( - time = 1622133051937L, + time = 1631057245846L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/view/translation/TranslationResponseValue.java", inputSignatures = "public static final int STATUS_SUCCESS\npublic static final int STATUS_ERROR\npublic static final java.lang.String EXTRA_DEFINITIONS\nprivate final @android.view.translation.TranslationResponseValue.Status int mStatusCode\nprivate final @android.annotation.Nullable java.lang.CharSequence mText\nprivate final @android.annotation.NonNull android.os.Bundle mExtras\nprivate final @android.annotation.Nullable java.lang.CharSequence mTransliteration\npublic static @android.annotation.NonNull android.view.translation.TranslationResponseValue forError()\nprivate static java.lang.CharSequence defaultText()\nprivate static android.os.Bundle defaultExtras()\nprivate boolean extrasEquals(android.os.Bundle)\nprivate static java.lang.CharSequence defaultTransliteration()\nclass TranslationResponseValue extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)\nclass BaseBuilder extends java.lang.Object implements []") diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java index 442d099f0678..d078c2cfbfd1 100644 --- a/core/java/android/view/translation/UiTranslationController.java +++ b/core/java/android/view/translation/UiTranslationController.java @@ -431,15 +431,19 @@ public class UiTranslationController { continue; } mActivity.runOnUiThread(() -> { + ViewTranslationCallback callback = view.getViewTranslationCallback(); if (view.getViewTranslationResponse() != null && view.getViewTranslationResponse().equals(response)) { - if (DEBUG) { - Log.d(TAG, "Duplicate ViewTranslationResponse for " + autofillId - + ". Ignoring."); + if (callback instanceof TextViewTranslationCallback) { + if (((TextViewTranslationCallback) callback).isShowingTranslation()) { + if (DEBUG) { + Log.d(TAG, "Duplicate ViewTranslationResponse for " + autofillId + + ". Ignoring."); + } + return; + } } - return; } - ViewTranslationCallback callback = view.getViewTranslationCallback(); if (callback == null) { if (view instanceof TextView) { // developer doesn't provide their override, we set the default TextView @@ -598,9 +602,8 @@ public class UiTranslationController { final View rootView = roots.get(rootNum).getView(); if (rootView instanceof ViewGroup) { findViewsTraversalByAutofillIds((ViewGroup) rootView, sourceViewIds); - } else { - addViewIfNeeded(sourceViewIds, rootView); } + addViewIfNeeded(sourceViewIds, rootView); } } @@ -611,9 +614,8 @@ public class UiTranslationController { final View child = viewGroup.getChildAt(i); if (child instanceof ViewGroup) { findViewsTraversalByAutofillIds((ViewGroup) child, sourceViewIds); - } else { - addViewIfNeeded(sourceViewIds, child); } + addViewIfNeeded(sourceViewIds, child); } } diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index b9ed32ce248b..3012e9344a1b 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -33,6 +33,7 @@ import android.util.ArrayMap; 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.List; 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 @@ public final class UiTranslationManager { } } - // 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 6efd621c4caa..66c028b48dc6 100644 --- a/core/java/android/view/translation/ViewTranslationCallback.java +++ b/core/java/android/view/translation/ViewTranslationCallback.java @@ -19,9 +19,17 @@ package android.view.translation; 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,24 @@ public interface ViewTranslationCallback { * method will not be called before {@link View#onViewTranslationResponse} or * {@link View#onVirtualViewTranslationResponses}. * + * <p> NOTE: It is possible the user changes text that causes a new + * {@link ViewTranslationResponse} returns to show the new translation. If you cache the + * {@link ViewTranslationResponse} here, you should remember to keep the cached value up + * to date. + * + * <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 +66,8 @@ public interface ViewTranslationCallback { */ 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/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 91fc5a56d979..fe5eb085dc5c 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -740,6 +740,16 @@ public class RemoteViews implements Parcelable, Filter { } @Override + public UserHandle getUser() { + return mContextForResources.getUser(); + } + + @Override + public int getUserId() { + return mContextForResources.getUserId(); + } + + @Override public boolean isRestricted() { // Override isRestricted and direct to resource's implementation. The isRestricted is // used for determining the risky resources loading, e.g. fonts, thus direct to context diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java index 9d60009031f9..4a78f3ee6fac 100644 --- a/core/java/android/widget/TextViewTranslationCallback.java +++ b/core/java/android/widget/TextViewTranslationCallback.java @@ -64,13 +64,24 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { */ @Override public boolean onShowTranslation(@NonNull View view) { + if (mIsShowingTranslation) { + if (DEBUG) { + Log.d(TAG, view + " is already showing translated text."); + } + return false; + } ViewTranslationResponse response = view.getViewTranslationResponse(); if (response == null) { Log.e(TAG, "onShowTranslation() shouldn't be called before " + "onViewTranslationResponse()."); return false; } - if (mTranslationTransformation == null) { + // It is possible user changes text and new translation response returns, system should + // update the translation response to keep the result up to date. + // Because TextView.setTransformationMethod() will skip the same TransformationMethod + // instance, we should create a new one to let new translation can work. + if (mTranslationTransformation == null + || !response.equals(mTranslationTransformation.getViewTranslationResponse())) { TransformationMethod originalTranslationMethod = ((TextView) view).getTransformationMethod(); mTranslationTransformation = new TranslationTransformationMethod(response, @@ -147,7 +158,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { return true; } - boolean isShowingTranslation() { + public boolean isShowingTranslation() { return mIsShowingTranslation; } diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index acf20d701eeb..6a875d1be65d 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -316,7 +316,8 @@ public final class SplashScreenView extends FrameLayout { } private SurfaceView createSurfaceView(@NonNull SplashScreenView view) { - final SurfaceView surfaceView = new SurfaceView(view.getContext()); + final Context viewContext = view.getContext(); + final SurfaceView surfaceView = new SurfaceView(viewContext); surfaceView.setPadding(0, 0, 0, 0); surfaceView.setBackground(mIconBackground); if (mSurfacePackage == null) { @@ -326,10 +327,10 @@ public final class SplashScreenView extends FrameLayout { + Thread.currentThread().getId()); } - SurfaceControlViewHost viewHost = new SurfaceControlViewHost(mContext, - mContext.getDisplay(), + SurfaceControlViewHost viewHost = new SurfaceControlViewHost(viewContext, + viewContext.getDisplay(), surfaceView.getHostToken()); - ImageView imageView = new ImageView(mContext); + ImageView imageView = new ImageView(viewContext); imageView.setBackground(mIconDrawable); viewHost.setView(imageView, mIconSize, mIconSize); SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage(); diff --git a/core/java/android/window/WindowContext.java b/core/java/android/window/WindowContext.java index 901625b0732c..6d0a6bd559ae 100644 --- a/core/java/android/window/WindowContext.java +++ b/core/java/android/window/WindowContext.java @@ -26,7 +26,6 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; import android.os.Bundle; -import android.os.IBinder; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; @@ -67,7 +66,7 @@ public class WindowContext extends ContextWrapper { mType = type; mOptions = options; mWindowManager = createWindowContextWindowManager(this); - IBinder token = getWindowContextToken(); + WindowTokenClient token = (WindowTokenClient) getWindowContextToken(); mController = new WindowContextController(token); Reference.reachabilityFence(this); diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java index d84f571931fd..505b45008663 100644 --- a/core/java/android/window/WindowContextController.java +++ b/core/java/android/window/WindowContextController.java @@ -19,6 +19,7 @@ package android.window; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -46,7 +47,7 @@ public class WindowContextController { @VisibleForTesting public boolean mAttachedToDisplayArea; @NonNull - private final IBinder mToken; + private final WindowTokenClient mToken; /** * Window Context Controller constructor @@ -54,14 +55,13 @@ public class WindowContextController { * @param token The token used to attach to a window manager node. It is usually from * {@link Context#getWindowContextToken()}. */ - public WindowContextController(@NonNull IBinder token) { - mToken = token; - mWms = WindowManagerGlobal.getWindowManagerService(); + public WindowContextController(@NonNull WindowTokenClient token) { + this(token, WindowManagerGlobal.getWindowManagerService()); } /** Used for test only. DO NOT USE it in production code. */ @VisibleForTesting - public WindowContextController(@NonNull IBinder token, IWindowManager mockWms) { + public WindowContextController(@NonNull WindowTokenClient token, IWindowManager mockWms) { mToken = token; mWms = mockWms; } @@ -81,8 +81,14 @@ public class WindowContextController { + "a DisplayArea once."); } try { - mAttachedToDisplayArea = mWms.attachWindowContextToDisplayArea(mToken, type, displayId, - options); + final Configuration configuration = mWms.attachWindowContextToDisplayArea(mToken, type, + displayId, options); + if (configuration != null) { + mAttachedToDisplayArea = true; + // Send the DisplayArea's configuration to WindowContext directly instead of + // waiting for dispatching from WMS. + mToken.onConfigurationChanged(configuration, displayId); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index 6abf5575d353..4dcd2e74a53f 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -24,6 +24,8 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; +import com.android.internal.annotations.VisibleForTesting; + import java.lang.ref.WeakReference; /** @@ -33,7 +35,7 @@ import java.lang.ref.WeakReference; * {@link Context#getWindowContextToken() the token of non-Activity UI Contexts}. * * @see WindowContext - * @see android.view.IWindowManager#registerWindowContextListener(IBinder, int, int, Bundle) + * @see android.view.IWindowManager#attachWindowContextToDisplayArea(IBinder, int, int, Bundle) * * @hide */ @@ -50,8 +52,8 @@ public class WindowTokenClient extends IWindowToken.Stub { * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient} * can only attach one {@link Context}. * <p>This method must be called before invoking - * {@link android.view.IWindowManager#registerWindowContextListener(IBinder, int, int, - * Bundle, boolean)}.<p/> + * {@link android.view.IWindowManager#attachWindowContextToDisplayArea(IBinder, int, int, + * Bundle)}.<p/> * * @param context context to be attached * @throws IllegalStateException if attached context has already existed. @@ -63,6 +65,13 @@ public class WindowTokenClient extends IWindowToken.Stub { mContextRef = new WeakReference<>(context); } + /** + * Called when {@link Configuration} updates from the server side receive. + * + * @param newConfig the updated {@link Configuration} + * @param newDisplayId the updated {@link android.view.Display} ID + */ + @VisibleForTesting @Override public void onConfigurationChanged(Configuration newConfig, int newDisplayId) { final Context context = mContextRef.get(); diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java index 84354d90b5f3..ec224e50eb8d 100644 --- a/core/java/com/android/internal/app/SuspendedAppActivity.java +++ b/core/java/com/android/internal/app/SuspendedAppActivity.java @@ -72,17 +72,19 @@ public class SuspendedAppActivity extends AlertActivity private Resources mSuspendingAppResources; private SuspendDialogInfo mSuppliedDialogInfo; private Bundle mOptions; - private BroadcastReceiver mUnsuspendReceiver = new BroadcastReceiver() { + private BroadcastReceiver mSuspendModifiedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(intent.getAction())) { - final String[] unsuspended = intent.getStringArrayExtra( + if (Intent.ACTION_PACKAGES_SUSPENSION_CHANGED.equals(intent.getAction())) { + // Suspension conditions were modified, dismiss any related visible dialogs. + final String[] modified = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_PACKAGE_LIST); - if (ArrayUtils.contains(unsuspended, mSuspendedPackage)) { + if (ArrayUtils.contains(modified, mSuspendedPackage)) { if (!isFinishing()) { - Slog.w(TAG, "Package " + mSuspendedPackage - + " got unsuspended while the dialog was visible. Finishing."); + Slog.w(TAG, "Package " + mSuspendedPackage + " has modified" + + " suspension conditions while dialog was visible. Finishing."); SuspendedAppActivity.this.finish(); + // TODO (b/198201994): reload the suspend dialog to show most relevant info } } } @@ -245,15 +247,16 @@ public class SuspendedAppActivity extends AlertActivity setupAlert(); - final IntentFilter unsuspendFilter = new IntentFilter(Intent.ACTION_PACKAGES_UNSUSPENDED); - registerReceiverAsUser(mUnsuspendReceiver, UserHandle.of(mUserId), unsuspendFilter, null, - null); + final IntentFilter suspendModifiedFilter = + new IntentFilter(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED); + registerReceiverAsUser(mSuspendModifiedReceiver, UserHandle.of(mUserId), + suspendModifiedFilter, null, null); } @Override protected void onDestroy() { super.onDestroy(); - unregisterReceiver(mUnsuspendReceiver); + unregisterReceiver(mSuspendModifiedReceiver); } private void requestDismissKeyguardIfNeeded(CharSequence dismissMessage) { diff --git a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java index ce75f45d0897..068b882eb4f7 100644 --- a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java +++ b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java @@ -165,7 +165,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { // Now fetch app icon and raster with no badging even in work profile Bitmap appIcon = mSelectableTargetInfoCommunicator.makePresentationGetter(info) - .getIconBitmap(android.os.Process.myUserHandle()); + .getIconBitmap(mContext.getUser()); // Raster target drawable with appIcon as a badge SimpleIconFactory sif = SimpleIconFactory.obtain(mContext); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 8c63f38494ea..a817119a735f 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -707,6 +707,10 @@ public class BatteryStatsImpl extends BatteryStats { * Mapping isolated uids to the actual owning app uid. */ final SparseIntArray mIsolatedUids = new SparseIntArray(); + /** + * Internal reference count of isolated uids. + */ + final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray(); /** * The statistics we have collected organized by uids. @@ -3897,6 +3901,7 @@ public class BatteryStatsImpl extends BatteryStats { public void addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs) { mIsolatedUids.put(isolatedUid, appUid); + mIsolatedUidRefCounts.put(isolatedUid, 1); final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs); u.addIsolatedUid(isolatedUid); } @@ -3915,19 +3920,51 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * This should only be called after the cpu times have been read. + * Isolated uid should only be removed after all wakelocks associated with the uid are stopped + * and the cpu time-in-state has been read one last time for the uid. + * * @see #scheduleRemoveIsolatedUidLocked(int, int) + * + * @return true if the isolated uid is actually removed. */ @GuardedBy("this") - public void removeIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) { + public boolean maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, + long uptimeMs) { + final int refCount = mIsolatedUidRefCounts.get(isolatedUid, 0) - 1; + if (refCount > 0) { + // Isolated uid is still being tracked + mIsolatedUidRefCounts.put(isolatedUid, refCount); + return false; + } + final int idx = mIsolatedUids.indexOfKey(isolatedUid); if (idx >= 0) { final int ownerUid = mIsolatedUids.valueAt(idx); final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs); u.removeIsolatedUid(isolatedUid); mIsolatedUids.removeAt(idx); + mIsolatedUidRefCounts.delete(isolatedUid); + } else { + Slog.w(TAG, "Attempted to remove untracked isolated uid (" + isolatedUid + ")"); } mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs)); + + return true; + } + + /** + * Increment the ref count for an isolated uid. + * call #maybeRemoveIsolatedUidLocked to decrement. + */ + public void incrementIsolatedUidRefCount(int uid) { + final int refCount = mIsolatedUidRefCounts.get(uid, 0); + if (refCount <= 0) { + // Uid is not mapped or referenced + Slog.w(TAG, + "Attempted to increment ref counted of untracked isolated uid (" + uid + ")"); + return; + } + mIsolatedUidRefCounts.put(uid, refCount + 1); } public int mapUid(int uid) { @@ -4287,7 +4324,7 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); + final int mappedUid = mapUid(uid); if (type == WAKE_TYPE_PARTIAL) { // Only care about partial wake locks, since full wake locks // will be canceled when the user puts the screen to sleep. @@ -4297,9 +4334,9 @@ public class BatteryStatsImpl extends BatteryStats { } if (mRecordAllHistory) { if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName, - uid, 0)) { + mappedUid, 0)) { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, - HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid); + HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid); } } if (mWakeLockNesting == 0) { @@ -4308,7 +4345,7 @@ public class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; - mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; + mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid; mWakeLockImportant = !unimportantForLogging; addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } else if (!mWakeLockImportant && !unimportantForLogging @@ -4318,14 +4355,19 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryLastWritten.wakelockTag = null; mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; - mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; + mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = mappedUid; addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mWakeLockImportant = true; } mWakeLockNesting++; } - if (uid >= 0) { + if (mappedUid >= 0) { + if (mappedUid != uid) { + // Prevent the isolated uid mapping from being removed while the wakelock is + // being held. + incrementIsolatedUidRefCount(uid); + } if (mOnBatteryScreenOffTimeBase.isRunning()) { // We only update the cpu time when a wake lock is acquired if the screen is off. // If the screen is on, we don't distribute the power amongst partial wakelocks. @@ -4335,7 +4377,7 @@ public class BatteryStatsImpl extends BatteryStats { requestWakelockCpuUpdate(); } - getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs) .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs); if (wc != null) { @@ -4343,8 +4385,8 @@ public class BatteryStatsImpl extends BatteryStats { wc.getTags(), getPowerManagerWakeLockLevel(type), name, FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); } else { - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid, - null, getPowerManagerWakeLockLevel(type), name, + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, + mappedUid, null, getPowerManagerWakeLockLevel(type), name, FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); } } @@ -4358,7 +4400,7 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); + final int mappedUid = mapUid(uid); if (type == WAKE_TYPE_PARTIAL) { mWakeLockNesting--; if (mRecordAllHistory) { @@ -4366,9 +4408,9 @@ public class BatteryStatsImpl extends BatteryStats { historyName = name; } if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, - uid, 0)) { + mappedUid, 0)) { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, - HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid); + HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid); } } if (mWakeLockNesting == 0) { @@ -4380,7 +4422,7 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } - if (uid >= 0) { + if (mappedUid >= 0) { if (mOnBatteryScreenOffTimeBase.isRunning()) { if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because of -wake_lock"); @@ -4388,17 +4430,22 @@ public class BatteryStatsImpl extends BatteryStats { requestWakelockCpuUpdate(); } - getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs) .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs); if (wc != null) { FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), getPowerManagerWakeLockLevel(type), name, FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); } else { - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid, - null, getPowerManagerWakeLockLevel(type), name, + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, + mappedUid, null, getPowerManagerWakeLockLevel(type), name, FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); } + + if (mappedUid != uid) { + // Decrement the ref count for the isolated uid and delete the mapping if uneeded. + maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs); + } } } @@ -8571,7 +8618,7 @@ public class BatteryStatsImpl extends BatteryStats { * inactive so can be dropped. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean reset(long uptimeUs, long realtimeUs) { + public boolean reset(long uptimeUs, long realtimeUs, int resetReason) { boolean active = false; mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs); @@ -8641,7 +8688,11 @@ public class BatteryStatsImpl extends BatteryStats { resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs); resetIfNotNull(mModemControllerActivity, false, realtimeUs); - MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats); + if (resetReason == RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE) { + mUidMeasuredEnergyStats = null; + } else { + MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats); + } resetIfNotNull(mUserCpuTime, false, realtimeUs); resetIfNotNull(mSystemCpuTime, false, realtimeUs); @@ -11324,7 +11375,7 @@ public class BatteryStatsImpl extends BatteryStats { mNumConnectivityChange = 0; for (int i=0; i<mUidStats.size(); i++) { - if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs)) { + if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) { mUidStats.valueAt(i).detachFromTimeBase(); mUidStats.remove(mUidStats.keyAt(i)); i--; @@ -16761,6 +16812,15 @@ public class BatteryStatsImpl extends BatteryStats { pw.print("UIDs removed since the later of device start or stats reset: "); pw.println(mNumUidsRemoved); + pw.println("Currently mapped isolated uids:"); + final int numIsolatedUids = mIsolatedUids.size(); + for (int i = 0; i < numIsolatedUids; i++) { + final int isolatedUid = mIsolatedUids.keyAt(i); + final int ownerUid = mIsolatedUids.valueAt(i); + final int refCount = mIsolatedUidRefCounts.get(isolatedUid); + pw.println(" " + isolatedUid + "->" + ownerUid + " (ref count = " + refCount + ")"); + } + pw.println(); dumpConstantsLocked(pw); diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index 00385793b62b..980aec196079 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -29,6 +29,7 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -234,8 +235,9 @@ public class BatteryUsageStatsProvider { final boolean includePowerModels = (query.getFlags() & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0; + final String[] customEnergyConsumerNames = mStats.getCustomEnergyConsumerNames(); final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder( - mStats.getCustomEnergyConsumerNames(), includePowerModels); + customEnergyConsumerNames, includePowerModels); if (mBatteryUsageStatsStore == null) { Log.e(TAG, "BatteryUsageStatsStore is unavailable"); return builder.build(); @@ -247,7 +249,14 @@ public class BatteryUsageStatsProvider { final BatteryUsageStats snapshot = mBatteryUsageStatsStore.loadBatteryUsageStats(timestamp); if (snapshot != null) { - builder.add(snapshot); + if (Arrays.equals(snapshot.getCustomPowerComponentNames(), + customEnergyConsumerNames)) { + builder.add(snapshot); + } else { + Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different " + + "custom power components: " + + Arrays.toString(snapshot.getCustomPowerComponentNames())); + } } } } diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java index 9b51a8ef6410..bb307a0d29d8 100644 --- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java +++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java @@ -21,13 +21,18 @@ import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.UidBatteryConsumer; +import android.util.Slog; import android.util.SparseArray; +import java.util.Arrays; + /** * Calculates the amount of power consumed by custom energy consumers (i.e. consumers of type * {@link android.hardware.power.stats.EnergyConsumerType#OTHER}). */ public class CustomMeasuredPowerCalculator extends PowerCalculator { + private static final String TAG = "CustomMeasuredPowerCalc"; + public CustomMeasuredPowerCalculator(PowerProfile powerProfile) { } @@ -76,9 +81,9 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { if (totalPowerMah == null) { newTotalPowerMah = new double[customMeasuredPowerMah.length]; } else if (totalPowerMah.length != customMeasuredPowerMah.length) { - newTotalPowerMah = new double[customMeasuredPowerMah.length]; - System.arraycopy(totalPowerMah, 0, newTotalPowerMah, 0, - customMeasuredPowerMah.length); + Slog.wtf(TAG, "Number of custom energy components is not the same for all apps: " + + totalPowerMah.length + ", " + customMeasuredPowerMah.length); + newTotalPowerMah = Arrays.copyOf(totalPowerMah, customMeasuredPowerMah.length); } else { newTotalPowerMah = totalPowerMah; } diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java index 776a70545df4..3915b0e01e7f 100644 --- a/core/java/com/android/internal/os/WifiPowerCalculator.java +++ b/core/java/com/android/internal/os/WifiPowerCalculator.java @@ -215,6 +215,9 @@ public class WifiPowerCalculator extends PowerCalculator { + "ms tx=" + txTime + "ms power=" + formatCharge( powerDurationAndTraffic.powerMah)); } + } else { + powerDurationAndTraffic.durationMs = 0; + powerDurationAndTraffic.powerMah = 0; } } else { final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000; diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java index b321ac08912b..a09c8236b47d 100644 --- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java +++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java @@ -124,7 +124,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { - sendCloseSystemWindows(); mContext.startActivity(intent); } catch (ActivityNotFoundException e) { startCallActivity(); @@ -147,7 +146,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { dispatcher.performedLongPress(event); if (isUserSetupComplete()) { mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - sendCloseSystemWindows(); // Broadcast an intent that the Camera button was longpressed Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -178,7 +176,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - sendCloseSystemWindows(); getSearchManager().stopSearch(); mContext.startActivity(intent); // Only clear this if we successfully start the @@ -272,7 +269,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { @UnsupportedAppUsage void startCallActivity() { - sendCloseSystemWindows(); Intent intent = new Intent(Intent.ACTION_CALL_BUTTON); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { @@ -319,10 +315,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { return mMediaSessionManager; } - void sendCloseSystemWindows() { - PhoneWindow.sendCloseSystemWindows(mContext, null); - } - private void handleVolumeKeyEvent(KeyEvent keyEvent) { getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE); diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 10f14b42ae42..ed6415d749a3 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -148,7 +148,7 @@ oneway interface IStatusBar */ void showAuthenticationDialog(in PromptInfo promptInfo, IBiometricSysuiReceiver sysuiReceiver, in int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, int userId, - String opPackageName, long operationId, int multiSensorConfig); + long operationId, String opPackageName, long requestId, int multiSensorConfig); /** * Used to notify the authentication dialog that a biometric has been authenticated. */ diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index e7d6d6cf8936..b3499db94c88 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -110,7 +110,8 @@ interface IStatusBarService // Used to show the authentication dialog (Biometrics, Device Credential) void showAuthenticationDialog(in PromptInfo promptInfo, IBiometricSysuiReceiver sysuiReceiver, in int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, - int userId, String opPackageName, long operationId, int multiSensorConfig); + int userId, long operationId, String opPackageName, long requestId, + int multiSensorConfig); // Used to notify the authentication dialog that a biometric has been authenticated void onBiometricAuthenticated(); diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java index 8b3c1337c0c8..7a712e50e6a8 100644 --- a/core/java/com/android/internal/util/ContrastColorUtil.java +++ b/core/java/com/android/internal/util/ContrastColorUtil.java @@ -291,10 +291,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. - * @param other the color to ensure contrast against. Assumed to be lighter than {@param color} - * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. + * @param other the color to ensure contrast against. Assumed to be lighter than {@code color} + * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @param minRatio the minimum contrast ratio required. - * @return a color with the same hue as {@param color}, potentially darkened to meet the + * @return a color with the same hue as {@code color}, potentially darkened to meet the * contrast ratio. */ public static int findContrastColor(int color, int other, boolean findFg, double minRatio) { @@ -331,7 +331,7 @@ public class ContrastColorUtil { * @param color the color to start searching from. * @param backgroundColor the color to ensure contrast against. * @param minRatio the minimum contrast ratio required. - * @return the same color as {@param color} with potentially modified alpha to meet contrast + * @return the same color as {@code color} with potentially modified alpha to meet contrast */ public static int findAlphaToMeetContrast(int color, int backgroundColor, double minRatio) { int fg = color; @@ -361,10 +361,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. - * @param other the color to ensure contrast against. Assumed to be darker than {@param color} - * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. + * @param other the color to ensure contrast against. Assumed to be darker than {@code color} + * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @param minRatio the minimum contrast ratio required. - * @return a color with the same hue as {@param color}, potentially darkened to meet the + * @return a color with the same hue as {@code color}, potentially lightened to meet the * contrast ratio. */ public static int findContrastColorAgainstDark(int color, int other, boolean findFg, @@ -393,7 +393,8 @@ public class ContrastColorUtil { low = l; } } - return findFg ? fg : bg; + hsl[2] = high; + return ColorUtilsFromCompat.HSLToColor(hsl); } public static int ensureTextContrastOnBlack(int color) { @@ -452,7 +453,7 @@ public class ContrastColorUtil { } /** - * Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT} + * Resolves {@code color} to an actual color if it is {@link Notification#COLOR_DEFAULT} */ public static int resolveColor(Context context, int color, boolean defaultBackgroundIsDark) { if (color == Notification.COLOR_DEFAULT) { diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index fdaf5701578e..ea488947ae7b 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -17,6 +17,7 @@ package com.android.internal.widget; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; @@ -1283,6 +1284,14 @@ public class LockPatternUtils { } /** + * Whether the user is not allowed to set any credentials via PASSWORD_QUALITY_MANAGED. + */ + public boolean isCredentialsDisabledForUser(int userId) { + return getDevicePolicyManager().getPasswordQuality(/* admin= */ null, userId) + == PASSWORD_QUALITY_MANAGED; + } + + /** * @see StrongAuthTracker#isTrustAllowedForUser */ public boolean isTrustAllowedForUser(int userId) { diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java index 0c2d2a9bcf41..3191e23a9883 100644 --- a/core/java/com/android/internal/widget/NotificationActionListLayout.java +++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java @@ -53,6 +53,8 @@ public class NotificationActionListLayout extends LinearLayout { private int mEmphasizedHeight; private int mRegularHeight; @DimenRes private int mCollapsibleIndentDimen = R.dimen.notification_actions_padding_start; + int mNumNotGoneChildren; + int mNumPriorityChildren; public NotificationActionListLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -76,15 +78,14 @@ public class NotificationActionListLayout extends LinearLayout { && ((EmphasizedNotificationButton) actionView).isPriority(); } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int N = getChildCount(); + private void countAndRebuildMeasureOrder() { + final int numChildren = getChildCount(); int textViews = 0; int otherViews = 0; - int notGoneChildren = 0; - int priorityChildren = 0; + mNumNotGoneChildren = 0; + mNumPriorityChildren = 0; - for (int i = 0; i < N; i++) { + for (int i = 0; i < numChildren; i++) { View c = getChildAt(i); if (c instanceof TextView) { textViews++; @@ -92,9 +93,9 @@ public class NotificationActionListLayout extends LinearLayout { otherViews++; } if (c.getVisibility() != GONE) { - notGoneChildren++; + mNumNotGoneChildren++; if (isPriority(c)) { - priorityChildren++; + mNumPriorityChildren++; } } } @@ -119,17 +120,20 @@ public class NotificationActionListLayout extends LinearLayout { if (needRebuild) { rebuildMeasureOrder(textViews, otherViews); } + } + private int measureAndGetUsedWidth(int widthMeasureSpec, int heightMeasureSpec, int innerWidth, + boolean collapsePriorityActions) { + final int numChildren = getChildCount(); final boolean constrained = MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED; - - final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight; final int otherSize = mMeasureOrderOther.size(); int usedWidth = 0; + int maxPriorityWidth = 0; int measuredChildren = 0; int measuredPriorityChildren = 0; - for (int i = 0; i < N; i++) { + for (int i = 0; i < numChildren; i++) { // Measure shortest children first. To avoid measuring twice, we approximate by looking // at the text length. final boolean isPriority; @@ -154,12 +158,20 @@ public class NotificationActionListLayout extends LinearLayout { // measure in the order of (approx.) size, a large view can still take more than its // share if the others are small. int availableWidth = innerWidth - usedWidth; - int unmeasuredChildren = notGoneChildren - measuredChildren; + int unmeasuredChildren = mNumNotGoneChildren - measuredChildren; int maxWidthForChild = availableWidth / unmeasuredChildren; - if (isPriority) { + if (isPriority && collapsePriorityActions) { + // Collapsing the actions to just the width required to show the icon. + if (maxPriorityWidth == 0) { + maxPriorityWidth = getResources().getDimensionPixelSize( + R.dimen.notification_actions_collapsed_priority_width); + } + maxWidthForChild = maxPriorityWidth + lp.leftMargin + lp.rightMargin; + } else if (isPriority) { // Priority children get a larger maximum share of the total space: // maximum priority share = (nPriority + 1) / (MAX + 1) - int unmeasuredPriorityChildren = priorityChildren - measuredPriorityChildren; + int unmeasuredPriorityChildren = mNumPriorityChildren + - measuredPriorityChildren; int unmeasuredOtherChildren = unmeasuredChildren - unmeasuredPriorityChildren; int widthReservedForOtherChildren = innerWidth * unmeasuredOtherChildren / (Notification.MAX_ACTION_BUTTONS + 1); @@ -187,6 +199,19 @@ public class NotificationActionListLayout extends LinearLayout { } else { mExtraStartPadding = 0; } + return usedWidth; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + countAndRebuildMeasureOrder(); + final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight; + int usedWidth = measureAndGetUsedWidth(widthMeasureSpec, heightMeasureSpec, innerWidth, + false /* collapsePriorityButtons */); + if (mNumPriorityChildren != 0 && usedWidth >= innerWidth) { + usedWidth = measureAndGetUsedWidth(widthMeasureSpec, heightMeasureSpec, innerWidth, + true /* collapsePriorityButtons */); + } mTotalWidth = usedWidth + mPaddingRight + mPaddingLeft + mExtraStartPadding; setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec), diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index b40491a49b14..f44e829d49d7 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -50,8 +50,7 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, } void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, - jstring devOptIn, jobjectArray featuresObj, jobject rulesFd, - jlong rulesOffset, jlong rulesLength) { + jstring devOptIn, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); ScopedUtfChars appNameChars(env, appName); ScopedUtfChars devOptInChars(env, devOptIn); @@ -74,11 +73,8 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appNa } } - int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd); - android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(), - devOptInChars.c_str(), features, - rulesFd_native, rulesOffset, rulesLength); + devOptInChars.c_str(), features); } bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) { @@ -124,8 +120,7 @@ const JNINativeMethod g_methods[] = { {"setInjectLayersPrSetDumpable", "()Z", reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)}, {"setAngleInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/io/" - "FileDescriptor;JJ)V", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", reinterpret_cast<void*>(setAngleInfo_native)}, {"getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native)}, diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index ea754db9fa75..2a27b0998d4a 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -773,6 +773,8 @@ message GlobalSettingsProto { 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; @@ -972,6 +974,7 @@ message GlobalSettingsProto { optional SettingProto usb_mass_storage_enabled = 127 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto use_google_mail = 128 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto use_open_wifi_package = 129 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto uwb_enabled = 155 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto vt_ims_enabled = 130 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto wait_for_debugger = 131 [ (android.privacy).dest = DEST_AUTOMATIC ]; @@ -1065,5 +1068,5 @@ message GlobalSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 154; + // Next tag = 156; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 59d4d8b58f5f..2ef64107ab3c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -56,6 +56,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" /> + <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENSION_CHANGED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY" /> <protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" /> <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" /> @@ -252,6 +253,8 @@ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" /> <protected-broadcast android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" /> diff --git a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml index 5add19bba51b..aa3800061bd3 100644 --- a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml +++ b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml @@ -18,19 +18,9 @@ --> <!-- This should be kept in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:hasRoundedCorners="true" android:shareInterpolator="false" - android:zAdjustment="top"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="-105%" @@ -38,36 +28,9 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> <!-- To keep the thumbnail around longer and fade out the thumbnail --> <alpha android:fromAlpha="1.0" android:toAlpha="0" diff --git a/core/res/res/anim-ldrtl/task_close_enter.xml b/core/res/res/anim-ldrtl/task_close_enter.xml index e00141a8c155..5ace46d4c621 100644 --- a/core/res/res/anim-ldrtl/task_close_enter.xml +++ b/core/res/res/anim-ldrtl/task_close_enter.xml @@ -14,20 +14,9 @@ ~ limitations under the License --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="105%" @@ -35,34 +24,7 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim-ldrtl/task_close_exit.xml b/core/res/res/anim-ldrtl/task_close_exit.xml index 71a44ae7d2fc..0887019ca608 100644 --- a/core/res/res/anim-ldrtl/task_close_exit.xml +++ b/core/res/res/anim-ldrtl/task_close_exit.xml @@ -15,19 +15,8 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1.0" - android:toAlpha="1" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="283"/> + android:shareInterpolator="false" + android:hasRoundedCorners="true"> <translate android:fromXDelta="0" @@ -35,26 +24,8 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0" - android:toXScale="0.95" - android:fromYScale="1.0" - android:toYScale="0.95" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:pivotX="50%" - android:pivotY="50%" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim-ldrtl/task_open_enter.xml b/core/res/res/anim-ldrtl/task_open_enter.xml index 7815f7d661d0..52c74a6c4482 100644 --- a/core/res/res/anim-ldrtl/task_open_enter.xml +++ b/core/res/res/anim-ldrtl/task_open_enter.xml @@ -16,20 +16,9 @@ <!-- This should in sync with task_open_enter_cross_profile_apps.xml --> <!-- This should in sync with cross_profile_apps_thumbnail_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="-105%" @@ -37,34 +26,7 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> -</set>
\ No newline at end of file + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> +</set> diff --git a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml index 5fccd6df14a5..90ec0715f8b0 100644 --- a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml +++ b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml @@ -16,20 +16,9 @@ --> <!-- This should in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="-105%" @@ -37,36 +26,9 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> <!-- To keep the transition around longer for the thumbnail, should be kept in sync with cross_profile_apps_thumbmail.xml --> @@ -75,4 +37,4 @@ android:toAlpha="1.0" android:startOffset="717" android:duration="200"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim-ldrtl/task_open_exit.xml b/core/res/res/anim-ldrtl/task_open_exit.xml index 025e1bdc05c9..88cdcceae415 100644 --- a/core/res/res/anim-ldrtl/task_open_exit.xml +++ b/core/res/res/anim-ldrtl/task_open_exit.xml @@ -15,19 +15,8 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1.0" - android:toAlpha="1" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="283"/> + android:shareInterpolator="false" + android:hasRoundedCorners="true"> <translate android:fromXDelta="0" @@ -35,26 +24,8 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0" - android:toXScale="0.95" - android:fromYScale="1.0" - android:toYScale="0.95" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:pivotX="50%" - android:pivotY="50%" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml index 2cfeecf4685d..f6d7b7229677 100644 --- a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml +++ b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml @@ -19,18 +19,8 @@ <!-- This should be kept in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" - android:hasRoundedCorners="true" - android:zAdjustment="top"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="105%" @@ -38,36 +28,9 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> <!-- To keep the thumbnail around longer and fade out the thumbnail --> <alpha android:fromAlpha="1.0" android:toAlpha="0" diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml index 487ff5c748d3..52017b1091bc 100644 --- a/core/res/res/anim/task_close_enter.xml +++ b/core/res/res/anim/task_close_enter.xml @@ -16,20 +16,9 @@ */ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="-105%" @@ -37,34 +26,7 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml index afc3256cb617..3a8dd934cd17 100644 --- a/core/res/res/anim/task_close_exit.xml +++ b/core/res/res/anim/task_close_exit.xml @@ -17,19 +17,8 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1.0" - android:toAlpha="1" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="283"/> + android:shareInterpolator="false" + android:hasRoundedCorners="true"> <translate android:fromXDelta="0" @@ -37,26 +26,8 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0" - android:toXScale="0.95" - android:fromYScale="1.0" - android:toYScale="0.95" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:pivotX="50%" - android:pivotY="50%" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml index 0aafc1c0b91c..3c934382bb75 100644 --- a/core/res/res/anim/task_open_enter.xml +++ b/core/res/res/anim/task_open_enter.xml @@ -15,23 +15,12 @@ ** limitations under the License. */ --> -<!-- This should in sync with task_open_enter_cross_profile_apps.xml --> -<!-- This should in sync with cross_profile_apps_thumbnail_enter.xml --> +<!-- This should be kept in sync with task_open_enter_cross_profile_apps.xml --> +<!-- This should be kept in sync with cross_profile_apps_thumbnail_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="105%" @@ -39,34 +28,7 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml index 702f7ba162aa..16249d15e1b7 100644 --- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml +++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml @@ -18,20 +18,9 @@ --> <!-- This should in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1" - android:toAlpha="1.0" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="217"/> + android:shareInterpolator="false" + android:zAdjustment="top" + android:hasRoundedCorners="true"> <translate android:fromXDelta="105%" @@ -39,36 +28,9 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0526" - android:toXScale="1" - android:fromYScale="1.0526" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> - - <scale - android:fromXScale="0.95" - android:toXScale="1" - android:fromYScale="0.95" - android:toYScale="1" - android:pivotX="50%" - android:pivotY="50%" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="283" - android:duration="317"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> <!-- To keep the transition around longer for the thumbnail, should be kept in sync with cross_profile_apps_thumbmail.xml --> diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml index 691317d2e6e0..21fec7f694bf 100644 --- a/core/res/res/anim/task_open_exit.xml +++ b/core/res/res/anim/task_open_exit.xml @@ -17,19 +17,8 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:hasRoundedCorners="true" - android:showWallpaper="true"> - - <alpha - android:fromAlpha="1.0" - android:toAlpha="1" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:interpolator="@interpolator/linear" - android:startOffset="67" - android:duration="283"/> + android:shareInterpolator="false" + android:hasRoundedCorners="true"> <translate android:fromXDelta="0" @@ -37,26 +26,8 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/aggressive_ease" - android:startOffset="50" - android:duration="383"/> - - <scale - android:fromXScale="1.0" - android:toXScale="0.95" - android:fromYScale="1.0" - android:toYScale="0.95" - android:fillEnabled="true" - android:fillBefore="true" - android:fillAfter="true" - android:pivotX="50%" - android:pivotY="50%" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="283"/> + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:startOffset="0" + android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/color/overview_background.xml b/core/res/res/color/overview_background.xml new file mode 100644 index 000000000000..45c6c256d67a --- /dev/null +++ b/core/res/res/color/overview_background.xml @@ -0,0 +1,19 @@ +<?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. + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@android:color/system_neutral2_500" android:lStar="87" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/color/overview_background_dark.xml b/core/res/res/color/overview_background_dark.xml new file mode 100644 index 000000000000..84f4fdff4e1a --- /dev/null +++ b/core/res/res/color/overview_background_dark.xml @@ -0,0 +1,19 @@ +<?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. + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@android:color/system_neutral2_500" android:lStar="35" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/btn_notification_emphasized.xml b/core/res/res/drawable/btn_notification_emphasized.xml index 29c51f2a33c9..7c09fb889c48 100644 --- a/core/res/res/drawable/btn_notification_emphasized.xml +++ b/core/res/res/drawable/btn_notification_emphasized.xml @@ -24,9 +24,9 @@ android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/notification_action_button_radius" /> - <padding android:left="12dp" + <padding android:left="16dp" android:top="@dimen/button_padding_vertical_material" - android:right="12dp" + android:right="16dp" android:bottom="@dimen/button_padding_vertical_material" /> <solid android:color="@color/white" /> </shape> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 6946b3c07652..4541366c31cb 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik jou vingerafdruk of skermslot om voort te gaan"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Iets is fout. Probeer weer."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdrukikoon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Gesigslot"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Kwessie met Gesigslot"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik jou gesig of skermslot om voort te gaan"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Iets is fout. Probeer weer."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Gesig-ikoon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lees sinkroniseer-instellings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Laat die program toe om die sinkroniseringinstellings van \'n rekening te lees. Byvoorbeeld, dit kan bepaal of die People-program met \'n rekening gesinkroniseer is."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 9ab2f1939c84..4da99e27ebf7 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ለመቀጠል የጣት አሻራዎን ወይም የማያ ገጽ ቁልፍዎን ይጠቀሙ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"የጣት አሻራ አዶ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"በመልክ መክፈት"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ከመልክ መክፈት ጋር በተያያዘ ችግር"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ለመቀጠል መልክዎን ወይም የማያ ገጽዎን መቆለፊያ ይጠቀሙ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string> <string name="face_icon_content_description" msgid="465030547475916280">"የፊት አዶ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"የሥምሪያ ቅንብሮች አንብብ"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"መተግበሪያው የአንድ መለያ የማመሳሰል ቅንብሮችን እንዲያነብ ይፈቅድለታል። ለምሳሌ ይህ የሰዎች መተግበሪያ ከመለያ ጋር መመሳሰሉን አለመመሳሰሉን ሊወስን ይችላል።"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 0310b181398d..3746f3e14b42 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> @@ -621,6 +621,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"استخدام بصمة الإصبع أو قفل الشاشة للمتابعة"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"حدث خطأ، يُرجى إعادة المحاولة."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز بالتعرف على الوجه"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز بالتعرف على الوجه\""</string> @@ -673,6 +674,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"حدث خطأ، يُرجى إعادة المحاولة."</string> <string name="face_icon_content_description" msgid="465030547475916280">"رمز الوجه"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"قراءة إعدادات المزامنة"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"للسماح للتطبيق بقراءة الإعدادات المتزامنة لحساب ما. على سبيل المثال، يمكن أن يؤدي هذا إلى تحديد ما إذا تمت مزامنة تطبيق \"الأشخاص\" مع حساب ما."</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 65e4664589f3..0da3b0bb28b8 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -34,7 +34,7 @@ <string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string> <string name="mmiError" msgid="2862759606579822246">"সংযোগৰ সমস্যা বা MMI ক\'ড মান্য নহয়।"</string> <string name="mmiFdnError" msgid="3975490266767565852">"কেৱল ফিক্সড ডায়েলিং নম্বৰৰ বাবে কার্য সীমাবদ্ধ কৰা হৈছে।"</string> - <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"আপুনি ৰ\'মিঙত থকাৰ সময়ত কল ফৰৱাৰ্ডিঙৰ ছেটিংসমূহ সলনি কৰিব নোৱাৰি।"</string> + <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"আপুনি ৰ\'মিঙত থকাৰ সময়ত কল ফৰৱাৰ্ডিঙৰ ছেটিং সলনি কৰিব নোৱাৰি।"</string> <string name="serviceEnabled" msgid="7549025003394765639">"সেৱা সক্ষম কৰা হ’ল।"</string> <string name="serviceEnabledFor" msgid="1463104778656711613">"সেৱা সক্ষম কৰা হ’ল:"</string> <string name="serviceDisabled" msgid="641878791205871379">"সেৱা অক্ষম কৰা হ’ল।"</string> @@ -100,7 +100,7 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড HCOলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড VCO লৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড OFFলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"কণ্ঠস্বৰ"</string> <string name="serviceClassData" msgid="4148080018967300248">"ডেটা"</string> <string name="serviceClassFAX" msgid="2561653371698904118">"ফেক্স"</string> <string name="serviceClassSMS" msgid="1547664561704509004">"এছএমএছ"</string> @@ -124,7 +124,7 @@ <string name="roamingTextSearching" msgid="5323235489657753486">"সেৱাৰ বাবে অনুসন্ধান কৰি থকা হৈছে"</string> <string name="wfcRegErrorTitle" msgid="3193072971584858020">"ৱাই-ফাই কলিং ছেট আপ কৰিব পৰা নগ\'ল"</string> <string-array name="wfcOperatorErrorAlertMessages"> - <item msgid="468830943567116703">"ৱাই-ফাইৰ জৰিয়তে কল কৰিবলৈ আৰু বাৰ্তা পঠাবলৈ, প্ৰথমে আপোনাৰ বাহকক আপোনাৰ ডিভাইচটো ছেট আপ কৰিব দিবলৈ কওক। তাৰ পিচত, ছেটিংসমূহলৈ গৈ আকৌ ৱাই-ফাই কলিং অন কৰক। (ত্ৰুটি ক\'ড: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="468830943567116703">"ৱাই-ফাইৰ জৰিয়তে কল কৰিবলৈ আৰু বাৰ্তা পঠাবলৈ, প্ৰথমে আপোনাৰ বাহকক আপোনাৰ ডিভাইচটো ছেট আপ কৰিবলৈ কওক। তাৰ পাছত, ছেটিঙলৈ গৈ আকৌ ৱাই-ফাই কলিং অন কৰক। (ত্ৰুটি ক\'ড: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> <item msgid="4795145070505729156">"আপোনাৰ বাহকৰ ওচৰত ৱাই-ফাই কলিং সুবিধা পঞ্জীয়ন কৰাত সমস্যাৰ উদ্ভৱ হৈছে: <xliff:g id="CODE">%1$s</xliff:g>"</item> @@ -218,7 +218,7 @@ <string name="silent_mode" msgid="8796112363642579333">"নিঃশব্দ ম\'ড"</string> <string name="turn_on_radio" msgid="2961717788170634233">"ৱায়াৰলেছ অন কৰক"</string> <string name="turn_off_radio" msgid="7222573978109933360">"ৱায়াৰলেছ অফ কৰক"</string> - <string name="screen_lock" msgid="2072642720826409809">"স্ক্ৰীণ লক"</string> + <string name="screen_lock" msgid="2072642720826409809">"স্ক্ৰীন লক"</string> <string name="power_off" msgid="4111692782492232778">"পাৱাৰ অফ"</string> <string name="silent_mode_silent" msgid="5079789070221150912">"ৰিংগাৰ অফ আছে"</string> <string name="silent_mode_vibrate" msgid="8821830448369552678">"ৰিংগাৰ কম্পন অৱস্থাত আছে"</string> @@ -242,7 +242,7 @@ <string name="global_actions" product="tablet" msgid="4412132498517933867">"টে\'বলেটৰ বিকল্পসমূহ"</string> <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TVৰ বিকল্পসমূহ"</string> <string name="global_actions" product="default" msgid="6410072189971495460">"ফ\'নৰ বিকল্পসমূহ"</string> - <string name="global_action_lock" msgid="6949357274257655383">"স্ক্ৰীণ ল\'ক"</string> + <string name="global_action_lock" msgid="6949357274257655383">"স্ক্ৰীন লক"</string> <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> @@ -268,7 +268,7 @@ <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"এয়াৰপ্লেইন ম\'ড"</string> <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"এয়াৰপ্লেইন ম\'ড অন কৰা আছে"</string> <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"এয়াৰপ্লেইন ম\'ড অফ কৰা আছে"</string> - <string name="global_action_settings" msgid="4671878836947494217">"ছেটিংসমূহ"</string> + <string name="global_action_settings" msgid="4671878836947494217">"ছেটিং"</string> <string name="global_action_assist" msgid="2517047220311505805">"সহায়"</string> <string name="global_action_voice_assist" msgid="6655788068555086695">"কণ্ঠধ্বনিৰে সহায়"</string> <string name="global_action_lockdown" msgid="2475471405907902963">"লকডাউন"</string> @@ -329,7 +329,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> @@ -387,7 +387,7 @@ <string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"অন্য এপবোৰ বন্ধ কৰক"</string> <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"এপটোক অন্য এপসমূহৰ নেপথ্যৰ প্ৰক্ৰিয়াসমূহ শেষ কৰিবলৈ অনুমতি দিয়ে৷ এই কার্যৰ বাবে অন্য এপসমূহ চলাটো বন্ধ হ\'ব পাৰে৷"</string> <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"এই এপটো অইন এপৰ ওপৰত প্ৰদৰ্শিত হ\'ব পাৰে"</string> - <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"এই এপটো অইন এপৰ ওপৰত বা স্ক্ৰীণৰ অইন অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপসমূহৰ স্বাভাৱিক কাৰ্যকলাপত ব্যাঘাত জন্মাব পাৰে আৰু অইন এপসমূহক স্ক্ৰীণত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string> + <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"এই এপ্টো অন্য এপৰ ওপৰত বা স্ক্ৰীনৰ অন্য অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপৰ স্বাভাৱিক ব্যৱহাৰত ব্যাঘাত জন্মাব পাৰে আৰু অন্য এপ্সমূহক স্ক্ৰীনত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string> <string name="permlab_runInBackground" msgid="541863968571682785">"নেপথ্যত চলিব পাৰে"</string> <string name="permdesc_runInBackground" msgid="4344539472115495141">"এই এপটো নেপথ্যত চলিব পাৰে। ইয়াৰ ফলত বেটাৰি সোনকালে শেষ হ\'ব পাৰে।"</string> <string name="permlab_useDataInBackground" msgid="783415807623038947">"নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে"</string> @@ -400,8 +400,8 @@ <string name="permdesc_foregroundService" msgid="8720071450020922795">"এপটোক অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে।"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"এপৰ সঞ্চয়াগাৰৰ খালী ঠাই হিচাপ কৰক"</string> <string name="permdesc_getPackageSize" msgid="742743530909966782">"এপটোক ইয়াৰ ক\'ড, ডেটা আৰু কেশ্বৰ আকাৰ বিচাৰি উলিয়াবলৈ অনুমতি দিয়ে"</string> - <string name="permlab_writeSettings" msgid="8057285063719277394">"ছিষ্টেম ছেটিংসমূহ সংশোধন কৰক"</string> - <string name="permdesc_writeSettings" msgid="8293047411196067188">"এপটোক ছিষ্টেমৰ ছেটিংসমূহৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ ক্ষতিকাৰক এপসমূহে আপোনাৰ ছিষ্টেম কনফিগাৰেশ্বনক ক্ষতিগ্ৰস্ত কৰিব পাৰে৷"</string> + <string name="permlab_writeSettings" msgid="8057285063719277394">"ছিষ্টেম ছেটিংহ সংশোধন কৰক"</string> + <string name="permdesc_writeSettings" msgid="8293047411196067188">"এপ্টোক ছিষ্টেমৰ ছেটিঙৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ ক্ষতিকাৰক এপ্সমূহে আপোনাৰ ছিষ্টেম কনফিগাৰেশ্বনক ক্ষতিগ্ৰস্ত কৰিব পাৰে৷"</string> <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"আৰম্ভ হোৱাৰ সময়ত চলাওক"</string> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"ছিষ্টেমে বুট কৰা কাৰ্য সমাপ্ত কৰাৰ লগে লগে এপটোক নিজে নিজে আৰম্ভ হ\'বলৈ অনুমতি দিয়ে। ইয়াৰ ফলত ফ\'নটো ষ্টাৰ্ট হওতে বেছি সময়ৰ প্ৰয়োজন হ\'ব পাৰে, আৰু এপটো সদায় চলি থকাৰ কাৰণে ফ\'নটো সামগ্ৰিকভাৱে লেহেমীয়া হ\'ব পাৰে।"</string> <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"ছিষ্টেমে বুটিং সমাপ্ত কৰাৰ লগে লগে এই এপ্টোক নিজে নিজে আৰম্ভ হ’বলৈ অনুমতি দিয়ে। এই কাৰ্যৰ বাবে আপোনাৰ Android TV ডিভাইচটো আৰম্ভ হ’বলৈ দীঘলীয়া সময়ৰ প্ৰয়োজন হ’ব পাৰে আৰু সকলো সময়তে চলি থাকি এপ্টোক সামগ্ৰিকভাৱে ডিভাইচটো লেহেমীয়া কৰিবলৈ দিয়ে।"</string> @@ -442,8 +442,8 @@ <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"এই এপ্টো ব্যৱহাৰ হৈ থকা অৱস্থাত ই অৱস্থান সেৱাসমূহৰ পৰা আপোনাৰ আনুমানিক অৱস্থান লাভ কৰিব পাৰে। এপ্টোৱে অৱস্থান লাভ কৰিবলৈ হ’লে আপোনাৰ ডিভাইচৰ অৱস্থান সেৱাসমূহ অন কৰি ৰাখিবই লাগিব।"</string> <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"নেপথ্যত চলি থকা সময়ত অৱস্থানৰ এক্সেছ"</string> <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"এই এপ্টোৱে যিকোনো সময়তে অৱস্থান এক্সেছ কৰিব পাৰে, আনকি এপ্টো ব্যৱহাৰ হৈ নথকা অৱস্থাতো।"</string> - <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"আপোনাৰ অডিঅ\' ছেটিংসমূহ সলনি কৰক"</string> - <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"এপটোক ভলিউমৰ দৰে গ্ল\'বেল অডিঅ\' ছেটিংসমূহ যাৰ স্পীকাৰক আউটপুটৰ বাবে ব্যৱহাৰ হয় তাক সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string> + <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"আপোনাৰ অডিঅ\' ছেটিং সলনি কৰক"</string> + <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"এপ্টোক ভলিউমৰ দৰে গ্ল\'বেল অডিঅ\' ছেটিং আৰু আউটপুটৰ বাবে কোনটো স্পীকাৰ ব্যৱহাৰ হয় তাক সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string> <string name="permlab_recordAudio" msgid="1208457423054219147">"অডিঅ\' ৰেকর্ড কৰক"</string> <string name="permdesc_recordAudio" msgid="5857246765327514062">"এই এপ্টোৱে ইয়াক ব্যৱহাৰ কৰি থাকোঁতে মাইক্ৰ’ফ’ন ব্যৱহাৰ কৰি অডিঅ’ ৰেকর্ড কৰিব পাৰে।"</string> <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"নেপথ্যত অডিঅ’ ৰেকৰ্ড কৰক"</string> @@ -519,7 +519,7 @@ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"আপোনাৰ টেবলেটৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string> <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"কেৱল আপোনাৰ Android TV ডিভাইচটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনাবোৰ ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেটবোৰ লাভ কৰিবলৈ এপ্টোক অনুমতি দিয়ে। এই কার্যই ন’ন-মাল্টিকাষ্ট ম’ডতকৈ অধিক পাৱাৰ ব্যৱহাৰ কৰে।"</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"আপোনাৰ ফ\'নৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string> - <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"ব্লুটুথ ছেটিংসমূহ ব্যৱহাৰ কৰক"</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> <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"স্থানীয় ব্লুটুথ ফ\'ন কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string> @@ -545,10 +545,10 @@ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"এপ্টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"</string> <string name="permlab_nfc" msgid="1904455246837674977">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string> <string name="permdesc_nfc" msgid="8352737680695296741">"এপটোক নিয়েৰ ফিল্ড কমিউনিকেশ্বন (NFC) টেগ, কাৰ্ড আৰু ৰিডাৰসমূহৰ সৈতে যোগাযোগ কৰিবলৈ অনুমতি দিয়ে।"</string> - <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীণ ল\'ক অক্ষম কৰক"</string> + <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীন লক অক্ষম কৰক"</string> <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"এপটোক কী ল\'ক আৰু জড়িত হোৱা যিকোনো পাছৱৰ্ডৰ সুৰক্ষা অক্ষম কৰিব দিয়ে৷ উদাহৰণস্বৰূপে, কোনো অন্তৰ্গামী ফ\'ন কল উঠোৱাৰ সময়ত ফ\'নটোৱে কী-লকটো অক্ষম কৰে, তাৰ পিছত কল শেষ হ\'লেই কী লকটো পুনৰ সক্ষম কৰে৷"</string> - <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"স্ক্ৰীণ লকৰ জটিলতাৰ অনুৰোধ"</string> - <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"এপটোক স্ক্ৰীণ লকৰ জটিলতাৰ স্তৰ (উচ্চ, মধ্যম, নিম্ন বা একেবাৰে নাই) শিকিবলৈ অনুমতি দিয়ে ই স্ক্ৰীণ লকৰ সম্ভাব্য দৈৰ্ঘ্য বা স্ক্ৰীণ লকৰ প্ৰকাৰ দৰ্শায়। লগতে এপটোৱে ব্যৱহাৰকাৰীক স্ক্ৰীণ লকটো এটা নিৰ্দিষ্ট স্তৰলৈ আপডে’ট কৰিবলৈ পৰামৰ্শ দিব পাৰে যিটো ব্যৱহাৰকাৰীয়ে অৱজ্ঞা কৰি পৰৱর্তী পৃষ্ঠালৈ যাব পাৰে। মনত ৰাখিব যে স্ক্ৰীণ লকটো সাধাৰণ পাঠ হিচাপে সঞ্চয় কৰা নহয় সেয়ে এপ্টোৱে সঠিক পাছৱৰ্ডটো জানিব নোৱাৰে।"</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> <string name="permlab_manageFingerprint" msgid="7432667156322821178">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ পৰিচালনা কৰিব পাৰে"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেচ আনলক"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ফেচ আনলক ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string> @@ -639,7 +640,7 @@ <string name="face_acquired_tilt_too_extreme" msgid="8618210742620248049">"আপোনাৰ মূৰটো অলপ কমকৈ হেলনীয়া কৰক।"</string> <string name="face_acquired_roll_too_extreme" msgid="1442830503572636825">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"আপোনাৰ মুখখন ঢাকি ৰখা বস্তুবোৰ আঁতৰাওক।"</string> - <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ক’লা বাৰডালকে ধৰি আপোনাৰ স্ক্রীণৰ ওপৰৰ অংশ চাফা কৰক"</string> + <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"ক’লা বাৰডালকে ধৰি আপোনাৰ স্ক্রীনৰ ওপৰৰ অংশ চাফা কৰক"</string> <string-array name="face_acquired_vendor"> </string-array> <string name="face_error_hw_not_available" msgid="5085202213036026288">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। হাৰ্ডৱেৰ নাই।"</string> @@ -661,9 +662,10 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"অব্যাহত ৰাখিবলৈ আপোনাৰ মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string> <string name="face_icon_content_description" msgid="465030547475916280">"মুখমণ্ডলৰ আইকন"</string> - <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ছিংকৰ ছেটিংসমূহ পঢ়ক"</string> - <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"একাউণ্টৰ ছিংক ছেটিংবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। যেনে, People এপ কোনো একাউণ্টত ছিংক কৰা হৈছে নে নাই সেয়া নির্ধাৰণ কৰিব পাৰে।"</string> + <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ছিংকৰ ছেটিং পঢ়ক"</string> + <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"একাউণ্টৰ ছিংক ছেটিংবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। যেনে, People এপ্টো কোনো একাউণ্টৰ সৈতে ছিংক কৰা হৈছে নে নাই সেয়া নির্ধাৰণ কৰিব পাৰে।"</string> <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"ছিংকক অন আৰু অফ ট\'গল কৰক"</string> <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"এপটোক কোনো একাউণ্টৰ ছিংক সম্পৰ্কীয় ছেটিংসমূহ সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ উদাহৰণস্বৰূপে, এই কাৰ্যক কোনো একাউণ্টৰ জৰিয়তে People এপটোৰ ছিংক সক্ষম কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি৷"</string> <string name="permlab_readSyncStats" msgid="3747407238320105332">"ছিংকৰ পৰিসংখ্যা পঢ়ক"</string> @@ -680,8 +682,8 @@ <string name="permdesc_register_call_provider" msgid="4201429251459068613">"এপটোক নতুন টেলিকম সংযোগ পঞ্জীয়ন কৰিবলৈ অনুমতি দিয়ে।"</string> <string name="permlab_connection_manager" msgid="3179365584691166915">"টেলিকম সংযোগ পৰিচালনা কৰা"</string> <string name="permdesc_connection_manager" msgid="1426093604238937733">"এপটোক টেলিকম সংযোগ পৰিচালনা কৰিবলৈ অনুমতি দিয়ে।"</string> - <string name="permlab_bind_incall_service" msgid="5990625112603493016">"ইন-কল স্ক্ৰীণৰ সৈতে সংযোগ স্থাপন"</string> - <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"ব্যৱহাৰকাৰীয়ে কেতিয়া আৰু কেনেদৰে ইন-কল-স্ক্ৰীণ চাব, তাক নিয়ন্ত্ৰণ কৰিবলৈ এপক অনুমতি দিয়ে।"</string> + <string name="permlab_bind_incall_service" msgid="5990625112603493016">"ইন-কল স্ক্ৰীনৰ সৈতে সংযোগ স্থাপন"</string> + <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"ব্যৱহাৰকাৰীগৰাকীয়ে কেতিয়া আৰু কেনেদৰে ইন-কল-স্ক্ৰীন চায় সেয়া নিয়ন্ত্ৰণ কৰিবলৈ এপ্টোক অনুমতি দিয়ে।"</string> <string name="permlab_bind_connection_service" msgid="5409268245525024736">"টেলিফ\'নী সেৱাসমূহৰ সৈতে সংযোগ স্থাপন"</string> <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"কল কৰিবলৈ/লাভ কৰিবলৈ টেলিফ\'নী সেৱাসমূহৰ সৈতে এপক সংযোগ স্থাপনৰ বাবে অনুমতি দিয়ে।"</string> <string name="permlab_control_incall_experience" msgid="6436863486094352987">"ইন-কল ব্যৱহাৰকাৰীৰ অভিজ্ঞতা প্ৰদান কৰা"</string> @@ -705,7 +707,7 @@ <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"নেটৱৰ্ক অৱস্থাসমূহৰ ওপৰত নিৰীক্ষণৰ বাবে শুনিব পাৰে"</string> <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"এটা এপ্লিকেশ্বনক নেটৱৰ্ক অৱস্থাসমূহত নিৰীক্ষণৰ বাবে শুনিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string> <string name="permlab_setInputCalibration" msgid="932069700285223434">"ইনপুট ডিভাইচ কেলিব্ৰেশ্বন সলনি কৰিব পাৰে"</string> - <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"টাচ্চ স্ক্ৰীণৰ কেলিব্ৰেশ্বন পেৰামিটাৰ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string> + <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"টাচ্চ স্ক্ৰীনৰ কেলিব্ৰেশ্বন পেৰামিটাৰ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে কেতিয়াও প্ৰয়োজন হোৱা উচিত নহয়।"</string> <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM প্ৰমাণপত্ৰসমূহলৈ প্ৰৱেশ"</string> <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"এটা এপ্লিকেশ্বনক DRM প্ৰমাণপত্ৰ গোটাবলৈ আৰু ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string> <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android বীম স্থানান্তৰণৰ স্থিতি লাভ কৰিব পাৰে"</string> @@ -723,18 +725,18 @@ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"এটা উচ্চ ছেম্পলিঙৰ হাৰত ছেন্সৰৰ ডেটা এক্সেছ কৰে"</string> <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"এপ্টোক ২০০ হাৰ্টজতকৈ অধিক হাৰত ছেন্সৰৰ ডেটাৰ নমুনা ল’বলৈ অনুমতি দিয়ে"</string> <string name="policylab_limitPassword" msgid="4851829918814422199">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string> - <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string> - <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string> - <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে টে\'বলেটটো লক কৰক বা টে\'বলেটটোৰ সকলো ডেটা মোহাৰক।"</string> - <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"স্ক্ৰীণ আনলক কৰোঁতে দিয়া ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড দিয়া হয় তেন্তে Android TV ডিভাইচটো লক কৰক অথবা আপোনাৰ Android TV ডিভাইচৰ সকলো ডেটা মচক।"</string> - <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে ফ\'নটো লক কৰক বা ফ\'নটোৰ সকলো ডেটা মোহাৰক।"</string> - <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে টে\'বলেটটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string> - <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্ৰীণখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয় তেন্তে Android TV ডিভাইচটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string> - <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্ৰীণ আনলক কৰোতে দিয়া অশুদ্ধ পাছৱৰ্ডৰ হিচাপ নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে ফ\'নটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string> - <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্ৰীণ লক সলনি কৰক"</string> - <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীণ লক সলনি কৰক।"</string> - <string name="policylab_forceLock" msgid="7360335502968476434">"স্ক্ৰীণখন লক কৰক"</string> - <string name="policydesc_forceLock" msgid="1008844760853899693">"স্ক্ৰীণ কেনেকৈ আৰু কেতিয়া ল\'ক হ\'ব লাগে সেয়া নিয়ন্ত্ৰণ কৰক।"</string> + <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীন লক পাছৱৰ্ড আৰু পিনত অনুমোদিত দৈৰ্ঘ্য আৰু বৰ্ণবোৰ নিয়ন্ত্ৰণ কৰক।।"</string> + <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীন আনলক কৰা প্ৰয়াসবোৰ নিৰীক্ষণ কৰক"</string> + <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে টেবলেটটো লক কৰক বা টেবলেটটোৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে Android TV ডিভাইচটো লক কৰক অথবা আপোনাৰ Android TV ডিভাইচৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে ফ\'নটো লক কৰক বা ফ\'নটোৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে টেবলেটটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে Android TV ডিভাইচটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে ফ\'নটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্ৰীন লক সলনি কৰক"</string> + <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীন লক সলনি কৰক।"</string> + <string name="policylab_forceLock" msgid="7360335502968476434">"স্ক্ৰীনখন লক কৰক"</string> + <string name="policydesc_forceLock" msgid="1008844760853899693">"স্ক্ৰীন কেনেকৈ আৰু কেতিয়া লক হয় সেয়া নিয়ন্ত্ৰণ কৰক।"</string> <string name="policylab_wipeData" msgid="1359485247727537311">"সকলো ডেটা মচক"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টেবলেটৰ ডেটা মচক।"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"কোনো সতর্কবার্তা নপঠিওৱাকৈ ফেক্টৰী ডেটা ৰিছেট কৰি আপোনাৰ Android TV ডিভাইচৰ ডেটা মচক।"</string> @@ -745,14 +747,14 @@ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"এই ফ\'নটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্য়ৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string> - <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীণ লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string> - <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীণ লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string> + <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীন লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string> + <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীন লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string> <string name="policylab_encryptedStorage" msgid="9012936958126670110">"সঞ্চয়াগাৰৰ এনক্ৰিপশ্বন ছেট কৰক"</string> <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"সঞ্চয় কৰি ৰখা ডেটাক এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন।"</string> <string name="policylab_disableCamera" msgid="5749486347810162018">"কেমেৰাবোৰ অক্ষম কৰক"</string> <string name="policydesc_disableCamera" msgid="3204405908799676104">"সকলো ডিভাইচৰ কেমেৰাবোৰ ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string> - <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string> - <string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা ব্যৱহাৰ হোৱাত বাধা দিয়ক।"</string> + <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"স্ক্ৰীন লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string> + <string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"স্ক্ৰীন লকৰ কিছুমান সুবিধা ব্যৱহাৰ হোৱাত বাধা দিয়ক।"</string> <string-array name="phoneTypes"> <item msgid="8996339953292723951">"ঘৰ"</item> <item msgid="7740243458912727194">"ম’বাইল"</item> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"কৰ্মস্থানৰ ম’বাইল নম্বৰ"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"কৰ্মস্থানৰ পেজাৰৰ নম্বৰ"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"সহায়ক"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"এমএমএছ"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"নিজৰ উপযোগিতা অনুযায়ী"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"জন্মদিন"</string> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"অন্যান্য"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"নিজৰ উপযোগিতা অনুযায়ী"</string> <string name="relationTypeCustom" msgid="282938315217441351">"নিজৰ উপযোগিতা অনুযায়ী"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"সহায়ক"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"ভাতৃ"</string> <string name="relationTypeChild" msgid="9076258911292693601">"শিশু"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"সংগী"</string> @@ -878,7 +880,7 @@ <string name="keyguard_label_text" msgid="3841953694564168384">"আনলক কৰিবলৈ মেনু টিপাৰ পিছত ০ টিপক।"</string> <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"জৰুৰীকালীন নম্বৰ"</string> <string name="lockscreen_carrier_default" msgid="6192313772955399160">"কোনো সেৱা নাই"</string> - <string name="lockscreen_screen_locked" msgid="7364905540516041817">"স্ক্ৰীণ লক কৰা হ’ল।"</string> + <string name="lockscreen_screen_locked" msgid="7364905540516041817">"স্ক্ৰীন লক কৰা হ’ল।"</string> <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"আনলক কৰিবলৈ বা জৰুৰীকালীন কল কৰিবলৈ মেনু টিপক।"</string> <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"আনলক কৰিবলৈ মেনু টিপক।"</string> <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"আনলক কৰিবলৈ আর্হি আঁকক"</string> @@ -1038,9 +1040,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"স্পেচ"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"লিখক"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"মচক"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> - <string name="search_hint" msgid="455364685740251925">"অনুসন্ধান কৰক…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> + <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_clear" msgid="1989371719192982900">"প্ৰশ্ন মচক"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"প্ৰশ্ন দাখিল কৰক"</string> @@ -1210,7 +1212,7 @@ <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"প্ৰতিচ্ছবি তোলক"</string> <string name="alwaysUse" msgid="3153558199076112903">"এই কার্যৰ বাবে পূর্বনির্ধাৰিত ধৰণে ব্যৱহাৰ কৰক।"</string> <string name="use_a_different_app" msgid="4987790276170972776">"এটা পৃথক এপ্ ব্যৱহাৰ কৰক"</string> - <string name="clearDefaultHintMsg" msgid="1325866337702524936">"ছিষ্টেমৰ ছেটিংসমূহ > এপসমূহ > ডাউনল’ড কৰা সমল-লৈ গৈ ডিফ\'ল্ট মচক৷"</string> + <string name="clearDefaultHintMsg" msgid="1325866337702524936">"ছিষ্টেমৰ ছেটিং > এপ্ > ডাউনল’ড কৰা সমল-লৈ গৈ ডিফ\'ল্ট মচক৷"</string> <string name="chooseActivity" msgid="8563390197659779956">"কোনো কার্য বাছনি কৰক"</string> <string name="chooseUsbActivity" msgid="2096269989990986612">"ইউএছবি ডিভাইচৰ বাবে এটা এপ্ বাছনি কৰক"</string> <string name="noApplications" msgid="1186909265235544019">"কোনো এপে এই কাৰ্য কৰিব নোৱাৰে।"</string> @@ -1238,7 +1240,7 @@ <string name="launch_warning_original" msgid="3332206576800169626">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক পূৰ্বতে লঞ্চ কৰা হৈছিল৷"</string> <string name="screen_compat_mode_scale" msgid="8627359598437527726">"স্কেল"</string> <string name="screen_compat_mode_show" msgid="5080361367584709857">"সদায় দেখুৱাওক"</string> - <string name="screen_compat_mode_hint" msgid="4032272159093750908">"ছিষ্টেমৰ ছেটিংসমূহ > এপসমূহ > ডাউনল’ড কৰা সমল-লৈ গৈ ইয়াক আকৌ সক্ষম কৰক।"</string> + <string name="screen_compat_mode_hint" msgid="4032272159093750908">"ছিষ্টেমৰ ছেটিং > এপ্ > ডাউনল’ড কৰা সমল-লৈ গৈ ইয়াক আকৌ সক্ষম কৰক।"</string> <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বর্তমানৰ ডিছপ্লে’ৰ আকাৰ ছেটিং ব্যৱহাৰ কৰিব নোৱাৰে আৰু ই সঠিকভাৱে নচলিবও পাৰে।"</string> <string name="unsupported_display_size_show" msgid="980129850974919375">"সদায় দেখুৱাওক"</string> <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক এটা খাপ নোখোৱা Android OS সংস্কৰণৰ বাবে তৈয়াৰ কৰা হৈছিল, যাৰ ফলত ই অস্বাভাৱিকধৰণে আচৰণ কৰিব পাৰে। এপটোৰ শেহতীয়া সংস্কৰণ উপলব্ধ হ\'ব পাৰে।"</string> @@ -1335,7 +1337,7 @@ <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"পঠিয়াওক"</string> <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"বাতিল কৰক"</string> <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"মোৰ পচন্দ মনত ৰাখিব"</string> - <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"আপুনি ইয়াক পিছত ছেটিং > এপ্-ত সলনি কৰিব পাৰে"</string> + <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"আপুনি ইয়াক পিছত ছেটিং > এপত সলনি কৰিব পাৰে"</string> <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"যিকোনো সময়ত অনুমতি দিয়ক"</string> <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"কেতিয়াও অনুমতি নিদিব"</string> <string name="sim_removed_title" msgid="5387212933992546283">"ছিম কাৰ্ড আঁতৰোৱা হ’ল"</string> @@ -1391,7 +1393,7 @@ <string name="share_remote_bugreport_action" msgid="7630880678785123682">"শ্বেয়াৰ কৰক"</string> <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"প্ৰত্যাখ্যান কৰক"</string> <string name="select_input_method" msgid="3971267998568587025">"ইনপুট পদ্ধতি বাছনি কৰক"</string> - <string name="show_ime" msgid="6406112007347443383">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীণত ৰাখিব"</string> + <string name="show_ime" msgid="6406112007347443383">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীনত ৰাখক"</string> <string name="hardware" msgid="1800597768237606953">"ভাৰ্শ্বুৱল কীব\'ৰ্ড দেখুৱাওক"</string> <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"কায়িক কীব’ৰ্ড কনফিগাৰ কৰক"</string> <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ভাষা আৰু চানেকি বাছনি কৰিবলৈ ইয়াত টিপক"</string> @@ -1400,7 +1402,7 @@ <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"অন্য এপৰ ওপৰত দেখুৱায়"</string> <string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> অন্য এপসমূহৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string> <string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g>এ অইন এপবোৰৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string> - <string name="alert_windows_notification_message" msgid="6538171456970725333">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g>এ এই সুবিধাটো ব্যৱহাৰ কৰাটো নিবিচাৰে তেন্তে টিপি ছেটিংসমূহ খোলক আৰু ইয়াক অফ কৰক।"</string> + <string name="alert_windows_notification_message" msgid="6538171456970725333">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g>এ এই সুবিধাটো ব্যৱহাৰ কৰাটো নিবিচাৰে তেন্তে ছেটিং খুলিবলৈ টিপক আৰু ইয়াক অফ কৰক।"</string> <string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"অফ কৰক"</string> <string name="ext_media_checking_notification_title" msgid="8299199995416510094">"<xliff:g id="NAME">%s</xliff:g> পৰীক্ষা কৰি থকা হৈছে…"</string> <string name="ext_media_checking_notification_message" msgid="2231566971425375542">"বৰ্তমানৰ সমলৰ সমীক্ষা কৰি থকা হৈছে"</string> @@ -1467,7 +1469,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"জুম নিয়ন্ত্ৰণ কৰিবলৈ দুবাৰ টিপক"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ৱিজেট যোগ কৰিব পৰা নগ\'ল।"</string> <string name="ime_action_go" msgid="5536744546326495436">"যাওক"</string> - <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> + <string name="ime_action_search" msgid="4501435960587287668">"সন্ধান কৰক"</string> <string name="ime_action_send" msgid="8456843745664334138">"পঠিয়াওক"</string> <string name="ime_action_next" msgid="4169702997635728543">"পৰৱৰ্তী"</string> <string name="ime_action_done" msgid="6299921014822891569">"সম্পন্ন হ’ল"</string> @@ -1502,7 +1504,7 @@ <string name="vpn_lockdown_connected" msgid="2853127976590658469">"সদা-সক্ৰিয় ভিপিএন সংযোগ কৰা হ’ল"</string> <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"সদা-সক্ৰিয় ভিপিএনৰ লগত সংযোগ বিচ্ছিন্ন কৰা হৈছে"</string> <string name="vpn_lockdown_error" msgid="4453048646854247947">"সদা-সক্ৰিয় ভিপিএনৰ লগত সংযোগ কৰিব পৰা নাই"</string> - <string name="vpn_lockdown_config" msgid="8331697329868252169">"নেটৱৰ্ক বা ভিপিএন ছেটিংসমূহ সলনি কৰক"</string> + <string name="vpn_lockdown_config" msgid="8331697329868252169">"নেটৱৰ্ক বা VPN ছেটিং সলনি কৰক"</string> <string name="upload_file" msgid="8651942222301634271">"ফাইল বাছনি কৰক"</string> <string name="no_file_chosen" msgid="4146295695162318057">"কোনো ফাইল বাছনি কৰা হোৱা নাই"</string> <string name="reset" msgid="3865826612628171429">"ৰিছেট কৰক"</string> @@ -1629,7 +1631,7 @@ <string name="wireless_display_route_description" msgid="8297563323032966831">"ৱায়াৰলেচ ডিছপ্লে’"</string> <string name="media_route_button_content_description" msgid="2299223698196869956">"কাষ্ট"</string> <string name="media_route_chooser_title" msgid="6646594924991269208">"ডিভাইচৰ লগত সংযোগ কৰক"</string> - <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"ডিভাইচত স্ক্ৰীণ কাষ্ট কৰক"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"ডিভাইচত স্ক্ৰীন কাষ্ট কৰক"</string> <string name="media_route_chooser_searching" msgid="6119673534251329535">"ডিভাইচৰ সন্ধান কৰক…"</string> <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"ছেটিংসমূহ"</string> <string name="media_route_controller_disconnect" msgid="7362617572732576959">"বিচ্ছিন্ন কৰক"</string> @@ -1638,8 +1640,8 @@ <string name="media_route_status_available" msgid="1477537663492007608">"উপলব্ধ"</string> <string name="media_route_status_not_available" msgid="480912417977515261">"উপলব্ধ নহয়"</string> <string name="media_route_status_in_use" msgid="6684112905244944724">"ব্যৱহাৰ হৈ আছে"</string> - <string name="display_manager_built_in_display_name" msgid="1015775198829722440">"অন্তৰ্নিমিত স্ক্ৰীণ"</string> - <string name="display_manager_hdmi_display_name" msgid="1022758026251534975">"HDMI স্ক্ৰীণ"</string> + <string name="display_manager_built_in_display_name" msgid="1015775198829722440">"বিল্ট-ইন স্ক্ৰীন"</string> + <string name="display_manager_hdmi_display_name" msgid="1022758026251534975">"HDMI স্ক্ৰীন"</string> <string name="display_manager_overlay_display_name" msgid="5306088205181005861">"অ\'ভাৰলে\' #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="1480158037150469170">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="2810034719482834679">", সুৰক্ষিত"</string> @@ -1690,10 +1692,10 @@ <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শ্বৰ্টকাটটো অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটাম ৩ ছেকেণ্ডৰ বাবে হেঁচি ধৰি ৰাখিলে এটা সাধ্য সুবিধা আৰম্ভ হ’ব।"</string> <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"সাধ্য সুবিধাসমূহৰ বাবে শ্বৰ্টকাট অন কৰিবনে?"</string> - <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিংসমূহ > সাধ্য-সুবিধাত কিছুমান নিৰ্দিষ্ট সুবিধা সলনি কৰিব পাৰে।"</string> + <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিং > সাধ্য-সুবিধাত কিছুমান নিৰ্দিষ্ট সুবিধা সলনি কৰিব পাৰে।"</string> <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string> <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g>ৰ শ্বৰ্টকাট অন কৰিবনে?"</string> - <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে এটা সাধ্য- সুবিধা <xliff:g id="SERVICE">%1$s</xliff:g> অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nআপুনি ছেটিংসমূহ > সাধ্য-সুবিধাসমূহত এই শ্বৰ্টকাটটো অন্য এটা সুবিধালৈ সলনি কৰিব পাৰে।"</string> + <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে এটা সাধ্য- সুবিধা <xliff:g id="SERVICE">%1$s</xliff:g> অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nআপুনি ছেটিং > সাধ্য-সুবিধাসমূহত এই শ্বৰ্টকাটটো অন্য এটা সুবিধালৈ সলনি কৰিব পাৰে।"</string> <string name="accessibility_shortcut_on" msgid="5463618449556111344">"অন কৰক"</string> <string name="accessibility_shortcut_off" msgid="3651336255403648739">"অন নকৰিব"</string> <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"অন কৰা আছে"</string> @@ -1701,8 +1703,8 @@ <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_description" msgid="6946315917771791525">"ই স্ক্ৰীণৰ সকলো সমল পঢ়িব পাৰে আৰু অন্য এপ্সমূহৰ ওপৰত সমল প্ৰদর্শন কৰিব পাৰে।"</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_description" msgid="2718852014003170558">"ই আপুনি কোনো এপ্ বা হার্ডৱেৰ ছেন্সৰৰ সৈতে কৰা ভাব-বিনিময় আৰু আপোনাৰ হৈ অন্য কোনো লোকে এপৰ সৈতে কৰা ভাব-বিনিময় ট্ৰেক কৰিব পাৰে।"</string> <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"অনুমতি দিয়ক"</string> @@ -1852,7 +1854,7 @@ <item quantity="other"> <xliff:g id="COUNT">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক</item> </plurals> <string name="restr_pin_try_later" msgid="5897719962541636727">"পিছত আকৌ চেষ্টা কৰক"</string> - <string name="immersive_cling_title" msgid="2307034298721541791">"স্ক্ৰীণ পূৰ্ণৰূপত চাই আছে"</string> + <string name="immersive_cling_title" msgid="2307034298721541791">"স্ক্ৰীন পূৰ্ণৰূপত চাই আছে"</string> <string name="immersive_cling_description" msgid="7092737175345204832">"বাহিৰ হ\'বলৈ ওপৰৰপৰা তললৈ ছোৱাইপ কৰক।"</string> <string name="immersive_cling_positive" msgid="7047498036346489883">"বুজি পালোঁ"</string> <string name="done_label" msgid="7283767013231718521">"সম্পন্ন কৰা হ’ল"</string> @@ -1972,7 +1974,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"প্ৰস্তাৱিত"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"সকলো ভাষা"</string> <string name="region_picker_section_all" msgid="756441309928774155">"সকলো অঞ্চল"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"সন্ধান কৰক"</string> <string name="app_suspended_title" msgid="888873445010322650">"এপটো নাই"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"এই মুহূৰ্তত <xliff:g id="APP_NAME_0">%1$s</xliff:g> উপলব্ধ নহয়। ইয়াক <xliff:g id="APP_NAME_1">%2$s</xliff:g>এ পৰিচালনা কৰে।"</string> <string name="app_suspended_more_details" msgid="211260942831587014">"অধিক জানক"</string> @@ -2085,10 +2087,10 @@ <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"অসুবিধা নিদিব সলনি হৈছে"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"কি কি অৱৰোধ কৰা হৈছে জানিবলৈ টিপক।"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ছিষ্টেম"</string> - <string name="notification_app_name_settings" msgid="9088548800899952531">"ছেটিংসমূহ"</string> + <string name="notification_app_name_settings" msgid="9088548800899952531">"ছেটিং"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"কেমেৰা"</string> <string name="notification_appops_microphone_active" msgid="581333393214739332">"মাইক্ৰ\'ফ\'ন"</string> - <string name="notification_appops_overlay_active" msgid="5571732753262836481">"স্ক্ৰীণত অইন এপৰ ওপৰত দেখুৱাওক"</string> + <string name="notification_appops_overlay_active" msgid="5571732753262836481">"আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string> <string name="notification_feedback_indicator" msgid="663476517711323016">"মতামত দিয়ক"</string> <string name="notification_feedback_indicator_alerted" msgid="6552871804121942099">"এই জাননীটোৰ গুৰুত্ব ডিফ’ল্টলৈ বৃদ্ধি কৰা হৈছে। মতামত দিবলৈ টিপক।"</string> <string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"এই জাননীটোৰ গুৰুত্ব নীৰৱলৈ হ্ৰাস কৰা হৈছে। মতামত দিবলৈ টিপক।"</string> @@ -2139,7 +2141,7 @@ <string name="accessibility_system_action_back_label" msgid="4205361367345537608">"উভতি যাওক"</string> <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"শেহতীয়া এপ্সমূহ"</string> <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"জাননীসমূহ"</string> - <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"ক্ষিপ্ৰ ছেটিংসমূহ"</string> + <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"ক্ষিপ্ৰ ছেটিং"</string> <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"পাৱাৰ ডায়লগ"</string> <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"লক স্ক্ৰীন"</string> <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"স্ক্ৰীণশ্বট"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index bab05ad489b3..7d415342d1b8 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davam etmək üçün barmaq izi və ya ekran kilidinizdən istifadə edin"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Xəta oldu. Yenə cəhd edin."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmaq izi ikonası"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Üz ilə kiliddən çıxarma"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Üz ilə kiliddən çıxarma problemi"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davam etmək üçün üz və ya ekran kilidinizdən istifadə edin"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Xəta oldu. Yenə cəhd edin."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Üz işarəsi"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx ayarlarını oxu"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tətbiqə hesablar üçün sinxronizasiya nizamlarını oxuma icazəsi verir. Məsələn, bu Şəxslər tətbiqinin sinxronizə olunub-olunmadığını təyin edə bilər."</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 4179ab03dac3..7f7d62e8ce7d 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da biste nastavili"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Došlo je do problema. Probajte ponovo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem sa otključavanje licem"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da biste nastavili"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Došlo je do problema. Probajte ponovo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje podešavanja sinhronizacije"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Dozvoljava aplikaciji da čita podešavanja sinhronizacije za nalog. Na primer, ovako može da se utvrdi da li je aplikacija Ljudi sinhronizovana sa nalogom."</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 2d94ffe2b0eb..49938844104a 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Каб працягнуць, скарыстайце адбітак пальца ці сродак разблакіроўкі экрана"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нешта пайшло не так. Паўтарыце спробу."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок адбіткаў пальцаў"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Распазнаванне твару"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Праблема з распазнаваннем твару"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Каб працягнуць, скарыстайце распазнаванне твару ці сродак разблакіроўкі экрана"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нешта пайшло не так. Паўтарыце спробу."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Значок твару"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"чытаць параметры сінхранізацыі"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дазваляе прыкладанням чытаць параметры сінхранізацыі для ўліковага запісу. Напрыклад, яны могуць вызначыць, цi сiнхранiзавана з улiковым запiсам прыкладанне \"Кантакты\"."</string> @@ -972,7 +974,7 @@ <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Вобласць узора."</string> <string name="keyguard_accessibility_slide_area" msgid="4331399051142520176">"Вобласць слайда."</string> <string name="password_keyboard_label_symbol_key" msgid="2716255580853511949">"123"</string> - <string name="password_keyboard_label_alpha_key" msgid="5294837425652726684">"ABC"</string> + <string name="password_keyboard_label_alpha_key" msgid="5294837425652726684">"АБВ"</string> <string name="password_keyboard_label_alt_key" msgid="8528261816395508841">"Alt"</string> <string name="granularity_label_character" msgid="8903387663153706317">"Знак"</string> <string name="granularity_label_word" msgid="3686589158760620518">"слова"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 40807e5650fa..0baf2f1f0969 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Използвайте отпечатъка си или опцията за заключване на екрана, за да продължите"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нещо се обърка. Опитайте отново."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатък"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отключване с лице"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем с отключването с лице"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Използвайте лицето си или опцията за заключване на екрана, за да продължите"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нещо се обърка. Опитайте отново."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Икона на лице"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"четене на настройките за синхронизиране"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Разрешава на приложението да чете настройките за синхронизиране на профил. Например това може да определи дали приложението Хора е синхронизирано с даден профил."</string> @@ -861,7 +863,7 @@ <string name="relationTypeReferredBy" msgid="5285082289602849400">"Препоръчан/а от"</string> <string name="relationTypeRelative" msgid="3396498519818009134">"Роднина"</string> <string name="relationTypeSister" msgid="3721676005094140671">"Сестра"</string> - <string name="relationTypeSpouse" msgid="6916682664436031703">"Съпруг/а"</string> + <string name="relationTypeSpouse" msgid="6916682664436031703">"Съпруг(а)"</string> <string name="sipAddressTypeCustom" msgid="6283889809842649336">"Персонализиран"</string> <string name="sipAddressTypeHome" msgid="5918441930656878367">"Домашен"</string> <string name="sipAddressTypeWork" msgid="7873967986701216770">"Служебен"</string> @@ -2095,7 +2097,7 @@ <string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Това известие бе класирано по-високо. Докоснете, за да изпратите отзиви."</string> <string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Това известие бе класирано по-ниско. Докоснете, за да изпратите отзиви."</string> <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Подобрени известия"</string> - <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Предложените действия и отговори вече се предоставят от функцията за подобрени известия. Адаптивните известия за Android вече не се поддържат."</string> + <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Предложените действия и отговори вече се предоставят от функцията за подобрени известия. Адаптивните известия за Android вече не се поддържат."</string> <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Изключване"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Научете повече"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 2f68cdab4a03..5543d724becc 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"চালিয়ে যেতে আপনার আঙুলের ছাপ বা স্ক্রিন লক ব্য়বহার করুন"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"কোনও সমস্যা হয়েছে। আবার করে দেখুন।"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেস আনলক"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"\'ফেস আনলক\' ফিচার ব্যবহার করার ক্ষেত্রে হওয়া সমস্যা"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"চালিয়ে যেতে আপনার ফেস বা স্ক্রিন লক ব্যবহার করুন"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"কোনও সমস্যা হয়েছে। আবার করে দেখুন।"</string> <string name="face_icon_content_description" msgid="465030547475916280">"ফেস আইকন"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"সিঙ্ক সেটিংস পড়ে"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 3ebb7ccc8471..1e574bddc045 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da nastavite"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nešto nije uredu. Pokušajte ponovo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona za otisak prsta"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem s otključavanjem licem"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da nastavite"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nešto nije uredu. Pokušajte ponovo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki za sinhroniziranje"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Omogućava aplikaciji čitanje postavki sinhroniziranja za račun. Naprimjer, ovim se može utvrditi da li je aplikacija People sinhronizirana sa računom."</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 880ad1804498..6256eb4c4c89 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -325,7 +325,7 @@ <string name="permgrouplab_phone" msgid="570318944091926620">"Telèfon"</string> <string name="permgroupdesc_phone" msgid="270048070781478204">"fer i gestionar trucades telefòniques"</string> <string name="permgrouplab_sensors" msgid="9134046949784064495">"Sensors corporals"</string> - <string name="permgroupdesc_sensors" msgid="2610631290633747752">"accedir a les dades del sensor sobre els signes vitals"</string> + <string name="permgroupdesc_sensors" msgid="2610631290633747752">"accedir a les dades del sensor sobre les constants vitals"</string> <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperar el contingut de la finestra"</string> <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecciona el contingut d\'una finestra amb què estàs interaccionant."</string> <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activar Exploració tàctil"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilitza l\'empremta digital o el bloqueig de pantalla per continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"S\'ha produït un error. Torna-ho a provar."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona d\'empremta digital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueig facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema amb Desbloqueig facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilitza la cara o el bloqueig de pantalla per continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"S\'ha produït un error. Torna-ho a provar."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icona facial"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"llegir la configuració de sincronització"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Contactes estigui sincronitzada amb un compte."</string> @@ -907,7 +909,7 @@ <string name="emergency_calls_only" msgid="3057351206678279851">"Només trucades d\'emergència"</string> <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Xarxa bloquejada"</string> <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"La targeta SIM està bloquejada pel PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta la guia de l\'usuari o posa\'t en contacte amb el servei d\'atenció al client."</string> + <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta la guia d\'usuari o posa\'t en contacte amb el servei d\'atenció al client."</string> <string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"La targeta SIM està bloquejada."</string> <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"S\'està desbloquejant la targeta SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Has dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 61fb4710b20c..3469a6def770 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte ověřením pomocí otisku prstu nebo zámku obrazovky"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Došlo k chybě. Zkuste to znovu."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otisku prstů"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odemknutí obličejem"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odemykáním obličejem"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte ověřením pomocí obličeje nebo zámku obrazovky"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Došlo k chybě. Zkuste to znovu."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona obličeje"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čtení nastavení synchronizace"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikaci číst nastavení synchronizace v účtu. Může například určit, zda je s účtem synchronizována aplikace Lidé."</string> @@ -1369,9 +1371,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-da/strings.xml b/core/res/res/values-da/strings.xml index 45f02e363fe9..bcca73465b9a 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -194,11 +194,11 @@ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratoren har gjort personlig brug af enheden utilgængelig"</string> <string name="network_logging_notification_title" msgid="554983187553845004">"Dette er en administreret enhed"</string> <string name="network_logging_notification_text" msgid="1327373071132562512">"Din organisation administrerer denne enhed og kan overvåge netværkstrafik. Tryk for at se info."</string> - <string name="location_changed_notification_title" msgid="3620158742816699316">"Apps kan få adgang til din placering"</string> + <string name="location_changed_notification_title" msgid="3620158742816699316">"Apps kan få adgang til din lokation"</string> <string name="location_changed_notification_text" msgid="7158423339982706912">"Kontakt din it-administrator for at få flere oplysninger"</string> - <string name="geofencing_service" msgid="3826902410740315456">"Geografisk placeringstjeneste"</string> + <string name="geofencing_service" msgid="3826902410740315456">"Tjeneste til geografisk afgrænsning"</string> <string name="country_detector" msgid="7023275114706088854">"Landeregistrering"</string> - <string name="location_service" msgid="2439187616018455546">"Placeringstjeneste"</string> + <string name="location_service" msgid="2439187616018455546">"Lokationstjeneste"</string> <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Tjenesten Sensor Notification"</string> <string name="twilight_service" msgid="8964898045693187224">"Tjenesten Twilight"</string> @@ -304,8 +304,8 @@ <string name="managed_profile_label" msgid="7316778766973512382">"Skift til arbejdsprofil"</string> <string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakter"</string> <string name="permgroupdesc_contacts" msgid="9163927941244182567">"have adgang til dine kontakter"</string> - <string name="permgrouplab_location" msgid="1858277002233964394">"Placering"</string> - <string name="permgroupdesc_location" msgid="1995955142118450685">"få adgang til enhedens placering"</string> + <string name="permgrouplab_location" msgid="1858277002233964394">"Lokation"</string> + <string name="permgroupdesc_location" msgid="1995955142118450685">"få adgang til enhedens lokation"</string> <string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalender"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"have adgang til din kalender"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string> @@ -434,14 +434,14 @@ <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din tablet. Denne app kan sende meddelelser, der kan se ud, som om de kommer fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string> <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din Android TV-enhed. Denne app kan sende meddelelser, der lader til at stamme fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string> <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din telefon. Denne app kan sende meddelelser, der kan se ud, som om de kommer fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string> - <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få adgang til yderligere kommandoer for placeringsudbyder"</string> - <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder."</string> - <string name="permlab_accessFineLocation" msgid="6426318438195622966">"få kun adgang til nøjagtig placering i forgrunden"</string> - <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Denne app kan finde din nøjagtige placering via placeringstjenester, når appen er i brug. Placeringstjenester skal være aktiveret på din enhed, før appen kan finde din placering. Dette kan øge batteriforbruget."</string> - <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"få kun adgang til omtrentlig placering i forgrunden"</string> - <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Denne app kan finde din omtrentlige placering via placeringstjenester, når appen er i brug. Placeringstjenester skal være aktiveret på din enhed, før appen kan finde din placering."</string> - <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"adgang til placering i baggrunden"</string> - <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Denne app kan til enhver tid få adgang til din placering, selv når den ikke er i brug."</string> + <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få adgang til yderligere kommandoer for lokationsudbyder"</string> + <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillader, at appen kan få adgang til yderligere kommandoer for lokationsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre lokationskilder."</string> + <string name="permlab_accessFineLocation" msgid="6426318438195622966">"få kun adgang til nøjagtig lokation i forgrunden"</string> + <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Denne app kan finde din nøjagtige lokation via lokationstjenester, når appen er i brug. Lokationstjenester skal være aktiveret på din enhed, før appen kan finde din lokation. Dette kan øge batteriforbruget."</string> + <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"få kun adgang til omtrentlig lokation i forgrunden"</string> + <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Denne app kan finde din omtrentlige lokation via lokationstjenester, når appen er i brug. Lokationstjenester skal være aktiveret på din enhed, før appen kan finde din lokation."</string> + <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"adgang til lokation i baggrunden"</string> + <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Denne app kan til enhver tid få adgang til din lokation, selv når den ikke er i brug."</string> <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"skifte dine lydindstillinger"</string> <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string> <string name="permlab_recordAudio" msgid="1208457423054219147">"optage lyd"</string> @@ -561,8 +561,8 @@ <string name="permdesc_videoWrite" msgid="6124731210613317051">"Tillader, at appen kan ændre din videosamling."</string> <string name="permlab_imagesWrite" msgid="1774555086984985578">"ændre din billedsamling"</string> <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Tillader, at appen kan ændre din billedsamling."</string> - <string name="permlab_mediaLocation" msgid="7368098373378598066">"læse placeringer fra din mediesamling"</string> - <string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillader, at appen kan læse placeringer fra din mediesamling."</string> + <string name="permlab_mediaLocation" msgid="7368098373378598066">"læse lokationer fra din mediesamling"</string> + <string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillader, at appen kan læse lokationer fra din mediesamling."</string> <string name="biometric_app_setting_name" msgid="3339209978734534457">"Brug biometri"</string> <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Brug biometri eller skærmlås"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Bekræft, at det er dig"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Brug dit fingeraftryk eller din skærmlås for at fortsætte"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Noget gik galt. Prøv igen."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeraftryk"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtslås"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtslås"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Brug din ansigts- eller skærmlås for at fortsætte"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Noget gik galt. Prøv igen."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ansigt"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"læse indstillinger for synkronisering"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillader, at appen kan læse synkroniseringsindstillingerne for en konto. Denne tilladelse kan f.eks. fastslå, om appen Personer er synkroniseret med en konto."</string> @@ -1525,8 +1527,8 @@ <string name="websearch" msgid="5624340204512793290">"Websøgning"</string> <string name="find_next" msgid="5341217051549648153">"Find næste"</string> <string name="find_previous" msgid="4405898398141275532">"Find forrige"</string> - <string name="gpsNotifTicker" msgid="3207361857637620780">"Placeringsanmodning fra <xliff:g id="NAME">%s</xliff:g>"</string> - <string name="gpsNotifTitle" msgid="1590033371665669570">"Placeringsanmodning"</string> + <string name="gpsNotifTicker" msgid="3207361857637620780">"Lokationsanmodning fra <xliff:g id="NAME">%s</xliff:g>"</string> + <string name="gpsNotifTitle" msgid="1590033371665669570">"Lokationsanmodning"</string> <string name="gpsNotifMessage" msgid="7346649122793758032">"Anmodet om af <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string> <string name="gpsVerifYes" msgid="3719843080744112940">"Ja"</string> <string name="gpsVerifNo" msgid="1671201856091564741">"Nej"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 865f02663299..795c42571261 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -336,7 +336,7 @@ <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Legt die Zoom-Stufe und -Position auf dem Display fest."</string> <string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Touch-Gesten möglich"</string> <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Tippen, Wischen, Zusammenziehen und andere Touch-Gesten möglich."</string> - <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesten auf dem Fingerabdrucksensor"</string> + <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesten auf dem Fingerabdrucksensor"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Verwende deinen Fingerabdruck oder deine Display-Entsperrmethode, um fortzufahren"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Ein Problem ist aufgetreten. Versuch es noch einmal."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Entsperrung per Gesichtserkennung"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem bei der Entsperrung per Gesichtserkennung"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Verwende die Gesichtserkennung oder deine Display-Entsperrmethode, um fortzufahren"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Ein Problem ist aufgetreten. Versuch es noch einmal."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Gesichtssymbol"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"Synchronisierungseinstellungen lesen"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 67bd43325cf7..a8dcc4f835e8 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Χρησιμοποιήστε το δακτυλικό σας αποτύπωμα ή το κλείδωμα οθόνης για να συνεχίσετε"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ξεκλείδωμα με το πρόσωπο"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Πρόβλημα με το Ξεκλείδωμα με το πρόσωπο"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Χρησιμοποιήστε το πρόσωπό σας ή το κλείδωμα οθόνης για συνέχεια"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Εικ. προσ."</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"διαβάζει τις ρυθμίσεις συγχρονισμού"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 8cf968d503a7..c268eda05323 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index b772335a6438..5e5ffbe49268 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index e1e81870cfa3..c65b8bbdbfdc 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 892041c2332d..baa35172c964 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index a7ad2b6dc16a..dcf237ed3929 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 5206c484b893..8987cda96efa 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Usa tu huella dactilar o bloqueo de pantalla para continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Se produjo un error. Vuelve a intentarlo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella dactilar"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con el Desbloqueo facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu rostro o bloqueo de pantalla para continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Se produjo un error. Vuelve a intentarlo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ícono cara"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"leer la configuración de sincronización"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Este permiso permite que la aplicación consulte la configuración de sincronización de una cuenta. Esto permite, por ejemplo, determinar si la aplicación Personas está sincronizada con una cuenta."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 9a29addc10b0..81d36263fef0 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Usa tu huella digital o tu bloqueo de pantalla para continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Se ha producido un error. Inténtalo de nuevo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icono de huella digital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Desbloqueo facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu cara o tu bloqueo de pantalla para continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Se ha producido un error. Inténtalo de nuevo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icono cara"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"leer la configuración de sincronización"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que la aplicación consulte la configuración de sincronización de una cuenta. La aplicación puede utilizar este permiso, por ejemplo, para determinar si la aplicación Contactos está sincronizada con una cuenta."</string> @@ -1056,7 +1058,7 @@ </plurals> <string name="last_month" msgid="1528906781083518683">"El mes pasado"</string> <string name="older" msgid="1645159827884647400">"Anterior"</string> - <string name="preposition_for_date" msgid="2780767868832729599">"el <xliff:g id="DATE">%s</xliff:g>"</string> + <string name="preposition_for_date" msgid="2780767868832729599">"<xliff:g id="DATE">%s</xliff:g>"</string> <string name="preposition_for_time" msgid="4336835286453822053">"a las <xliff:g id="TIME">%s</xliff:g>"</string> <string name="preposition_for_year" msgid="3149809685340130039">"en <xliff:g id="YEAR">%s</xliff:g>"</string> <string name="day" msgid="8394717255950176156">"día"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 4dd7d9469f4c..b76e7e3ddf7a 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jätkamiseks kasutage oma sõrmejälge või ekraanilukku"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Midagi läks valesti. Proovige uuesti."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sõrmejälje ikoon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Näoga avamine"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem funktsiooniga Näoga avamine"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jätkamiseks kasutage oma nägu või ekraanilukku"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Midagi läks valesti. Proovige uuesti."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Näoikoon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"loe sünkroonimisseadeid"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Võimaldab rakendusel lugeda konto sünkroonimisseadeid. Näiteks võib see määrata, kas rakendus Inimesed on kontoga sünkroonitud."</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index d4705c100a8f..cc394dddc4fd 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aurrera egiteko, erabili hatz-marka edo pantailaren blokeoa"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Arazoren bat izan da. Saiatu berriro."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegi bidez desblokeatzeko eginbidea"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arazoak ditugu aurpegi bidez desblokeatzeko eginbidearekin"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aurrera egiteko, erabili aurpegia edo pantailaren blokeoa"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Arazoren bat izan da. Saiatu berriro."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Aurpegiaren ikonoa"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"irakurri sinkronizazio-ezarpenak"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string> @@ -1312,7 +1314,7 @@ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sareak konektagarritasun murriztua du"</string> <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Sakatu hala ere konektatzeko"</string> <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string> - <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Baliteke zerbait ordaindu behar izatea."</string> <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> erabiltzen ari zinen, baina <xliff:g id="NEW_NETWORK">%2$s</xliff:g> erabiltzen ari zara orain"</string> <string-array name="network_switch_type_name"> <item msgid="2255670471736226365">"datu-konexioa"</item> @@ -1985,7 +1987,7 @@ <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string> - <string name="new_sms_notification_content" msgid="3197949934153460639">"Mezuak ikusteko, ireki SMS mezuetarako aplikazioa"</string> + <string name="new_sms_notification_content" msgid="3197949934153460639">"Mezuak ikusteko, ireki SMSetarako aplikazioa"</string> <string name="profile_encrypted_title" msgid="9001208667521266472">"Baliteke funtzio batzuk mugatuta egotea"</string> <string name="profile_encrypted_detail" msgid="5279730442756849055">"Blokeatuta dago laneko profila"</string> <string name="profile_encrypted_message" msgid="1128512616293157802">"Sakatu profila desblokeatzeko"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index fcca1b39330a..5155dfa9071b 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"برای ادامه، از اثر انگشت یا قفل صفحه استفاده کنید"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"مشکلی پیش آمد. دوباره امتحان کنید."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"نماد اثر انگشت"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"قفلگشایی با چهره"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشکل در «قفلگشایی با چهره»"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"برای ادامه، از تشخیص چهره یا قفل صفحه استفاده کنید"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"مشکلی پیش آمد. دوباره امتحان کنید."</string> <string name="face_icon_content_description" msgid="465030547475916280">"نماد چهره"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"خواندن تنظیمات همگامسازی"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"به برنامه اجازه میدهد تنظیمات را برای یک حساب بخواند. بهعنوان مثال، این ویژگی میتواند تعیین کند آیا حساب «افراد» شما با یک حساب همگامسازی شده است."</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 5998269aae48..1e491e5b7482 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jatka sormenjäljen tai näytön lukituksen avulla"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Jotain meni vikaan. Yritä uudelleen."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sormenjälkikuvake"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kasvojentunnistusavaus"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Face Unlockiin liittyvä ongelma"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jatka kasvojentunnistuksen tai näytön lukituksen avulla"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Jotain meni vikaan. Yritä uudelleen."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Kasvokuvake"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lue synkronointiasetuksia"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Antaa sovelluksen lukea tilien synkronointiasetuksia. Sovellus voi esimerkiksi määrittää, onko Henkilöt-sovellus synkronoitu tilin kanssa."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 860e10bcff4d..46994f07b18c 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -601,7 +601,7 @@ <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Aucune empreinte digitale enregistrée."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Cet appareil ne possède pas de capteur d\'empreintes digitales."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Le capteur a été désactivé temporairement."</string> - <string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"Impossible utiliser capteur empreinte digitale. Consultez un fournisseur de services de réparation"</string> + <string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"Impossible d\'utiliser le capteur d\'empreintes digitales. Consultez un fournisseur de services de réparation"</string> <string name="fingerprint_name_template" msgid="8941662088160289778">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string> <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utiliser l\'empreinte digitale"</string> <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Utiliser l\'empreinte digitale ou le verrouillage de l\'écran"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Un problème est survenu. Réessayez."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème avec la fonctionnalité de déverrouillage par reconnaissance faciale"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez votre visage ou le verrouillage de l\'écran pour continuer"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Un problème est survenu. Réessayez."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 55fa1453caf8..b1a7eece28ed 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Un problème est survenu. Réessayez."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème lié au déverrouillage par reconnaissance faciale"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez la reconnaissance faciale ou le verrouillage de l\'écran pour continuer"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Un problème est survenu. Réessayez."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 76f54ff26b09..50117568dad4 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Para continuar, utiliza a impresión dixital ou o bloqueo de pantalla"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Produciuse un erro. Téntao de novo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona de impresión dixital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Produciuse un problema co desbloqueo facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Para continuar, utiliza o desbloqueo facial ou a credencial do dispositivo"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Produciuse un erro. Téntao de novo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icona cara"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler a configuración de vinculación"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite á aplicación ler a configuración de vinculación dunha conta. Por exemplo, esta acción pode determinar se a aplicación Contactos se vincula cunha conta."</string> @@ -981,7 +983,7 @@ <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"Confirmar navegación"</string> <string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"Abandonar esta páxina"</string> <string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"Permanecer nesta páxina"</string> - <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nEstás seguro de que queres saír desta páxina?"</string> + <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nSeguro que queres saír desta páxina?"</string> <string name="save_password_label" msgid="9161712335355510035">"Confirmar"</string> <string name="double_tap_toast" msgid="7065519579174882778">"Consello: Toca dúas veces para achegar e afastar o zoom."</string> <string name="autofill_this_form" msgid="3187132440451621492">"Encher"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index e473ab670e75..e1d89ab6ab73 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -100,7 +100,7 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"પીઅરે TTY મોડ HCO ની વિનંતી કરી"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"પીઅરે TTY મોડ VCO ની વિનંતી કરી"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"પીઅરે TTY મોડ બંધ કરવાની વિનંતી કરી"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"વૉઇસ"</string> <string name="serviceClassData" msgid="4148080018967300248">"ડેટા"</string> <string name="serviceClassFAX" msgid="2561653371698904118">"ફેક્સ"</string> <string name="serviceClassSMS" msgid="1547664561704509004">"SMS"</string> @@ -306,7 +306,7 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"તમારા સંપર્કોને ઍક્સેસ કરવાની"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"સ્થાન"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"આ ઉપકરણના સ્થાનને ઍક્સેસ કરવાની"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"કૅલેન્ડર"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"તમારા કેલેન્ડરને ઍક્સેસ કરવાની"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS સંદેશા મોકલવાની અને જોવાની"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ચાલુ રાખવા માટે તમારા ફિંગરપ્રિન્ટ અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ફિંગરપ્રિન્ટ આયકન"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ફેસ અનલૉક"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ફેસ અનલૉકની સુવિધામાં સમસ્યા"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ચાલુ રાખવા માટે તમારા ફેસ લૉક અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string> <string name="face_icon_content_description" msgid="465030547475916280">"ચહેરા આઇકન"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સિંક સેટિંગ વાંચો"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ સિંક થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"અન્ય"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"કસ્ટમ"</string> <string name="relationTypeCustom" msgid="282938315217441351">"કસ્ટમ"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"આસિસ્ટંટ"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"ભાઈ"</string> <string name="relationTypeChild" msgid="9076258911292693601">"બાળક"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"ઘરેલું ભાગીદાર"</string> @@ -950,7 +952,7 @@ <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> વિજેટ."</string> <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"વપરાશકર્તા પસંદગીકર્તા"</string> <string name="keyguard_accessibility_status" msgid="6792745049712397237">"સ્થિતિ"</string> - <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"કૅમેરો"</string> + <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"કૅમેરા"</string> <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"મીડિયા નિયંત્રણો"</string> <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"વિજેટ પુનઃક્રમાંકન પ્રારંભ થયું."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"વિજેટ પુનઃક્રમાંકન સમાપ્ત થયું."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index dcf357b2307a..8df37722e5d9 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -326,7 +326,7 @@ <string name="permgroupdesc_phone" msgid="270048070781478204">"फ़ोन कॉल करने और उन्हें प्रबंधित करने की अनुमति दें"</string> <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_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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी रखने के लिए, फ़िंगरप्रिंट या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फ़िंगरप्रिंट आइकॉन"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फ़ेस अनलॉक"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फ़ेस अनलॉक से जुड़ी समस्या"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी रखने के लिए, अपना चेहरा दिखाकर या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string> <string name="face_icon_content_description" msgid="465030547475916280">"चेहरे का आइकॉन"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"समन्वयन सेटिंग पढ़ें"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ऐप्स को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह तय किया जा सकता है कि लोग ऐप्स किसी खाते के साथ समन्वयित है या नहीं."</string> @@ -745,10 +747,10 @@ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"इस फ़ोन पर मौजूद इस उपयोगकर्ता का डेटा बिना चेतावनी के मिटा दें."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"डिवाइस वैश्विक प्रॉक्सी सेट करें"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"नीति चालू होने के दौरान इस्तेमाल करने के लिए डिवाइस ग्लोबल प्रॉक्सी सेट करें. केवल डिवाइस का मालिक ही ग्लोबल प्रॉक्सी सेट कर सकता है."</string> - <string name="policylab_expirePassword" msgid="6015404400532459169">"स्क्रीन लॉक पासवर्ड समाप्ति सेट करें"</string> + <string name="policylab_expirePassword" msgid="6015404400532459169">"स्क्रीन लॉक पासवर्ड के खत्म होने की अवधि सेट करें"</string> <string name="policydesc_expirePassword" msgid="9136524319325960675">"यह बदलें कि स्क्रीन लॉक पासवर्ड, पिन या पैटर्न को कितने समय में बदला जाना चाहिए."</string> <string name="policylab_encryptedStorage" msgid="9012936958126670110">"मेमोरी को सुरक्षित करने का तरीका सेट करें"</string> - <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"संग्रहित ऐप्स डेटा को एन्क्रिप्ट किया जाना आवश्यक है."</string> + <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"स्टोर किए गए ऐप डेटा को एन्क्रिप्ट किया जाना ज़रूरी है."</string> <string name="policylab_disableCamera" msgid="5749486347810162018">"कैमरों को अक्षम करें"</string> <string name="policydesc_disableCamera" msgid="3204405908799676104">"सभी डिवाइस कैमरों का उपयोग रोकें."</string> <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"स्क्रीन लॉक की कुछ सुविधाएं बंद करना"</string> @@ -2008,7 +2010,7 @@ <string name="app_category_image" msgid="7307840291864213007">"फ़ोटो और तस्वीरें"</string> <string name="app_category_social" msgid="2278269325488344054">"सामाजिक और संचार"</string> <string name="app_category_news" msgid="1172762719574964544">"समाचार और पत्रिकाएं"</string> - <string name="app_category_maps" msgid="6395725487922533156">"Maps और नेविगेशन ऐप्लिकेशन"</string> + <string name="app_category_maps" msgid="6395725487922533156">"मैप और नेविगेशन ऐप्लिकेशन"</string> <string name="app_category_productivity" msgid="1844422703029557883">"उत्पादकता"</string> <string name="app_category_accessibility" msgid="6643521607848547683">"सुलभता"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"डिवाइस में जगह"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 9aa3350d6ecd..7dd2ad39891f 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nastavak se identificirajte otiskom prsta ili vjerodajnicom zaključavanja zaslona"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nešto nije u redu. Pokušajte ponovo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Poteškoće s otključavanjem licem"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nastavak se identificirajte licem ili vjerodajnicom zaključavanja zaslona"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nešto nije u redu. Pokušajte ponovo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki sinkronizacije"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogućuje čitanje postavki sinkronizacije za račun. Time se, primjerice, može utvrditi je li aplikacija Osobe sinkronizirana s računom."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 908b77956b44..0e20f2051c29 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"A folytatás ujjlenyomattal vagy a képernyőzár feloldásával lehetséges"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Hiba történt. Próbálja újra."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ujjlenyomat ikon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Arcalapú feloldás"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arcalapú feloldással kapcsolatos problémák"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"A folytatás arcalapú feloldással vagy a képernyőzár feloldásával lehetséges"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Hiba történt. Próbálja újra."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Arcikon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"szinkronizálási beállítások olvasása"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lehetővé teszi az alkalmazás számára egy fiók szinkronizálási beállításainak beolvasását. Például ellenőrizheti, hogy a Személyek alkalmazás szinkronizálva van-e egy fiókkal."</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index a7992f968ea0..f94c8114a0e6 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -177,7 +177,7 @@ <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> - <string name="low_memory" product="watch" msgid="3479447988234030194">"Ժամացույցի ֆայլերի պահեստը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string> + <string name="low_memory" product="watch" msgid="3479447988234030194">"Ժամացույցի ֆայլերի պահոցը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV սարքի հիշողությունը լցված է։ Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string> <string name="low_memory" product="default" msgid="2539532364144025569">"Հեռախոսի պահոցը լիքն է: Ջնջեք մի քանի ֆայլեր` տարածություն ազատելու համար:"</string> <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029"> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Շարունակելու համար օգտագործեք ձեր մատնահետքը կամ էկրանի կողպումը"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Սխալ առաջացավ։ Նորից փորձեք։"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Մատնահետքի պատկերակ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Դեմքով ապակողպում"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Դեմքով ապակողպման հետ կապված խնդիր"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Շարունակելու համար օգտագործեք ձեր դեմքը կամ էկրանի կողպումը"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Սխալ առաջացավ։ Նորից փորձեք։"</string> <string name="face_icon_content_description" msgid="465030547475916280">"Դեմքի պատկերակ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"կարդալ համաժամացման կարգավորումները"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ՝ այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 17382c453f7f..5f9ad9d7d456 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -58,8 +58,8 @@ <string name="meid" msgid="3291227361605924674">"MEID"</string> <string name="ClipMmi" msgid="4110549342447630629">"Nomor Penelepon Masuk"</string> <string name="ClirMmi" msgid="6752346475055446417">"Menyembunyikan ID Penelepon untuk Panggilan Keluar"</string> - <string name="ColpMmi" msgid="4736462893284419302">"ID Saluran yang Tersambung"</string> - <string name="ColrMmi" msgid="5889782479745764278">"Batasan ID Saluran yang Tersambung"</string> + <string name="ColpMmi" msgid="4736462893284419302">"ID Saluran yang Terhubung"</string> + <string name="ColrMmi" msgid="5889782479745764278">"Batasan ID Saluran yang Terhubung"</string> <string name="CfMmi" msgid="8390012691099787178">"Penerusan panggilan"</string> <string name="CwMmi" msgid="3164609577675404761">"Nada tunggu"</string> <string name="BaMmi" msgid="7205614070543372167">"Pemblokiran panggilan"</string> @@ -162,7 +162,7 @@ <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Skema autentikasi situs tidak didukung."</string> <string name="httpErrorAuth" msgid="469553140922938968">"Tidak dapat mengautentikasi."</string> <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Autentikasi via proxy server gagal."</string> - <string name="httpErrorConnect" msgid="3295081579893205617">"Tidak dapat tersambung ke server."</string> + <string name="httpErrorConnect" msgid="3295081579893205617">"Tidak dapat terhubung ke server."</string> <string name="httpErrorIO" msgid="3860318696166314490">"Tidak dapat berkomunikasi dengan server. Coba lagi nanti."</string> <string name="httpErrorTimeout" msgid="7446272815190334204">"Koneksi ke server terputus."</string> <string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Halaman ini berisi terlalu banyak pengalihan server."</string> @@ -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> @@ -468,7 +468,7 @@ <string name="permlab_accessImsCallService" msgid="442192920714863782">"akses layanan panggilan IMS"</string> <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Memungkinkan aplikasi menggunakan layanan IMS untuk melakukan panggilan tanpa campur tangan Anda."</string> <string name="permlab_readPhoneState" msgid="8138526903259297969">"baca identitas dan status ponsel"</string> - <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang tersambung oleh sebuah panggilan."</string> + <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang terhubung oleh sebuah panggilan."</string> <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"sambungkan panggilan telepon melalui sistem"</string> <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Mengizinkan aplikasi menyambungkan panggilan telepon melalui sistem untuk menyempurnakan pengalaman menelepon."</string> <string name="permlab_callCompanionApp" msgid="3654373653014126884">"melihat dan mengontrol panggilan melalui sistem."</string> @@ -504,7 +504,7 @@ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Mengizinkan aplikasi mendapatkan daftar akun yang dikenal oleh perangkat Android TV. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah Anda instal."</string> <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Memungkinkan aplikasi mendapatkan daftar akun yang dikenal oleh ponsel. Ini mungkin termasuk akun yang dibuat oleh aplikasi yang telah Anda instal."</string> <string name="permlab_accessNetworkState" msgid="2349126720783633918">"lihat koneksi jaringan"</string> - <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang koneksi jaringan, misalnya jaringan yang ada dan tersambung."</string> + <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang koneksi jaringan, misalnya jaringan yang ada dan terhubung."</string> <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"dapatkan akses jaringan penuh"</string> <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Memungkinkan aplikasi membuat soket jaringan dan menggunakan protokol jaringan khusus. Browser dan aplikasi lain menyediakan sarana untuk mengirim data ke internet sehingga izin ini tidak diperlukan untuk mengirim data ke internet."</string> <string name="permlab_changeNetworkState" msgid="8945711637530425586">"ubah konektivitas jaringan"</string> @@ -512,7 +512,7 @@ <string name="permlab_changeTetherState" msgid="9079611809931863861">"mengubah konektivitas yang tertambat"</string> <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Mengizinkan apl mengubah status konektivitas jaringan yang tertambat."</string> <string name="permlab_accessWifiState" msgid="5552488500317911052">"lihat sambungan Wi-Fi"</string> - <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Memungkinkan aplikasi melihat informasi tentang jaringan Wi-Fi, misalnya apakah Wi-Fi diaktifkan dan nama perangkat Wi-Fi yang tersambung."</string> + <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Memungkinkan aplikasi melihat informasi tentang jaringan Wi-Fi, misalnya apakah Wi-Fi diaktifkan dan nama perangkat Wi-Fi yang terhubung."</string> <string name="permlab_changeWifiState" msgid="7947824109713181554">"sambung dan putuskan Wi-Fi"</string> <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Memungkinkan aplikasi menyambung ke dan memutus dari titik akses Wi-Fi, dan mengubah konfigurasi perangkat untuk jaringan Wi-Fi."</string> <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"Izinkan penerimaan Wi-Fi Multicast"</string> @@ -524,14 +524,14 @@ <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Mengizinkan aplikasi mengonfigurasi Bluetooth di perangkat Android TV, serta menemukan dan menyambungkan dengan perangkat jarak jauh."</string> <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Mengizinkan apl mengonfigurasi ponsel Bluetooth lokal, dan menemukan serta menyandingkan dengan perangkat jarak jauh."</string> <string name="permlab_accessWimaxState" msgid="7029563339012437434">"sambungkan dan putuskan dari WiMAX"</string> - <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang tersambung."</string> + <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang terhubung."</string> <string name="permlab_changeWimaxState" msgid="6223305780806267462">"Ganti status WiMAX"</string> <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string> <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Mengizinkan aplikasi menghubungkan perangkat Android TV ke, dan memutuskan hubungan perangkat Android TV dari, jaringan WiMAX."</string> <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX."</string> <string name="permlab_bluetooth" msgid="586333280736937209">"sambungkan dengan perangkat Bluetooth"</string> <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string> - <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang tersambung."</string> + <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang terhubung."</string> <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string> <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"temukan & sambungkan perangkat Bluetooth di sekitar"</string> <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Mengizinkan aplikasi menemukan dan menyambungkan perangkat Bluetooth di sekitar"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan sidik jari atau kunci layar untuk melanjutkan"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Terjadi error. Coba lagi."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon sidik jari"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Masalah pada Face Unlock"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan face lock atau kunci layar untuk melanjutkan"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Terjadi error. Coba lagi."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"baca setelan sinkronisasi"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string> @@ -1365,7 +1367,7 @@ <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB diaktifkan"</string> <string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB diaktifkan"</string> <string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB diaktifkan"</string> - <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB tersambung"</string> + <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB terhubung"</string> <string name="usb_notification_message" msgid="4715163067192110676">"Ketuk untuk opsi lainnya."</string> <string name="usb_power_notification_message" msgid="7284765627437897702">"Mengisi daya perangkat yang terhubung. Ketuk untuk opsi lainnya."</string> <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Aksesori audio analog terdeteksi"</string> @@ -1497,9 +1499,9 @@ <string name="vpn_title" msgid="5906991595291514182">"VPN diaktifkan"</string> <string name="vpn_title_long" msgid="6834144390504619998">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="2275388920267251078">"Ketuk untuk mengelola jaringan."</string> - <string name="vpn_text_long" msgid="278540576806169831">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string> + <string name="vpn_text_long" msgid="278540576806169831">"Terhubung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string> <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"Menyambungkan VPN selalu aktif..."</string> - <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN selalu aktif tersambung"</string> + <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN selalu aktif terhubung"</string> <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"Terputus dari VPN yang selalu aktif"</string> <string name="vpn_lockdown_error" msgid="4453048646854247947">"Tidak dapat terhubung ke VPN yang selalu aktif"</string> <string name="vpn_lockdown_config" msgid="8331697329868252169">"Ubah setelan jaringan atau VPN"</string> @@ -1634,7 +1636,7 @@ <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"Setelan"</string> <string name="media_route_controller_disconnect" msgid="7362617572732576959">"Putuskan koneksi"</string> <string name="media_route_status_scanning" msgid="8045156315309594482">"Memindai..."</string> - <string name="media_route_status_connecting" msgid="5845597961412010540">"Menyambung..."</string> + <string name="media_route_status_connecting" msgid="5845597961412010540">"Menghubungkan..."</string> <string name="media_route_status_available" msgid="1477537663492007608">"Tersedia"</string> <string name="media_route_status_not_available" msgid="480912417977515261">"Tidak tersedia"</string> <string name="media_route_status_in_use" msgid="6684112905244944724">"Sedang digunakan"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 93e25a6b014e..76c583720c4d 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Notaðu fingrafar eða skjálás til að halda áfram"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Eitthvað fór úrskeiðis. Reyndu aftur."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingrafaratákn"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Andlitskenni"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vandamál varðandi andlitskenni"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Notaðu andlitið eða skjálás til að halda áfram"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Eitthvað fór úrskeiðis. Reyndu aftur."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Andlitstákn"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lesa samstillingar"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leyfir forriti að lesa kosti samstillingar fyrir reikning. Þetta er til dæmis hægt að nota til að komast að því hvort forritið Fólk er samstillt við reikning."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 6919a3dc6c7c..c4493a188a22 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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Per continuare devi usare la tua impronta o il tuo blocco schermo"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Si è verificato un errore. Riprova."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona dell\'impronta"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Sblocco con il volto"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Sblocco con il volto"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Per continuare devi usare il tuo volto o il tuo blocco schermo"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Si è verificato un errore. Riprova."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Icona volto"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lettura impostazioni di sincronizz."</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Consente all\'applicazione di leggere le impostazioni di sincronizzazione per un account. Ad esempio, questa autorizzazione può determinare se l\'applicazione Persone è sincronizzata con un account."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 716e97c70768..02ff0f561e58 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"יש להשתמש בטביעת האצבע או בנעילת המסך כדי להמשיך"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"משהו השתבש. עליך לנסות שוב."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"סמל טביעת אצבע"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"פתיחה ע\"י זיהוי הפנים"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"בעיה בפתיחה ע\"י זיהוי הפנים"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"יש להשתמש בזיהוי הפנים או בנעילת המסך כדי להמשיך"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"משהו השתבש. עליך לנסות שוב."</string> <string name="face_icon_content_description" msgid="465030547475916280">"סמל הפנים"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"קריאת הגדרות הסנכרון"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"מאפשרת לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, כך אפשר לדעת אם האפליקציה \'אנשים\' מסונכרנת עם חשבון כלשהו."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 30a62e3d8df0..0ef14c2c82a2 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"続行するには、指紋認証または画面ロックを使用してください"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"エラーが発生しました。もう一度お試しください。"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋アイコン"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"顔認証"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"顔認証に関する問題"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"続行するには、顔認証または画面ロックを使用してください"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"エラーが発生しました。もう一度お試しください。"</string> <string name="face_icon_content_description" msgid="465030547475916280">"顔アイコン"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"同期設定の読み取り"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"アカウントの同期設定の読み取りをアプリに許可します。たとえば、連絡帳アプリがアカウントと同期しているかどうかをアプリから特定できるようになります。"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 789e2794e083..b29ce0aa3795 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი ან ეკრანის განბლოკვის ნიმუში"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"თითის ანაბეჭდის ხატულა"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"განბლოკვა სახით"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"პრობლემა სახით განბლოკვასთან დაკავშირებით"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"გასაგრძელებლად გამოიყენეთ თქვენი სახე ან ეკრანის განბლოკვის ნიმუში"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string> <string name="face_icon_content_description" msgid="465030547475916280">"სახის ხატულა"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"სინქრონიზაციის პარამეტრების წაკითხვა"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"აპს შეეძლება, წაიკითხოს ანგარიშის სინქრონიზაციის პარამეტრები. მაგალითად, მას შეეძლება განსაზღვროს, არის თუ არა People აპი სინქრონიზებული ანგარიშთან."</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 6e8281326606..086a033e44dd 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -278,7 +278,7 @@ <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"Физикалық пернетақта"</string> <string name="notification_channel_security" msgid="8516754650348238057">"Қауіпсіздік"</string> <string name="notification_channel_car_mode" msgid="2123919247040988436">"Көлік режимі"</string> - <string name="notification_channel_account" msgid="6436294521740148173">"Есептік жазба күйі"</string> + <string name="notification_channel_account" msgid="6436294521740148173">"Аккаунт күйі"</string> <string name="notification_channel_developer" msgid="1691059964407549150">"Әзірлеуші хабарлары"</string> <string name="notification_channel_developer_important" msgid="7197281908918789589">"Әзірлеушілердің маңызды хабарлары"</string> <string name="notification_channel_updates" msgid="7907863984825495278">"Жаңартылған нұсқалар"</string> @@ -411,9 +411,9 @@ <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Қолданба трансляция біткеннен кейін сақталатын бекітілген трансляцияларды жібере алатын болады. Тым жиі пайдалансаңыз, жад толып, Android TV құрылғысы баяу немесе тұрақсыз жұмыс істеуі мүмкін."</string> <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Қолданбаға хабар тарату аяқталғанда сақталатын жабысқақ хабар тарату мүмкіндігін береді. Тым көп қолдану телефон жұмысын баяулатады немесе жадты көп қолдану арқылы жұмысын тұрақсыздандырады."</string> <string name="permlab_readContacts" msgid="8776395111787429099">"контактілерді оқу"</string> - <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған планшеттегі есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> - <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданба контактілер жасалған Android TV құрылғысындағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> - <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған телефондағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> + <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған планшеттегі аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> + <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданба контактілер жасалған Android TV құрылғысындағы аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> + <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған телефондағы аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string> <string name="permlab_writeContacts" msgid="8919430536404830430">"контактілерді өзгерту"</string> <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string> <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string> @@ -499,10 +499,10 @@ <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Қолданбаға планшеттің уақыт белдеуін өзгертуге рұқсат береді."</string> <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="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="permlab_accessNetworkState" msgid="2349126720783633918">"желі байланыстарын көру"</string> <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Қолданбаға желі байланысы туралы ақпаратты, мысалы, қайсысы бар және қосылған деген сияқты, көру мүмкіндігін береді."</string> <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"желіге толық қатынасы бар"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Жалғастыру үшін саусақ ізін немесе экран құлпын пайдаланыңыз."</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Бет тану"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Бет тану функциясына қатысты мәселе шықты"</string> @@ -661,13 +662,14 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Жалғастыру үшін бетті анықтау функциясын немесе экран құлпын пайдаланыңыз."</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Бет белгішесі"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"синх параметрлерін оқу"</string> - <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Қолданбаға есептік жазба синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының есептік жазбамен сихрондалғаны анықталуы мүмкін."</string> + <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Қолданбаға аккаунт синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының аккаунтмен сихрондалғаны анықталуы мүмкін."</string> <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"синх қосу және өшіру арасында ауысу"</string> - <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Қолданбаға есептік жазбаның синхрондау параметрлерін жөндеу мүмкіндігін береді. Мысалы, бұл People қолданбасын есептік жазбамен синхрондауды қосу үшін қолданылуы мүмкін."</string> + <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Қолданбаға аккаунттың синхрондау параметрлерін жөндеу мүмкіндігін береді. Мысалы, бұл People қолданбасын аккаунтпен синхрондауды қосу үшін қолданылуы мүмкін."</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> @@ -690,7 +692,7 @@ <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"Қолданбаға белгілі бір желілер және қолданбалар үшін журналдық желіні пайдалануды оқуға рұқсат береді."</string> <string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"желі саясатын басқару"</string> <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Қолданбаға желілік саясаттарды басқаруға және қолданба ережелерін анықтауға рұқсат береді."</string> - <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"желіні қолдану есептік жазбаларын өзгерту"</string> + <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"желіні қолдану аккаунттарын өзгерту"</string> <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"Қолданбаға қолданбалардың желіні қолдану әрекетін өзгерту мүмкіндігін береді. Қалыпты қолданбалар қолданысына арналмаған."</string> <string name="permlab_accessNotifications" msgid="7130360248191984741">"хабарларға кіру"</string> <string name="permdesc_accessNotifications" msgid="761730149268789668">"Қолданбаға хабарларды алу, тексеру және тазалау мүмкіндігін береді, басқа қолданбалар арқылы қойылған хабарларды қоса."</string> @@ -914,7 +916,7 @@ <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Құпия сөзді <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string> <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"PIN кодын <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Бекітпесін ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате салдыңыз. Тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін сізден Google жүйесіне кіріп планшет бекітпесін ашу сұралады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> - <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс сызбадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың құлпын ашу үшін Google есептік жазбаңызға кіру керек болады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайталап көріңіз."</string> + <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс сызбадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың құлпын ашу үшін Google аккаунтыңызға кіру керек болады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайталап көріңіз."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Бекітпесін ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате салдыңыз. Тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін сізден Google жүйесіне кіріп телефон бекітпесін ашу сұралады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"Планшеттің бекітпесін ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате әрекеттендіңіз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін, телефон зауыттың бастапқы параметрлеріне қайта реттеледі және пайдаланушы деректері жоғалады."</string> <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"Android TV құрылғыңыздың құлпын <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс ашпадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың зауыттық әдепкі параметрлері қайтарылады және одан барлық пайдаланушы деректері өшіп қалады."</string> @@ -924,9 +926,9 @@ <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Телефонды ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Телефон зауыттың бастапқы параметрлеріне қайта реттеледі."</string> <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string> <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Кескінді ұмытып қалдыңыз ба?"</string> - <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Есептік жазбаның бекітпесін ашу"</string> + <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Аккаунттың бекітпесін ашу"</string> <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Тым көп кескін әрекеттері"</string> - <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Ашу үшін Google есептік жазбаңызбен кіріңіз."</string> + <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Ашу үшін Google аккаунтыңызбен кіріңіз."</string> <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Пайдаланушы атауы (эл. пошта)"</string> <string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Құпия сөз"</string> <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Кіру"</string> @@ -1330,8 +1332,8 @@ <string name="sms_control_yes" msgid="4858845109269524622">"Рұқсат беру"</string> <string name="sms_control_no" msgid="4845717880040355570">"Өшіру"</string> <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> қолданбасы <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> мекенжайына хабар жіберуді қалайды."</string> - <string name="sms_short_code_details" msgid="2723725738333388351">"Бұл мобильді есептік жазбаңызда "<b>"өзгерістер"</b>" тудыруы мүмкін."</string> - <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Бұл мобильді есептік жазбаңызда өзгерістерді тудырады."</b></string> + <string name="sms_short_code_details" msgid="2723725738333388351">"Бұл мобильді аккаунтыңызда "<b>"өзгерістер"</b>" тудыруы мүмкін."</string> + <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Бұл мобильді аккаунтыңызда өзгерістерді тудырады."</b></string> <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Жіберу"</string> <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Бас тарту"</string> <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Менің таңдауым есте сақталсын"</string> @@ -1475,14 +1477,14 @@ <string name="ime_action_default" msgid="8265027027659800121">"Орындау"</string> <string name="dial_number_using" msgid="6060769078933953531">"Нөмірді\n <xliff:g id="NUMBER">%s</xliff:g> қолданып теріңіз"</string> <string name="create_contact_using" msgid="6200708808003692594">"Байланысты\n <xliff:g id="NUMBER">%s</xliff:g> нөмірі арқылы орнату"</string> - <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Келесі бір немесе бірнеше қолданба қазір және болашақта есептік жазбаңызға қатынасуға рұқсатты сұрап жатыр."</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> - <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Рұқсат \nесептік жазба үшін <xliff:g id="ACCOUNT">%s</xliff:g> өтінілді."</string> - <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы үшін <xliff:g id="APP">%1$s</xliff:g>\nқолданбасы арқылы рұқсат сұралды."</string> + <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Рұқсат \nаккаунт үшін <xliff:g id="ACCOUNT">%s</xliff:g> өтінілді."</string> + <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты үшін <xliff:g id="APP">%1$s</xliff:g>\nқолданбасы арқылы рұқсат сұралды."</string> <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> @@ -1531,13 +1533,13 @@ <string name="gpsVerifYes" msgid="3719843080744112940">"Иә"</string> <string name="gpsVerifNo" msgid="1671201856091564741">"Жоқ"</string> <string name="sync_too_many_deletes" msgid="6999440774578705300">"Жою шектеуінен асып кетті"</string> - <string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"Мұнда <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> жойылған <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> есептік жазбасының элементі бар. Не істеуді қалайсыз?"</string> + <string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"Мұнда <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> жойылған <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> аккаунтының элементі бар. Не істеуді қалайсыз?"</string> <string name="sync_really_delete" msgid="5657871730315579051">"Бұл нәрселер жойылсын"</string> <string name="sync_undo_deletes" msgid="5786033331266418896">"Жойылғандарды кері орындау"</string> <string name="sync_do_nothing" msgid="4528734662446469646">"Қазір ешқандай әрекет жасамаңыз"</string> - <string name="choose_account_label" msgid="5557833752759831548">"Есептік жазба таңдау"</string> - <string name="add_account_label" msgid="4067610644298737417">"Есептік жазба қосу"</string> - <string name="add_account_button_label" msgid="322390749416414097">"Есептік жазба қосу."</string> + <string name="choose_account_label" msgid="5557833752759831548">"Аккаунт таңдау"</string> + <string name="add_account_label" msgid="4067610644298737417">"Аккаунт қосу"</string> + <string name="add_account_button_label" msgid="322390749416414097">"Аккаунт қосу."</string> <string name="number_picker_increment_button" msgid="7621013714795186298">"Арттыру"</string> <string name="number_picker_decrement_button" msgid="5116948444762708204">"Азайту"</string> <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> түймесін басып тұрыңыз."</string> @@ -1665,13 +1667,13 @@ <string name="kg_invalid_puk" msgid="4809502818518963344">"Дұрыс PUK кодын қайта енгізіңіз. Әрекеттерді қайталау SIM картасының істен шығуына себеп болады."</string> <string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN коды сәйкес емес."</string> <string name="kg_login_too_many_attempts" msgid="699292728290654121">"Тым көп кескін әрекеттері"</string> - <string name="kg_login_instructions" msgid="3619844310339066827">"Ашу үшін Google есептік жазбасы арқылы кіріңіз."</string> + <string name="kg_login_instructions" msgid="3619844310339066827">"Ашу үшін Google аккаунты арқылы кіріңіз."</string> <string name="kg_login_username_hint" msgid="1765453775467133251">"Пайдаланушы атауы (эл. пошта)"</string> <string name="kg_login_password_hint" msgid="3330530727273164402">"Құпия сөз"</string> <string name="kg_login_submit_button" msgid="893611277617096870">"Кіру"</string> <string name="kg_login_invalid_input" msgid="8292367491901220210">"Пайдаланушы атауы немесе кілтсөз жарамсыз."</string> <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Пайдаланушы атауын немесе кілтсөзді ұмытып қалдыңыз ба?\n"<b>"google.com/accounts/recovery"</b>" веб-сайтына кіріңіз."</string> - <string name="kg_login_checking_password" msgid="4676010303243317253">"Есептік жазбаны тексеруде…"</string> + <string name="kg_login_checking_password" msgid="4676010303243317253">"Аккаунтты тексеруде…"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"PIN кодты <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Құпия сөзді <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате салдыңыз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> @@ -1681,9 +1683,9 @@ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"Планшетті ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Планшет бастапқы зауыттық параметрлеріне қайта реттеледі."</string> <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Android TV құрылғыңыздың құлпын <xliff:g id="NUMBER">%d</xliff:g> рет дұрыс ашпадыңыз. Енді Android TV құрылғыңыздың зауыттық әдепкі параметрлері қайтарылады."</string> <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Телефонды ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Телефон бастапқы зауыттық параметрлеріне қайта реттеледі."</string> - <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. After <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін планшетіңізді есептік жазба арқылы ашу өтінішін аласыз.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string> - <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс сызбадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың құлпын ашу үшін есептік жазбаңызға кіру керек болады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайталап көріңіз."</string> - <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string> + <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. After <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін планшетіңізді аккаунт арқылы ашу өтінішін аласыз.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string> + <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс сызбадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың құлпын ашу үшін аккаунтыңызға кіру керек болады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайталап көріңіз."</string> + <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды аккаунт арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string> <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string> <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Жою"</string> <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string> @@ -1964,8 +1966,8 @@ <string name="importance_from_user" msgid="2782756722448800447">"Сіз осы хабарландырулардың маңыздылығын орнатасыз."</string> <string name="importance_from_person" msgid="4235804979664465383">"Қатысты адамдарға байланысты бұл маңызды."</string> <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Арнаулы хабар хабарландыруы"</string> - <string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы (мұндай есептік жазбаға ие пайдаланушы бұрыннан бар) жасауға рұқсат етілсін бе?"</string> - <string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы жасауға рұқсат етілсін бе?"</string> + <string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы (мұндай аккаунтқа ие пайдаланушы бұрыннан бар) жасауға рұқсат етілсін бе?"</string> + <string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы жасауға рұқсат етілсін бе?"</string> <string name="language_selection_title" msgid="52674936078683285">"Тіл қосу"</string> <string name="country_selection_title" msgid="5221495687299014379">"Аймақ параметрі"</string> <string name="search_language_hint" msgid="7004225294308793583">"Тіл атауын теріңіз"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index d56a55ded4a9..8b4d9b63c3ea 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ប្រើការចាក់សោអេក្រង់ ឬស្នាមម្រាមដៃរបស់អ្នក ដើម្បីបន្ត"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"រូបស្នាមម្រាមដៃ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ដោះសោតាមទម្រង់មុខ"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"មានបញ្ហាពាក់ព័ន្ធនឹងមុខងារដោះសោតាមទម្រង់មុខ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ប្រើការចាក់សោអេក្រង់ ឬមុខរបស់អ្នក ដើម្បីបន្ត"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string> <string name="face_icon_content_description" msgid="465030547475916280">"រូបផ្ទៃមុខ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"អានការកំណត់ធ្វើសមកាលកម្ម"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ឲ្យកម្មវិធីអានការកំណត់ធ្វើសមកាលកម្មសម្រាប់គណនី។ ឧទាហរណ៍ វាអាចកំណត់ថាតើកម្មវិធីត្រូវបានបើកជាមួយគណនីដែរឬទេ។"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index ed2f964d29e7..af6df158afbe 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -306,7 +306,7 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"ಸ್ಥಳ"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"ಕ್ಯಾಲೆಂಡರ್"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ಮುಂದುವರಿಸಲು ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಐಕಾನ್"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ಫೇಸ್ ಅನ್ಲಾಕ್"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ಫೇಸ್ ಅನ್ಲಾಕ್ ಕುರಿತು ಸಮಸ್ಯೆ ಇದೆ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಮುಖ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="face_icon_content_description" msgid="465030547475916280">"ಮುಖದ ಐಕಾನ್"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ರೀಡ್ ಮಾಡು"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ಕಚೇರಿ ಮೊಬೈಲ್"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"ಕಚೇರಿ ಪೇಜರ್"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"ಅಸಿಸ್ಟೆಂಟ್"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"ಕಸ್ಟಮ್"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"ಜನ್ಮದಿನ"</string> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"ಇತರೆ"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"ಕಸ್ಟಮ್"</string> <string name="relationTypeCustom" msgid="282938315217441351">"ಕಸ್ಟಮ್"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"ಅಸಿಸ್ಟೆಂಟ್"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"ಸಹೋದರ"</string> <string name="relationTypeChild" msgid="9076258911292693601">"ಮಗು"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"ಸ್ಥಳೀಯ ಪಾಲುದಾರ"</string> @@ -1038,9 +1040,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ಅಳಿಸಿ"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> + <string name="search_go" msgid="2141477624421347086">"ಹುಡುಕಿ"</string> <string name="search_hint" msgid="455364685740251925">"ಹುಡುಕಿ…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"ಹುಡುಕಿ"</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> @@ -1467,7 +1469,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ಝೂಮ್ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string> <string name="ime_action_go" msgid="5536744546326495436">"ಹೋಗು"</string> - <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> + <string name="ime_action_search" msgid="4501435960587287668">"ಹುಡುಕಿ"</string> <string name="ime_action_send" msgid="8456843745664334138">"ಕಳುಹಿಸು"</string> <string name="ime_action_next" msgid="4169702997635728543">"ಮುಂದೆ"</string> <string name="ime_action_done" msgid="6299921014822891569">"ಮುಗಿದಿದೆ"</string> @@ -1972,7 +1974,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"ಸೂಚಿತ ಭಾಷೆ"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string> <string name="region_picker_section_all" msgid="756441309928774155">"ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"ಹುಡುಕಿ"</string> <string name="app_suspended_title" msgid="888873445010322650">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಸದ್ಯಕ್ಕೆ ಲಭ್ಯವಿಲ್ಲ. ಇದನ್ನು <xliff:g id="APP_NAME_1">%2$s</xliff:g> ನಲ್ಲಿ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index ea8fe228896a..1bf33df04aff 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"계속하려면 지문이나 화면 잠금을 사용하세요"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"문제가 발생했습니다. 다시 시도해 보세요."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"지문 아이콘"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"얼굴 인식 잠금 해제"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"얼굴 인식 잠금 해제 문제"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"계속하려면 얼굴 또는 화면 잠금을 사용하세요"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"문제가 발생했습니다. 다시 시도해 보세요."</string> <string name="face_icon_content_description" msgid="465030547475916280">"얼굴 아이콘"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"동기화 설정 읽기"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할지 여부를 확인할 수 있습니다."</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 421608687033..89b6e1573e78 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Улантуу үчүн манжа изин же экрандын кулпусун колдонуңуз"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Манжа изинин сүрөтчөсү"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Жүзүнөн таанып ачуу"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Жүзүнөн таанып ачуу функциясында маселе келип чыкты"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Улантуу үчүн жүзүңүздү же экрандын кулпусун колдонуңуз"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Жүздүн сүрөтчөсү"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"шайкештирүү жөндөөлөрүн окуу"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Колдонмого эсеп менен синхрондошуу тууралоолорун окуганга уруксат берет. Мисалы, Кишилер колдонмосу эсеп менен синхрондошкондугун аныктай алат."</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index b1c0d591c4fb..9849b2988aca 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ໃຊ້ລາຍນິ້ວມື ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ໄອຄອນລາຍນິ້ວມື"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ປົດລັອກດ້ວຍໜ້າ"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ເກີດບັນຫາກັບການປົດລັອກດ້ວຍໜ້າ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ໃຊ້ໃບໜ້າ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string> <string name="face_icon_content_description" msgid="465030547475916280">"ໄອຄອນໃບໜ້າ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ອ່ານການຕັ້ງຄ່າຊິ້ງຂໍ້ມູນ"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການຕັ້ງຄ່າການຊິ້ງຂໍ້ມູນຂອງບັນຊີໄດ້. ຕົວຢ່າງເຊັ່ນ: ມັນຈະສາມາດກວດສອບໄດ້ແອັບຯ People ຖືກຊິ້ງຂໍ້ມູນກັບບັນຊີໃດນຶ່ງແລ້ວຫຼືຍັງ."</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 1879dcc85513..32cf15edfd4a 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jei norite tęsti, naudokite kontrolinį kodą arba ekrano užraktą"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kažkas nepavyko. Bandykite dar kartą."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Piršto antspaudo piktograma"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Atrakinimas pagal veidą"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Su atrakinimu pagal veidą susijusi problema"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jei norite tęsti, naudokite veido atpažinimo funkciją arba ekrano užraktą"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kažkas nepavyko. Bandykite dar kartą."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Veido pkt."</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"skaityti sinchronizavimo nustatymus"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leidžiama programai skaityti ir sinchronizuoti paskyros nustatymus. Pvz., taip gali būti nustatoma, ar su paskyra sinchronizuota Žmonių programa."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 15eda966c48c..48318cdef17b 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -321,7 +321,7 @@ <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"piekļūt jūsu fiziskajām aktivitātēm"</string> <string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string> <string name="permgroupdesc_camera" msgid="7585150538459320326">"uzņemt attēlus un ierakstīt videoklipus"</string> - <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Tuvējās ierīces"</string> + <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Tuvumā esošas ierīces"</string> <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"tuvumā esošu ierīču meklēšana un savienojuma izveide ar tām"</string> <string name="permgrouplab_calllog" msgid="7926834372073550288">"Zvanu žurnāli"</string> <string name="permgroupdesc_calllog" msgid="2026996642917801803">"lasīt un rakstīt tālruņa zvanu žurnālu"</string> @@ -542,7 +542,7 @@ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Ļauj lietotnei piekļūt pārī savienotām Bluetooth ierīcēm."</string> <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"reklamēšana tuvumā esošās Bluetooth ierīcēs"</string> <string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Atļauj lietotnei veikt reklamēšanu tuvumā esošās Bluetooth ierīcēs"</string> - <string name="permlab_uwb_ranging" msgid="8141915781475770665">"novietojuma noteikšana starp tuvu esošām ultraplatjoslas ierīcēm"</string> + <string name="permlab_uwb_ranging" msgid="8141915781475770665">"novietojums starp tuvējām ultraplatjoslas ierīcēm"</string> <string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Atļaut lietotnei noteikt relatīvo atrašanās vietu starp tuvumā esošām ultraplatjoslas ierīcēm"</string> <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informācija par vēlamo NFC maksājumu pakalpojumu"</string> <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ļauj lietotnei iegūt informāciju par vēlamo NFC maksājumu pakalpojumu, piemēram, par reģistrētajiem lietojumprogrammu ID un maršruta galamērķi."</string> @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Izmantojiet pirksta nospiedumu vai ekrāna bloķēšanas opciju, lai turpinātu"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Radās kļūda. Mēģiniet vēlreiz."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pirksta nospieduma ikona"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Autorizācija pēc sejas"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problēma ar autorizāciju pēc sejas"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Izmantojiet autorizāciju pēc sejas vai ekrāna bloķēšanas opciju, lai turpinātu"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Radās kļūda. Mēģiniet vēlreiz."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Sejas ikona"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lasīt sinhronizācijas iestatījumus"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ļauj lietotnei lasīt konta sinhronizācijas iestatījumus. Piemēram, šādi var noteikt, vai lietotne Personas ir sinhronizēta ar kontu."</string> diff --git a/core/res/res/values-mcc334-mnc020-af/strings.xml b/core/res/res/values-mcc334-mnc020-af/strings.xml new file mode 100644 index 000000000000..c9177f3cb772 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-af/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"STAWINGMISLUKKING -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NIE INGETEKEN OP DIENS NIE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Veelvuldige PDN-verbindings vir \'n bepaalde APN word nie toegelaat nie -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-am/strings.xml b/core/res/res/values-mcc334-mnc020-am/strings.xml new file mode 100644 index 000000000000..609fcf95630b --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-am/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"የማረጋገጫ አለመሳካት -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ለአገልግሎት ደንበኝነት አልተመዘገበም -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ለተሰጠው ኤፒኤን ብዙ የፒዲኤን ግንኙነቶች አይፈቀዱም -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ar/strings.xml b/core/res/res/values-mcc334-mnc020-ar/strings.xml new file mode 100644 index 000000000000..ac7dec0da313 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ar/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"تعذّرت المصادقة -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"غير مشترك في الخدمة -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"غير مسموح باتصالات PDN متعددة لاسم نقطة وصول محددة (APN) -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-as/strings.xml b/core/res/res/values-mcc334-mnc020-as/strings.xml new file mode 100644 index 000000000000..43f5fb1effa2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-as/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ বিফল হৈছে -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"সেৱাটো ছাবস্ক্ৰাইব কৰা নাই -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"এটা APNৰ বাবে একাধিক PDN সংযোগৰ অনুমতি নাই -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-az/strings.xml b/core/res/res/values-mcc334-mnc020-az/strings.xml new file mode 100644 index 000000000000..83b210d90eaa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-az/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"DOĞRULAMA XƏTASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"XİDMƏTƏ ABUNƏ OLUNMAYIB -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Verilmiş APN üçün birdən çox PDN bağlantısına icazə verilmir -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml b/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..b27e485e5f73 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"POTVRDA IDENTITETA NIJE USPELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nije dozvoljeno više PDN veza za određeni APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-be/strings.xml b/core/res/res/values-mcc334-mnc020-be/strings.xml new file mode 100644 index 000000000000..3ee9e8f1ce60 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-be/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ЗБОЙ АЎТЭНТЫФІКАЦЫІ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"У ВАС НЯМА ПАДПІСКІ НА СЭРВІС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Да гэтага APN нельга падключаць некалькі сетак PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bg/strings.xml b/core/res/res/values-mcc334-mnc020-bg/strings.xml new file mode 100644 index 000000000000..257cf585ca21 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bg/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"НЕУСПЕШНО УДОСТОВЕРЯВАНЕ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЯМА АБОНАМЕНТ ЗА УСЛУГАТА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Не е разрешено да има повече от една PDN връзка за дадено име на точката за достъп (APN) -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bn/strings.xml b/core/res/res/values-mcc334-mnc020-bn/strings.xml new file mode 100644 index 000000000000..f58aea71bdde --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"যাচাই করা যায়নি -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"পরিষেবা সাবস্ক্রাইব করা হয়নি -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"নির্দিষ্ট কোনও APN-এর জন্য একাধিক PDN কানেকশন অনুমোদিত নয় -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bs/strings.xml b/core/res/res/values-mcc334-mnc020-bs/strings.xml new file mode 100644 index 000000000000..4bf1b8f6cbae --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bs/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKACIJA NIJE USPJELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Više PDN veza za određeni APN nije dozvoljeno -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ca/strings.xml b/core/res/res/values-mcc334-mnc020-ca/strings.xml new file mode 100644 index 000000000000..0ad1f1cfc77d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ca/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERROR D\'AUTENTICACIÓ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO ESTÀS SUBSCRIT AL SERVEI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No es permeten diverses connexions PDN per a un APN determinat -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-cs/strings.xml b/core/res/res/values-mcc334-mnc020-cs/strings.xml new file mode 100644 index 000000000000..cfa1a44340da --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-cs/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"SELHÁNÍ OVĚŘENÍ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NEJSTE PŘIHLÁŠENI K ODBĚRU SLUŽBY -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"U jednoho APN není povoleno více než jedno připojení PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-da/strings.xml b/core/res/res/values-mcc334-mnc020-da/strings.xml new file mode 100644 index 000000000000..7d349cf67f5c --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-da/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"GODKENDELSESFEJL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"IKKE TILMELDT TJENESTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flere PDN-forbindelser for en given APN er ikke tilladt -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-de/strings.xml b/core/res/res/values-mcc334-mnc020-de/strings.xml new file mode 100644 index 000000000000..084bf46ee569 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-de/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTIFIZIERUNGSFEHLER -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"DIENST NICHT ABONNIERT -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Mehrere PDN-Verbindungen für einen bestimmten APN sind nicht zulässig -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-el/strings.xml b/core/res/res/values-mcc334-mnc020-el/strings.xml new file mode 100644 index 000000000000..27c5f9548a08 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-el/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ΑΠΟΤΥΧΙΑ ΕΛΕΓΧΟΥ ΤΑΥΤΟΤΗΤΑΣ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ΔΕΝ ΕΓΙΝΕ ΕΓΓΡΑΦΗ ΣΤΗΝ ΥΠΗΡΕΣΙΑ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Δεν επιτρέπονται πολλές συνδέσεις PDN για ένα δεδομένο APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml b/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml b/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml b/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml b/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml b/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml new file mode 100644 index 000000000000..ec8f4ab19bce --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml b/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml new file mode 100644 index 000000000000..8cb181d371ee --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALLO EN LA AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO TE SUSCRIBISTE AL SERVICIO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No se permiten varias conexiones PDN para un APN determinado -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-es/strings.xml b/core/res/res/values-mcc334-mnc020-es/strings.xml new file mode 100644 index 000000000000..0744699804e5 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-es/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERROR DE AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO SUSCRITO AL SERVICIO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No se permiten varias conexiones PDN de un APN concreto -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-et/strings.xml b/core/res/res/values-mcc334-mnc020-et/strings.xml new file mode 100644 index 000000000000..a7e9e1665ee0 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-et/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIMINE EBAÕNNESTUS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TEENUST POLE TELLITUD -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Antud APN-i puhul pole mitu PDN-ühendust lubatud -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-eu/strings.xml b/core/res/res/values-mcc334-mnc020-eu/strings.xml new file mode 100644 index 000000000000..2d05b3fea78d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-eu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"EZIN IZAN DA AUTENTIFIKATU -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"EZ DAGO HARPIDETUTA ZERBITZURA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Ezin da konektatu APN jakin bat PDN batera baino gehiagotara -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fa/strings.xml b/core/res/res/values-mcc334-mnc020-fa/strings.xml new file mode 100644 index 000000000000..8bf364f5b118 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fa/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"اصالتسنجی انجام نشد -۲۹-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"مشترک سرویس نیستید -۳۳-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"تعدادی از اتصالهای PDN مربوط به APN تعیینشده مجاز نیست -۵۵-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fi/strings.xml b/core/res/res/values-mcc334-mnc020-fi/strings.xml new file mode 100644 index 000000000000..f8d01ba03fc4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"TODENNUS EPÄONNISTUI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PALVELUA EI TILATTU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Useat yhteydet eivät ole sallittuja yhdelle APN:lle -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml b/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml new file mode 100644 index 000000000000..19794dafb6c8 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ÉCHEC DE L\'AUTHENTIFICATION -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NON ABONNÉ AU SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Connexions PDN multiples interdites pour un APN donné -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fr/strings.xml b/core/res/res/values-mcc334-mnc020-fr/strings.xml new file mode 100644 index 000000000000..6eaa7cd61589 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ÉCHEC DE L\'AUTHENTIFICATION -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NON INSCRIT AU SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Vous n\'êtes pas autorisé à avoir plusieurs connexions PDN pour un APN donné -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-gl/strings.xml b/core/res/res/values-mcc334-mnc020-gl/strings.xml new file mode 100644 index 000000000000..49baed94d1c7 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-gl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERRO DE AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SEN SUBSCRICIÓN AO SERVIZO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Non está permitido establecer varias conexións de tipo PDN para un determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-gu/strings.xml b/core/res/res/values-mcc334-mnc020-gu/strings.xml new file mode 100644 index 000000000000..5faef6f13a26 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-gu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"પ્રમાણીકરણ નિષ્ફળ થયું -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"સેવા સબ્સ્ક્રાઇબ કરી નથી -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"આપેલા APN માટે એક કરતાં વધારે PDN કનેક્શનની મંજૂરી નથી -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hi/strings.xml b/core/res/res/values-mcc334-mnc020-hi/strings.xml new file mode 100644 index 000000000000..8a11053764b9 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"पुष्टि नहीं की जा सकी -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवा की सदस्यता नहीं ली गई है -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"किसी भी एपीएन के लिए एक से ज़्यादा पीडीएन कनेक्शन की अनुमति नहीं है -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hr/strings.xml b/core/res/res/values-mcc334-mnc020-hr/strings.xml new file mode 100644 index 000000000000..ff9b427e0df4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKACIJA NIJE USPJELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Više PDN veza za određeni APN nije dopušteno -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hu/strings.xml b/core/res/res/values-mcc334-mnc020-hu/strings.xml new file mode 100644 index 000000000000..42776c1e9619 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"SIKERTELEN HITELESÍTÉS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NINCS ELŐFIZETÉSE A SZOLGÁLTATÁSRA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nem engedélyezett több PDN-kapcsolat egy adott APN-nél -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hy/strings.xml b/core/res/res/values-mcc334-mnc020-hy/strings.xml new file mode 100644 index 000000000000..6633bb30e01d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hy/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ՆՈՒՅՆԱԿԱՆԱՑՄԱՆ ՍԽԱԼ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ԴՈՒՔ ԲԱԺԱՆՈՐԴԱԳՐՎԱԾ ՉԵՔ ԱՅՍ ԾԱՌԱՅՈՒԹՅԱՆԸ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Այս APN-ով չի թույլատրվում միանալ տվյալների փոխանցման մեկից ավել բաց ցանցի -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-in/strings.xml b/core/res/res/values-mcc334-mnc020-in/strings.xml new file mode 100644 index 000000000000..79a9dfdf971e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-in/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KEGAGALAN AUTENTIKASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TIDAK BERLANGGANAN KE LAYANAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Beberapa koneksi PDN untuk APN tertentu tidak diizinkan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-is/strings.xml b/core/res/res/values-mcc334-mnc020-is/strings.xml new file mode 100644 index 000000000000..c9049e8821aa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-is/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUÐKENNING MISTÓKST -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"EKKI ÁSKRIFANDI AÐ ÞJÓNUSTU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Margar PDN-tengingar fyrir tiltekinn aðgangsstað eru ekki leyfðar -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-it/strings.xml b/core/res/res/values-mcc334-mnc020-it/strings.xml new file mode 100644 index 000000000000..add9b0d24c20 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-it/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERRORE DI AUTENTICAZIONE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SOTTOSCRIZIONE AL SERVIZIO NON EFFETTUATA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Più connessioni PDN per un dato APN non consentite -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-iw/strings.xml b/core/res/res/values-mcc334-mnc020-iw/strings.xml new file mode 100644 index 000000000000..b8b1ab5ad3b4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-iw/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"האימות נכשל -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"לא נרשמת כמנוי לשירות -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"אין הרשאה למספר חיבורי PDN ל-APN מסוים -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ja/strings.xml b/core/res/res/values-mcc334-mnc020-ja/strings.xml new file mode 100644 index 000000000000..ec543faa0119 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ja/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"認証エラーが発生しました -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"サービスに登録していません -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"特定の APN に対する複数の PDN 接続は許可されていません -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ka/strings.xml b/core/res/res/values-mcc334-mnc020-ka/strings.xml new file mode 100644 index 000000000000..e55057b90f4b --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ka/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ავტორიზაციის შეცდომა -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"გამოწერილი არ გაქვთ სერვისი -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"მრავალი PDN კავშირი მოცემული APN-ისთვის დაუშვებელია -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-kk/strings.xml b/core/res/res/values-mcc334-mnc020-kk/strings.xml new file mode 100644 index 000000000000..f19d2c727c22 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-kk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"АУТЕНТИФИКАЦИЯЛАУ ҚАТЕСІ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ҚЫЗМЕТКЕ ЖАЗЫЛМАҒАН -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Бұл APN үшін бірнеше PDN-ге қосылуға рұқсат берілмеген -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-km/strings.xml b/core/res/res/values-mcc334-mnc020-km/strings.xml new file mode 100644 index 000000000000..08e1a0d8a6f3 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-km/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"មិនអាចផ្ទៀងផ្ទាត់បានទេ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"មិនបានជាវសេវាកម្មទេ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ការតភ្ជាប់ PDN ច្រើនសម្រាប់ APN ដែលបានផ្ដល់មិនត្រូវបានអនុញ្ញាតទេ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-kn/strings.xml b/core/res/res/values-mcc334-mnc020-kn/strings.xml new file mode 100644 index 000000000000..e5780b3e8abb --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-kn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ದೃಢೀಕರಣ ವಿಫಲಗೊಂಡಿದೆ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ಸೇವೆಗೆ ಸಬ್ಸ್ಕ್ರೈಬ್ ಮಾಡಿಲ್ಲ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ನೀಡಲಾದ APN ಗಾಗಿ ಬಹು PDN ಸಂಪರ್ಕಗಳನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ko/strings.xml b/core/res/res/values-mcc334-mnc020-ko/strings.xml new file mode 100644 index 000000000000..444d05097663 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ko/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"인증할 수 없음 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"서비스 구독 중이 아님 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"지정된 APN에 여러 PDN을 연결할 수 없음 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ky/strings.xml b/core/res/res/values-mcc334-mnc020-ky/strings.xml new file mode 100644 index 000000000000..240c6debee1c --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ky/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"АНЫКТЫГЫ ТЕКШЕРИЛГЕН ЖОК -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"КЫЗМАТКА ЖАЗЫЛГАН ЭМЕССИЗ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Бул APN менен бир нече PDN\'ге туташууга болбойт -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lo/strings.xml b/core/res/res/values-mcc334-mnc020-lo/strings.xml new file mode 100644 index 000000000000..89eb9fc9f896 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lo/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ການພິສູດຢືນຢັນບໍ່ສຳເລັດ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ບໍ່ໄດ້ສະໝັກໃຊ້ບໍລິການ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ບໍ່ອະນຸຍາດການເຊື່ອມຕໍ່ PDN ຫຼາຍອັນສຳລັບ APN ທີ່ລະບຸ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lt/strings.xml b/core/res/res/values-mcc334-mnc020-lt/strings.xml new file mode 100644 index 000000000000..9157b8d72b81 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lt/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKAVIMO TRIKTIS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PASLAUGA NEPRENUMERUOJAMA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Kelių PDN ryšiai su APN neleidžiami -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lv/strings.xml b/core/res/res/values-mcc334-mnc020-lv/strings.xml new file mode 100644 index 000000000000..33af8634f1dc --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lv/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKĀCIJAS KĻŪME -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PAKALPOJUMS NAV ABONĒTS -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Norādītajam APN nav atļauti vairāki PDN savienojumi -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mk/strings.xml b/core/res/res/values-mcc334-mnc020-mk/strings.xml new file mode 100644 index 000000000000..5b6b62193440 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"НЕУСПЕШНА ПРОВЕРКА -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕ СТЕ ПРЕТПЛАТЕНИ НА УСЛУГАТА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Не се дозволени повеќекратни PDN-врски за дадена APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ml/strings.xml b/core/res/res/values-mcc334-mnc020-ml/strings.xml new file mode 100644 index 000000000000..d56b4c889896 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ml/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"പരിശോധിച്ചുറപ്പിക്കൽ പരാജയം -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"സേവനം സബ്സ്ക്രൈബ് ചെയ്തിട്ടില്ല -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"നൽകിയിരിക്കുന്ന ഒരു APN-ൽ ഒന്നിലധികം PDN കണക്ഷനുകൾ അനുവദനീയമല്ല -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mn/strings.xml b/core/res/res/values-mcc334-mnc020-mn/strings.xml new file mode 100644 index 000000000000..9eb4753155af --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"БАТАЛГААЖУУЛЖ ЧАДСАНГҮЙ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ҮЙЛЧИЛГЭЭГ ЗАХИАЛААГҮЙ БАЙНА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Өгсөн APN-д хэд хэдэн PDN холболтыг зөвшөөрдөггүй -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mr/strings.xml b/core/res/res/values-mcc334-mnc020-mr/strings.xml new file mode 100644 index 000000000000..7adf6667ebaa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ऑथेंटिकेशन यशस्वी झाले नाही -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवेचे सदस्यत्व घेतलेले नाही -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"दिलेल्या APN साठी एकपेक्षा जास्त PDN कनेक्शनची अनुमती नाही -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ms/strings.xml b/core/res/res/values-mcc334-mnc020-ms/strings.xml new file mode 100644 index 000000000000..cbae67e73bad --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ms/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KEGAGALAN PENGESAHAN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TIDAK MELANGGAN PERKHIDMATAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Sambungan berbilang PDN untuk APN yang diberikan tidak dibenarkan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-my/strings.xml b/core/res/res/values-mcc334-mnc020-my/strings.xml new file mode 100644 index 000000000000..f1e7d6e24b83 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-my/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ဝန်ဆောင်မှုကို စာရင်းသွင်းမထားပါ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ပေးထားသော APN အတွက် PDN ချိတ်ဆက်မှုအများအပြားကို ခွင့်မပြုပါ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-nb/strings.xml b/core/res/res/values-mcc334-mnc020-nb/strings.xml new file mode 100644 index 000000000000..623f2d98663f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-nb/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTISERINGSFEIL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ABONNERER IKKE PÅ TJENESTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flere PDN-tilkoblinger for et gitt APN er ikke tillatt -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ne/strings.xml b/core/res/res/values-mcc334-mnc020-ne/strings.xml new file mode 100644 index 000000000000..fd692766c5d2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ne/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"पुष्टि गर्न सकिएन -२९-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवाको सदस्यता लिइएको छैन -३३-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"कुनै निश्चित APN का हकमा एकभन्दा बढी PDN कनेक्सन गर्ने अनुमति दिइएको छैन -५५-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-nl/strings.xml b/core/res/res/values-mcc334-mnc020-nl/strings.xml new file mode 100644 index 000000000000..40cb2fa4e6e2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-nl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"VERIFICATIE MISLUKT -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NIET GEABONNEERD OP SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Meerdere PDN-verbindingen voor een bepaalde APN niet toegestaan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-or/strings.xml b/core/res/res/values-mcc334-mnc020-or/strings.xml new file mode 100644 index 000000000000..49810d511372 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-or/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ପ୍ରାମାଣିକତା ବିଫଳ ହୋଇଛି -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ସେବା ପାଇଁ ସଦସ୍ୟତା ନିଆଯାଇନାହିଁ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ଦିଆଯାଇଥିବା ଏକ APN ପାଇଁ ଏକାଧିକ PDN ସଂଯୋଗକୁ ଅନୁମତି ଦିଆଯାଇନାହିଁ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pa/strings.xml b/core/res/res/values-mcc334-mnc020-pa/strings.xml new file mode 100644 index 000000000000..3cf6bc88e70e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pa/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ਪ੍ਰਮਾਣੀਕਰਨ ਅਸਫਲ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ਸੇਵਾ ਦੀ ਗਾਹਕੀ ਨਹੀਂ ਲਈ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ਕਿਸੇ ਵੀ APN ਲਈ ਇੱਕ ਤੋਂ ਵੱਧ PDN ਕਨੈਕਸ਼ਨਾਂ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pl/strings.xml b/core/res/res/values-mcc334-mnc020-pl/strings.xml new file mode 100644 index 000000000000..9c5fd78b9527 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"BŁĄD UWIERZYTELNIANIA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"USŁUGA NIESUBSKRYBOWANA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Wielokrotne połączenia PDN w danym APN nie są dozwolone -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml b/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml new file mode 100644 index 000000000000..1292978cc840 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"A CONTA NÃO ESTÁ INSCRITA NO SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não é permitido ter várias conexões PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml b/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml new file mode 100644 index 000000000000..68248f3f6d94 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NÃO SUBSCREVEU O SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não são permitidas várias ligações PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt/strings.xml b/core/res/res/values-mcc334-mnc020-pt/strings.xml new file mode 100644 index 000000000000..1292978cc840 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"A CONTA NÃO ESTÁ INSCRITA NO SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não é permitido ter várias conexões PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ro/strings.xml b/core/res/res/values-mcc334-mnc020-ro/strings.xml new file mode 100644 index 000000000000..92564e977617 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ro/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"EROARE DE AUTENTIFICARE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"FĂRĂ ABONAMENT LA SERVICIU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nu se permit mai multe conexiuni PDN pentru un anumit APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ru/strings.xml b/core/res/res/values-mcc334-mnc020-ru/strings.xml new file mode 100644 index 000000000000..f4647ba04139 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ru/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ОШИБКА АУТЕНТИФИКАЦИИ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕТ ПОДПИСКИ НА СЕРВИС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Указанная точка доступа не поддерживает несколько PDN-соединений -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-si/strings.xml b/core/res/res/values-mcc334-mnc020-si/strings.xml new file mode 100644 index 000000000000..cb839758b29d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-si/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"සත්යාපනය අසාර්ථකයි -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"සේවාවකට ග්රාහක වී නැත -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"දී ඇති APN එකක් සඳහා බහුවිධ PDN සම්බන්ධතා ඉඩ නොදේ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sk/strings.xml b/core/res/res/values-mcc334-mnc020-sk/strings.xml new file mode 100644 index 000000000000..77efe302ecc0 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"NEPODARILO SA OVERIŤ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SLUŽBU NEODOBERÁTE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Pre daný názov prístupového bodu (APN) nie je povolených viacero pripojení PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sl/strings.xml b/core/res/res/values-mcc334-mnc020-sl/strings.xml new file mode 100644 index 000000000000..118c3dde0411 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"NAPAKA PRI PREVERJANJU PRISTNOSTI. -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE NAROČENI NA STORITEV. -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Za dano ime dostopne točke (APN) ni dovoljenih več povezav PDN. -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sq/strings.xml b/core/res/res/values-mcc334-mnc020-sq/strings.xml new file mode 100644 index 000000000000..315a8abba377 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sq/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"DËSHTIM NË VERIFIKIM -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NUK JE ABONUAR NË SHËRBIM -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Disa lidhje PDN për një APN të caktuar nuk lejohen -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sr/strings.xml b/core/res/res/values-mcc334-mnc020-sr/strings.xml new file mode 100644 index 000000000000..ddf0ce15aa78 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ПОТВРДА ИДЕНТИТЕТА НИЈЕ УСПЕЛА -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НИСТЕ ПРЕТПЛАЋЕНИ НА УСЛУГУ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Није дозвољено више PDN веза за одређени APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sv/strings.xml b/core/res/res/values-mcc334-mnc020-sv/strings.xml new file mode 100644 index 000000000000..75bc6427cf55 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sv/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTISERINGSFEL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PRENUMERERAR INTE PÅ TJÄNSTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flera PDN-anslutningar för samma APN tillåts inte -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sw/strings.xml b/core/res/res/values-mcc334-mnc020-sw/strings.xml new file mode 100644 index 000000000000..275f628eab06 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sw/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"IMESHINDWA KUTHIBITISHA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HUJAJISAJILI KWENYE HUDUMA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Miunganisho mingi ya PDN kwenye APN husika hairuhusiwi -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ta/strings.xml b/core/res/res/values-mcc334-mnc020-ta/strings.xml new file mode 100644 index 000000000000..699ea71f7d8d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ta/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"அங்கீகரிக்க முடியவில்லை -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"சேவைக்குச் சந்தா பெறவில்லை -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ஒரு APNக்குப் பல PDN இணைப்புகள் அனுமதிக்கப்படாது -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-te/strings.xml b/core/res/res/values-mcc334-mnc020-te/strings.xml new file mode 100644 index 000000000000..eee21aa44677 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-te/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ప్రామాణీకరణ వైఫల్యం -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ఈ సర్వీస్ కోసం సబ్స్క్రయిబ్ చేసుకోలేదు -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ఈ APNలో బహుళ PDN కనెక్షన్లు అనుమతించబడవు -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-th/strings.xml b/core/res/res/values-mcc334-mnc020-th/strings.xml new file mode 100644 index 000000000000..e4e62f0a0417 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-th/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ล้มเหลว -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ไม่ได้สมัครใช้บริการ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ไม่อนุญาตการเชื่อมต่อ PDN หลายรายการสำหรับ APN ที่กำหนด -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-tl/strings.xml b/core/res/res/values-mcc334-mnc020-tl/strings.xml new file mode 100644 index 000000000000..e05ef9ba28c3 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-tl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"HINDI NA-AUTHENTICATE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HINDI NAKA-SUBSCRIBE SA SERBISYO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Hindi pinapayagan ang maraming PDN na koneksyon para sa isang partikular na APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-tr/strings.xml b/core/res/res/values-mcc334-mnc020-tr/strings.xml new file mode 100644 index 000000000000..7c83aeee3d7f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-tr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KİMLİK DOĞRULAMA HATASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HİZMETE ABONE OLUNMADI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Belirli bir APN için birden fazla PDN bağlantısına izin verilmez -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-uk/strings.xml b/core/res/res/values-mcc334-mnc020-uk/strings.xml new file mode 100644 index 000000000000..dc18a3ed520f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-uk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ПОМИЛКА АВТЕНТИФІКАЦІЇ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕМАЄ ПІДПИСКИ НА СЕРВІС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"З цієї APN не можна підключатися до кількох відкритих мереж -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ur/strings.xml b/core/res/res/values-mcc334-mnc020-ur/strings.xml new file mode 100644 index 000000000000..bab5589eeadb --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ur/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"توثیق کی ناکامی -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"سروس کو سبسکرائب نہیں کیا -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ایک دیئے گئے APN کے لیے متعدد PDN کنکشنز کی اجازت نہیں ہے -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-uz/strings.xml b/core/res/res/values-mcc334-mnc020-uz/strings.xml new file mode 100644 index 000000000000..321aff2efbd2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-uz/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"HAQIQIYLIK TEKSHIRUVIDA XATO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"XIZMATGA OBUNA QILINMAGAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"APN uchun bir nechta PDN ulanishiga ruxsat berilmagan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-vi/strings.xml b/core/res/res/values-mcc334-mnc020-vi/strings.xml new file mode 100644 index 000000000000..bb77bb5298c2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-vi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KHÔNG XÁC THỰC ĐƯỢC -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"CHƯA ĐĂNG KÝ DỊCH VỤ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Không cho phép có nhiều kết nối PDN với một APN đã cho -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml new file mode 100644 index 000000000000..a8fbe74cd3ab --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"身份验证失败 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未订阅服务 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不能有多个 PDN 连接 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml new file mode 100644 index 000000000000..af2057828128 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"認證錯誤 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未訂閱服務 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不允許有多個 PDN 連線 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml new file mode 100644 index 000000000000..2d74d5abfa55 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"驗證失敗 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未訂閱服務 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不允許有多個 PDN 連線 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zu/strings.xml b/core/res/res/values-mcc334-mnc020-zu/strings.xml new file mode 100644 index 000000000000..ef0f3cbbde89 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"UKWEHLULEKA KOKUFAKAZELA UBUQINISO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"AWUBHALISELE ISEVISI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Uxhumano lwe-PDN oluningi lwe-APN enikeziwe aluvunyelwe -55-"</string> +</resources> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index b29d49ef8dbe..34a1d29d0810 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користете го вашиот отпечаток или заклучување екран за да продолжите"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нешто не е во ред. Обидете се повторно."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатоци"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отклучување со лик"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем со „Отклучување со лик“"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користете отклучување со лик или заклучување екран за да продолжите"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нешто не е во ред. Обидете се повторно."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Икона"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"чита поставки за синхронизација"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Овозможува апликацијата да ги чита поставките за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 44172ea0438e..14aab7185c7b 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -100,7 +100,7 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് HCO"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് VCO"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് \'ഓഫ്\'"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"ശബ്ദം"</string> <string name="serviceClassData" msgid="4148080018967300248">"ഡാറ്റ"</string> <string name="serviceClassFAX" msgid="2561653371698904118">"ഫാക്സ്"</string> <string name="serviceClassSMS" msgid="1547664561704509004">"SMS"</string> @@ -306,7 +306,7 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്സസ്സ് ചെയ്യുക"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"ലൊക്കേഷൻ"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാൻ"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"കലണ്ടർ"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"നിങ്ങളുടെ കലണ്ടർ ആക്സസ്സ് ചെയ്യുക"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS സന്ദേശങ്ങൾ അയയ്ക്കുകയും കാണുകയും ചെയ്യുക"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"തുടരാൻ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ഫെയ്സ് അൺലോക്ക്"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ഫെയ്സ് അൺലോക്കുമായി ബന്ധപ്പെട്ട പ്രശ്നം"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"തുടരാൻ നിങ്ങളുടെ മുഖം അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string> <string name="face_icon_content_description" msgid="465030547475916280">"മുഖത്തിന്റെ ഐക്കൺ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ഓഫീസ് മൊബൈല്"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"ഔദ്യോഗിക പേജര്"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"അസിസ്റ്റന്റ്"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"അസിസ്റ്റന്റ്"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"ഇഷ്ടാനുസൃതം"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"ജന്മദിനം"</string> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"മറ്റുള്ളവ"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"ഇഷ്ടാനുസൃതം"</string> <string name="relationTypeCustom" msgid="282938315217441351">"ഇഷ്ടാനുസൃതം"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"അസിസ്റ്റന്റ്"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"സഹോദരന്"</string> <string name="relationTypeChild" msgid="9076258911292693601">"കുട്ടി"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"ഗാര്ഹിക പങ്കാളി"</string> @@ -1038,9 +1040,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"delete"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> + <string name="search_go" msgid="2141477624421347086">"തിരയുക"</string> <string name="search_hint" msgid="455364685740251925">"തിരയുക…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"തിരയുക"</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> @@ -1467,7 +1469,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"വിജറ്റ് ചേർക്കാനായില്ല."</string> <string name="ime_action_go" msgid="5536744546326495436">"പോവുക"</string> - <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> + <string name="ime_action_search" msgid="4501435960587287668">"തിരയുക"</string> <string name="ime_action_send" msgid="8456843745664334138">"അയയ്ക്കുക"</string> <string name="ime_action_next" msgid="4169702997635728543">"അടുത്തത്"</string> <string name="ime_action_done" msgid="6299921014822891569">"പൂർത്തിയായി"</string> @@ -1972,7 +1974,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"നിര്ദ്ദേശിച്ചത്"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"എല്ലാ ഭാഷകളും"</string> <string name="region_picker_section_all" msgid="756441309928774155">"എല്ലാ പ്രദേശങ്ങളും"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"തിരയുക"</string> <string name="app_suspended_title" msgid="888873445010322650">"ആപ്പ് ലഭ്യമല്ല"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല. <xliff:g id="APP_NAME_1">%2$s</xliff:g> ആണ് ഇത് മാനേജ് ചെയ്യുന്നത്."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"കൂടുതലറിയുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 424401584b83..f7be6ee95bb5 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Үргэлжлүүлэхийн тулд хурууны хээ эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Алдаа гарлаа. Дахин оролдоно уу."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Хурууны хээний дүрс"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Царайгаар түгжээ тайлах"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Царайгаар түгжээ тайлахтай холбоотой асуудал"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Үргэлжлүүлэхийн тулд царай эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Алдаа гарлаа. Дахин оролдоно уу."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Царайны дүрс тэмдэг"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"синк тохиргоог унших"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Апп нь бүртгэлийн синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп бүртгэлтэй синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 28522d7e564c..bed5dfc2ff7c 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -100,7 +100,7 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"समवयस्क व्यक्तीने TTY मोड HCO ची विनंती केली"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"समवयस्क व्यक्तीने TTY मोड VCO ची विनंती केली"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"समवयस्क व्यक्तीने TTY मोड बंद ची विनंती केली"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"व्हॉइस"</string> <string name="serviceClassData" msgid="4148080018967300248">"डेटा"</string> <string name="serviceClassFAX" msgid="2561653371698904118">"फॅक्स"</string> <string name="serviceClassSMS" msgid="1547664561704509004">"SMS"</string> @@ -306,7 +306,7 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"आपल्या संपर्कांवर प्रवेश"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"स्थान"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"या डिव्हाइसच्या स्थानावर प्रवेश"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"कॅलेंडर"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"आपल्या कॅलेंडरवर प्रवेश"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS मेसेज पाठवणे आणि पाहणे हे"</string> @@ -408,7 +408,7 @@ <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः सुरू करण्यास अनुमती देते. यामुळे फोन सुरू करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर फोनला धीमे करण्यास अॅप ला अनुमती देते."</string> <string name="permlab_broadcastSticky" msgid="4552241916400572230">"रोचक प्रसारण पाठवा"</string> <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"रोचक प्रसारणे पाठविण्यासाठी अॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो टॅब्लेटला धीमा किंवा अस्थिर करू शकतो."</string> - <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"चिकट प्रसारणे पाठविण्यासाठी ॲपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो तुमच्या Android TV डिव्हाइसला धीमा किंवा अस्थिर करू शकतो."</string> + <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"रोचक प्रसारणे पाठविण्यासाठी अॅपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो तुमच्या Android TV डिव्हाइसला धिमा किंवा अस्थिर करू शकतो."</string> <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"रोचक प्रसारणे पाठविण्यासाठी अॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो फोनला धीमा किंवा अस्थिर करू शकतो."</string> <string name="permlab_readContacts" msgid="8776395111787429099">"तुमचे संपर्क वाचा"</string> <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"तुमच्या टॅबलेटवर स्टोअर केलेल्या तुमच्या संपर्कांविषयीचा डेटा वाचण्याची ॲपला अनुमती देते. अॅप्सना संपर्क तयार केलेल्या तुमच्या टॅबलेटवरील खात्याचा अॅक्सेसदेखील असेल. यामध्ये तुम्ही इंस्टॉल केलेल्या ॲप्सने तयार केलेल्या खात्यांचा समावेश असू शकतात. ही परवानगी ॲप्सना तुमचा संपर्क डेटा सेव्ह करण्याची अनुमती देते आणि दुर्भावनापूर्ण ॲप्स तुम्हाला न कळवता संपर्क डेटा शेअर करू शकतात."</string> @@ -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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"पुढे सुरू ठेवण्यासाठी तुमचे फिंगरप्रिंट किंवा स्क्रीन लॉक वापरा"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिंट आयकन"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलॉक"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलॉकसंबंधित समस्या"</string> @@ -629,7 +630,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> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"पुढे सुरू ठेवण्यासाठी तुमचा चेहरा किंवा स्क्रीन लॉक वापरा"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string> <string name="face_icon_content_description" msgid="465030547475916280">"चेहरा आयकन"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"सिंक सेटिंग्ज वाचा"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"खात्याच्या सिंक सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"कार्य मोबाइल"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"कार्य पेजर"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"असिस्टंट"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"कस्टम"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"वाढदिवस"</string> @@ -983,7 +985,7 @@ <string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"या पेजवर रहा"</string> <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nआपल्याला खात्री आहे की तुम्ही या पृष्ठावरून नेव्हिगेट करू इच्छिता?"</string> <string name="save_password_label" msgid="9161712335355510035">"पुष्टी करा"</string> - <string name="double_tap_toast" msgid="7065519579174882778">"टीप: झूम कमी करण्यासाठी आणि वाढवण्यासाठी दोनदा-टॅप करा."</string> + <string name="double_tap_toast" msgid="7065519579174882778">"टीप: झूम कमी करण्यासाठी आणि वाढवण्यासाठी दोनदा टॅप करा."</string> <string name="autofill_this_form" msgid="3187132440451621492">"स्वयं-भरण"</string> <string name="setup_autofill" msgid="5431369130866618567">"स्वयं-भरण सेट करा"</string> <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> सह ऑटोफील करा"</string> @@ -1016,7 +1018,7 @@ <string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"ब्राउझर भौगोलिक स्थान परवानग्या सुधारित करा"</string> <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"ब्राउझरच्या भौगोलिक स्थान परवानग्या सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स यादृच्छिक वेबसाइटवर स्थान माहिती पाठविण्यास अनुमती देण्यासाठी याचा वापर करू शकतात."</string> <string name="save_password_message" msgid="2146409467245462965">"ब्राउझरने हा पासवर्ड लक्षात ठेवावा असे तुम्ही इच्छिता?"</string> - <string name="save_password_notnow" msgid="2878327088951240061">"आत्ता नाही"</string> + <string name="save_password_notnow" msgid="2878327088951240061">"आता नको"</string> <string name="save_password_remember" msgid="6490888932657708341">"लक्षात ठेवा"</string> <string name="save_password_never" msgid="6776808375903410659">"कधीही नाही"</string> <string name="open_permission_deny" msgid="5136793905306987251">"तुम्हाला हे पृष्ठ उघडण्याची परवानगी नाही."</string> @@ -1038,9 +1040,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"स्पेस"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"एंटर"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"हटवा"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> + <string name="search_go" msgid="2141477624421347086">"शोध"</string> <string name="search_hint" msgid="455364685740251925">"शोधा…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"शोधा"</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> @@ -1467,7 +1469,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट जोडू शकलो नाही."</string> <string name="ime_action_go" msgid="5536744546326495436">"जा"</string> - <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> + <string name="ime_action_search" msgid="4501435960587287668">"शोधा"</string> <string name="ime_action_send" msgid="8456843745664334138">"पाठवा"</string> <string name="ime_action_next" msgid="4169702997635728543">"पुढे"</string> <string name="ime_action_done" msgid="6299921014822891569">"पूर्ण झाले"</string> @@ -1701,9 +1703,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> @@ -1972,7 +1974,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"सुचवलेल्या भाषा"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"सर्व भाषा"</string> <string name="region_picker_section_all" msgid="756441309928774155">"सर्व प्रदेश"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"शोध"</string> <string name="app_suspended_title" msgid="888873445010322650">"अॅप उपलब्ध नाही"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> आत्ता उपलब्ध नाही. हे <xliff:g id="APP_NAME_1">%2$s</xliff:g> कडून व्यवस्थापित केले जाते."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"अधिक जाणून घ्या"</string> @@ -1982,7 +1984,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> @@ -2038,7 +2040,7 @@ <string name="autofill_update_title_with_3types" msgid="1312232153076212291">"हे आयटम "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> मध्ये अपडेट करायचे का?"</string> <string name="autofill_save_yes" msgid="8035743017382012850">"सेव्ह करा"</string> <string name="autofill_save_no" msgid="9212826374207023544">"नाही, नको"</string> - <string name="autofill_save_notnow" msgid="2853932672029024195">"आता नाही"</string> + <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> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 0bf24d7bcc10..2844e1e22f6d 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan cap jari atau kunci skrin anda untuk meneruskan"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kesilapan telah berlaku. Cuba lagi."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon cap jari"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Buka Kunci Wajah"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isu dengan Buka Kunci Wajah"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan wajah atau kunci skrin anda untuk meneruskan"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kesilapan telah berlaku. Cuba lagi."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"membaca tetapan penyegerakan"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Membenarkan apl membaca tetapan segerak untuk akaun. Sebagai contoh, ini boleh menentukan sama ada apl Orang disegerakkan dengan akaun."</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 14409d895099..c2643a56ec68 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ရှေ့ဆက်ရန် သင်၏ လက်ဗွေ (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"လက်ဗွေ သင်္ကေတ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"‘မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း’ ဆိုင်ရာ ပြဿနာ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ရှေ့ဆက်ရန် သင်၏ မျက်နှာ (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string> <string name="face_icon_content_description" msgid="465030547475916280">"မျက်နှာသင်္ကေတ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ထပ်တူပြုအဆင်အပြင်အားဖတ်ခြင်း"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"အပလီကေးရှင်းအား အကောင့်တစ်ခုအတွက် ထပ်တူညီအောင် လုပ်ဆောင်မှု ဆက်တင်အား ကြည့်ခွင့် ပြုပါ။ ဥပမာ People အက်ပ်က အကောင့်တစ်ခုနဲ့ ထပ်တူညီအောင် လုပ်ရန် ဆက်သွယ်ထားမှု ရှိမရှိ သိရှိနိုင်ခြင်း"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index d046447c82c8..0252eb354609 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Bruk fingeravtrykket eller skjermlåsen for å fortsette"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Noe gikk galt. Prøv på nytt."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeravtrykk"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Bruk ansikts- eller skjermlåsen for å fortsette"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Noe gikk galt. Prøv på nytt."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ansiktikon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lese synkroniseringsinnstillinger"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 6da40726d123..fbf40cfa5fb7 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी राख्न आफ्नो फिंगरप्रिन्ट वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिन्ट आइकन"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलक"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलक सुविधामा अनुहार दर्ता गर्ने क्रममा त्रुटि भयो"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी राख्न आफ्नो फेस वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string> <string name="face_icon_content_description" msgid="465030547475916280">"अनुहारको आइकन"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"समीकरण सेटिङहरू पढ्नुहोस्"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"एपलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको एप खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string> diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml index 2e4578c39430..783fabe20a6d 100644 --- a/core/res/res/values-night/colors.xml +++ b/core/res/res/values-night/colors.xml @@ -33,4 +33,6 @@ <color name="call_notification_answer_color">#5DBA80</color> <color name="personal_apps_suspension_notification_color">#8AB4F8</color> + + <color name="overview_background">@color/overview_background_dark</color> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 75857ff45ccb..ef6a441897be 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik je vingerafdruk of schermvergrendeling om door te gaan"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Er is iets misgegaan. Probeer het opnieuw."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ontgrendelen via gezichtsherkenning"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem met Ontgrendelen via gezichtsherkenning"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik je gezicht of schermvergrendeling om door te gaan"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Er is iets misgegaan. Probeer het opnieuw."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Gezichtspictogram"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"synchronisatie-instellingen lezen"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 11d6e7f4cfa1..291c1cc13e88 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ଫେସ୍ ଅନଲକ୍"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ଫେସ୍ ଅନଲକ୍ ସହ ସମସ୍ୟା"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଚେହେରା କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="face_icon_content_description" msgid="465030547475916280">"ଫେସ୍ ଆଇକନ୍"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ସିଙ୍କ ସେଟିଙ୍ଗକୁ ପଢ଼ନ୍ତୁ"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ଏକ ଆକାଉଣ୍ଟ ପାଇଁ ସିଙ୍କ ସେଟିଙ୍ଗ ପଢ଼ିବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଉଦାହରଣସ୍ୱରୂପ, ଲୋକଙ୍କ ଆପ୍ ଏକ ଆକାଉଣ୍ଟରେ ସିଙ୍କ ହୋଇଛି କି ନାହିଁ ଏହା ଜାଣିପାରେ।"</string> @@ -1038,9 +1040,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"ସ୍ପେସ୍"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"ଏଣ୍ଟର୍"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍ କରନ୍ତୁ"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> - <string name="search_hint" msgid="455364685740251925">"ସର୍ଚ୍ଚ…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> + <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_clear" msgid="1989371719192982900">"କ୍ୱେରୀ ଖାଲି କରନ୍ତୁ"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"କ୍ୱେରୀ ଦାଖଲ କରନ୍ତୁ"</string> @@ -1467,7 +1469,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ଜୁମ୍ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଦୁଇଥର ଟାପ୍ କରନ୍ତୁ"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ୱିଜେଟ୍ ଯୋଡ଼ିପାରିବ ନାହିଁ।"</string> <string name="ime_action_go" msgid="5536744546326495436">"ଯାଆନ୍ତୁ"</string> - <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> + <string name="ime_action_search" msgid="4501435960587287668">"ସନ୍ଧାନ କରନ୍ତୁ"</string> <string name="ime_action_send" msgid="8456843745664334138">"ପଠାନ୍ତୁ"</string> <string name="ime_action_next" msgid="4169702997635728543">"ପରବର୍ତ୍ତୀ"</string> <string name="ime_action_done" msgid="6299921014822891569">"ହୋଇଗଲା"</string> @@ -1972,7 +1974,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"ପ୍ରସ୍ତାବିତ"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"ସମସ୍ତ ଭାଷା"</string> <string name="region_picker_section_all" msgid="756441309928774155">"ସମସ୍ତ ଅଞ୍ଚଳ"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"ସନ୍ଧାନ କରନ୍ତୁ"</string> <string name="app_suspended_title" msgid="888873445010322650">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string> <string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 264829636af7..6e5aacf74f56 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -306,7 +306,7 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"ਟਿਕਾਣਾ"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚੋ"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"ਕੈਲੰਡਰ"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ਫ਼ੇਸ ਅਣਲਾਕ"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ਫ਼ੇਸ ਅਣਲਾਕ ਨਾਲ ਸਮੱਸਿਆ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਚਿਹਰਾ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="face_icon_content_description" msgid="465030547475916280">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।"</string> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ਕੰਮ ਦਾ ਮੋਬਾਈਲ"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"ਦਫ਼ਤਰ ਦਾ ਪੇਜਰ"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"ਸਹਾਇਕ"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"ਵਿਉਂਂਤੀ"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"ਜਨਮਦਿਨ"</string> @@ -2008,7 +2010,7 @@ <string name="app_category_image" msgid="7307840291864213007">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਚਿੱਤਰ"</string> <string name="app_category_social" msgid="2278269325488344054">"ਸਮਾਜਕ ਅਤੇ ਸੰਚਾਰ"</string> <string name="app_category_news" msgid="1172762719574964544">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string> - <string name="app_category_maps" msgid="6395725487922533156">"ਨਕਸ਼ੇ ਅਤੇ ਆਵਾਗੌਣ"</string> + <string name="app_category_maps" msgid="6395725487922533156">"Maps ਅਤੇ ਨੈਵੀਗੇਸ਼ਨ"</string> <string name="app_category_productivity" msgid="1844422703029557883">"ਉਤਪਾਦਕਤਾ"</string> <string name="app_category_accessibility" msgid="6643521607848547683">"ਪਹੁੰਚਯੋਗਤਾ"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"ਡੀਵਾਈਸ ਸਟੋਰੇਜ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index c45ac41462ae..2d9160f3e5dc 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> @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aby kontynuować, użyj odcisku palca lub blokady ekranu"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Coś poszło nie tak. Spróbuj ponownie."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odcisku palca"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Rozpoznawanie twarzy"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem z rozpoznawaniem twarzy"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aby kontynuować, użyj rozpoznawania twarzy lub blokady ekranu"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Coś poszło nie tak. Spróbuj ponownie."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona twarzy"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"czytanie ustawień synchronizacji"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Zezwala aplikacji na odczyt ustawień synchronizacji konta. Pozwala to na przykład określić, czy aplikacja Ludzie jest zsynchronizowana z kontem."</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 8198ae939e3b..3d55de4bbf67 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use sua impressão digital ou o bloqueio de tela para continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo deu errado. Tente de novo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo deu errado. Tente de novo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ícone facial"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler as configurações de sincronização"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que o app leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o app People está sincronizado com uma conta."</string> @@ -1938,7 +1940,7 @@ <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string> <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string> <string name="notification_verified_content_description" msgid="6401483602782359391">"Verificada"</string> - <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string> + <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Abrir"</string> <string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Recolher"</string> <string name="expand_action_accessibility" msgid="1947657036871746627">"alternar expansão"</string> <string name="usb_midi_peripheral_name" msgid="490523464968655741">"Porta USB periférica Android"</string> @@ -2037,7 +2039,7 @@ <string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> <string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string> <string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string> - <string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string> + <string name="autofill_save_no" msgid="9212826374207023544">"Agora não"</string> <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string> <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string> <string name="autofill_update_yes" msgid="4608662968996874445">"Atualizar"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 5a336ae237e5..64d28ba50104 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilize a impressão digital ou o bloqueio de ecrã para continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo correu mal. Tente novamente."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilize o rosto ou o bloqueio de ecrã para continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo correu mal. Tente novamente."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ícone de rosto"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler definições de sincronização"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que a app leia as definições de sincronização de uma conta. Por exemplo, pode determinar se a app Pessoas está sincronizada com uma conta."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 8198ae939e3b..3d55de4bbf67 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use sua impressão digital ou o bloqueio de tela para continuar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo deu errado. Tente de novo."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo deu errado. Tente de novo."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ícone facial"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler as configurações de sincronização"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que o app leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o app People está sincronizado com uma conta."</string> @@ -1938,7 +1940,7 @@ <string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string> <string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string> <string name="notification_verified_content_description" msgid="6401483602782359391">"Verificada"</string> - <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string> + <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Abrir"</string> <string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Recolher"</string> <string name="expand_action_accessibility" msgid="1947657036871746627">"alternar expansão"</string> <string name="usb_midi_peripheral_name" msgid="490523464968655741">"Porta USB periférica Android"</string> @@ -2037,7 +2039,7 @@ <string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> <string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string> <string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string> - <string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string> + <string name="autofill_save_no" msgid="9212826374207023544">"Agora não"</string> <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string> <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string> <string name="autofill_update_yes" msgid="4608662968996874445">"Atualizar"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index ae0a62901a94..9fb501c2c413 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Folosiți amprenta sau blocarea ecranului pentru a continua"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"A apărut o eroare. Încercați din nou."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pictograma amprentă"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Deblocare facială"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problemă cu Deblocarea facială"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Folosiți-vă chipul sau blocarea ecranului pentru a continua"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"A apărut o eroare. Încercați din nou."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Pictograma chip"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"citire setări sincronizare"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite aplicației să citească setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicația poate determina dacă aplicația Persoane este sincronizată cu un anumit cont."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 8d3edf1d79e3..c4c69c90b8d0 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Чтобы продолжить, используйте отпечаток пальца или данные для разблокировки экрана."</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Произошла ошибка. Повторите попытку."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок отпечатка пальца"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Фейсконтроль"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Ошибка фейсконтроля"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Чтобы продолжить, посмотрите на экран или используйте данные для разблокировки."</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Произошла ошибка. Повторите попытку."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Значок лица"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"Просмотр настроек синхронизации"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения \"Контакты\"."</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 132ee6f261c7..fd2e43bed403 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ඉදිරියට යාමට ඔබගේ ඇඟිලි සලකුණ හෝ තිර අගුල භාවිත කරන්න"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"මුහුණෙන් අගුළු හැරීම"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"මුහුණෙන් අගුලු හැරීම සම්බන්ධව ගැටලුවකි"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ඉදිරියට යාමට ඔබගේ මුහුණු හෝ තිර අගුල භාවිත කරන්න"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string> <string name="face_icon_content_description" msgid="465030547475916280">"මුහුණ නිරූපකය"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"සමමුහුර්ත සැකසීම් කියවන්න"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ගිණුම සඳහා සමමුහුර්ත සැකසීම් කියවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස, ගිණුමක් සමඟ පුද්ගල යෙදුම සමමුහුර්ත දැයි මෙයට හඳුනා ගත හැක."</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 67b0ce0d50b1..c862bc269dcf 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -322,7 +322,7 @@ <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nahrávanie zvuku"</string> <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Fyzická aktivita"</string> <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"prístup k vašej fyzickej aktivite"</string> - <string name="permgrouplab_camera" msgid="9090413408963547706">"Fotoaparát"</string> + <string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string> <string name="permgroupdesc_camera" msgid="7585150538459320326">"fotenie a natáčanie videí"</string> <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Zariadenia v okolí"</string> <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"objavovať a pripájať zariadenia v okolí"</string> @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte použitím odtlačku prsta alebo zámky obrazovky"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Vyskytla sa chyba. Skúste to znova."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odtlačku prsta"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odomknutie tvárou"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odomknutím tvárou"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte použitím tváre alebo zámky obrazovky"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Vyskytla sa chyba. Skúste to znova."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona tváre"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čítať nastavenia synchronizácie"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index d632e0c53b6f..9df733fd9be6 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nadaljevanje uporabite prstni odtis ali odklepanje s poverilnico."</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Prišlo je do napake. Poskusite znova."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona prstnih odtisov"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odklepanje z obrazom"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Težava z odklepanjem z obrazom"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nadaljevanje uporabite obraz ali odklepanje s poverilnico."</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Prišlo je do napake. Poskusite znova."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona obraza"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"branje nastavitev sinhronizacije"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogoča branje nastavitev sinhronizacije za račun. S tem lahko aplikacija na primer ugotovi, ali je aplikacija Ljudje sinhronizirana z računom."</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 239c9f8709da..44c820a8a7f5 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Përdor gjurmën tënde të gishtit ose kyçjen e ekranit për të vazhduar"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Ndodhi një gabim. Provo sërish."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona e gjurmës së gishtit"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Shkyçja me fytyrë"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem me \"Shkyçjen me fytyrë\""</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Përdor fytyrën tënde ose kyçjen e ekranit për të vazhduar"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Ndodhi një gabim. Provo sërish."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ikona e fytyrës"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lexo cilësimet e sinkronizimit"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lejon aplikacionin të lexojë cilësimet e sinkronizimit për një llogari. Për shembull, kjo mund të përcaktojë nëse aplikacioni \"Kontaktet\" është i sinkronizuar me një llogari."</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index cd03394c58d4..911ba91d058e 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -612,6 +612,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користите отисак прста или закључавање екрана да бисте наставили"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Дошло је до проблема. Пробајте поново."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона отиска прста"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Откључавање лицем"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем са откључавање лицем"</string> @@ -664,6 +665,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користите лице или закључавање екрана да бисте наставили"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Дошло је до проблема. Пробајте поново."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Икона лица"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"читање подешавања синхронизације"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дозвољава апликацији да чита подешавања синхронизације за налог. На пример, овако може да се утврди да ли је апликација Људи синхронизована са налогом."</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 940ee568228d..3c388f6cd308 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Fortsätt med hjälp av ditt fingeravtryck eller skärmlåset"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Något gick fel. Försök igen."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon för fingeravtryck"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Fortsätt med hjälp av ditt ansikte eller skärmlåset"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Något gick fel. Försök igen."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Ansikte"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"läsa synkroniseringsinställningar"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillåter att appen läser synkroniseringsinställningarna för ett konto. Detta kan användas till exempel för att avgöra om appen Personer är synkroniserad med ett konto."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index fbee2c3d8ff8..eb679ff6fa1e 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Tumia alama ya kidole au mbinu yako ya kufunga skrini ili uendelee"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Hitilafu fulani imetokea. Jaribu tena."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Aikoni ya alama ya kidole"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kufungua kwa Uso"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Hitilafu imetokea kwenye kipengele cha Kufungua kwa Uso"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Tumia uso au mbinu yako ya kufunga skrini ili uendelee"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Hitilafu fulani imetokea. Jaribu tena."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Aikoni ya uso"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"kusoma mipangilio ya usawazishaji"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 4a5be62120f6..398f60614395 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -100,7 +100,7 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"TTY Mode HCOஐ இணைச் செயல்பாடு கோரியது"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"TTY Mode VCOஐ இணைச் செயல்பாடு கோரியது"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"TTY Mode OFFஐ இணைச் செயல்பாடு கோரியது"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"குரல்"</string> <string name="serviceClassData" msgid="4148080018967300248">"தரவு"</string> <string name="serviceClassFAX" msgid="2561653371698904118">"தொலைநகல்"</string> <string name="serviceClassSMS" msgid="1547664561704509004">"SMS"</string> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"தொடர, உங்கள் கைரேகையையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"கைரேகை ஐகான்"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"முகம் காட்டித் திறத்தல்"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"முகம் காட்டித் திறத்தல் அம்சத்தில் சிக்கல்"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"தொடர, உங்கள் முகத்தையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string> <string name="face_icon_content_description" msgid="465030547475916280">"முக ஐகான்"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க ஆப்ஸை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் ஆப்ஸ் கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string> @@ -815,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"பணியிட மொபைல்"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"பணியிட பேஜர்"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"உதவியாளர்"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"பிரத்தியேகம்"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"பிறந்தநாள்"</string> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"மற்றவை"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"பிரத்தியேகம்"</string> <string name="relationTypeCustom" msgid="282938315217441351">"பிரத்தியேகம்"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"உதவியாளர்"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"சகோதரர்"</string> <string name="relationTypeChild" msgid="9076258911292693601">"குழந்தை"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"வாழ்வுத் துணை"</string> @@ -2108,7 +2110,7 @@ <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"மொபைலில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"டேப்லெட்டில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"சாதனத்தில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string> - <string name="mime_type_folder" msgid="2203536499348787650">"கோப்புறை"</string> + <string name="mime_type_folder" msgid="2203536499348787650">"ஃபோல்டர்"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android ஆப்ஸ்"</string> <string name="mime_type_generic" msgid="4606589110116560228">"ஃபைல்"</string> <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> ஃபைல்"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 08bf970fb5ab..159c0e3a8f78 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -71,16 +71,16 @@ <string name="RuacMmi" msgid="1876047385848991110">"అవాంఛిత అంతరాయ కాల్స్ల తిరస్కరణ"</string> <string name="CndMmi" msgid="185136449405618437">"కాలింగ్ నంబర్ బట్వాడా"</string> <string name="DndMmi" msgid="8797375819689129800">"అంతరాయం కలిగించవద్దు"</string> - <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"కాలర్ ID డిఫాల్ట్గా పరిమితానికి ఉంటుంది. తర్వాత కాల్: పరిమితం చేయబడింది"</string> - <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"కాలర్ ID డిఫాల్ట్గా పరిమితానికి ఉంటుంది. తర్వాత కాల్: అపరిమితం"</string> - <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"కాలర్ ID డిఫాల్ట్గా అపరిమితానికి ఉంటుంది. తర్వాత కాల్: పరిమితం చేయబడింది"</string> - <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"కాలర్ ID డిఫాల్ట్గా అపరిమితానికి ఉంటుంది. తర్వాత కాల్: అపరిమితం"</string> + <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"కాలర్ ID ఆటోమేటిక్లపై పరిమితి ఉంటుంది. తర్వాత కాల్: పరిమితి ఉంటుంది"</string> + <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"కాలర్ ID ఆటోమేటిక్లపై పరిమితి ఉంటుంది. తర్వాత కాల్: పరిమితి లేదు"</string> + <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"కాలర్ ID ఆటోమేటిక్లపై పరిమితి లేదు. తర్వాత కాల్: పరిమితి ఉంటుంది"</string> + <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"కాలర్ ID ఆటోమేటిక్లపై పరిమితి లేదు. తర్వాత కాల్: పరిమితి లేదు"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"సేవ కేటాయించబడలేదు."</string> <string name="CLIRPermanent" msgid="166443681876381118">"మీరు కాలర్ ID సెట్టింగ్ను మార్చలేరు."</string> <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"మొబైల్ డేటా సేవ లేదు"</string> <string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"అత్యవసర కాలింగ్ అందుబాటులో లేదు"</string> - <string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"వాయిస్ సేవ లేదు"</string> - <string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"వాయిస్ సేవ లేదా అత్యవసర కాలింగ్ లేదు"</string> + <string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"వాయిస్ సర్వీస్ లేదు"</string> + <string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"వాయిస్ సర్వీస్ లేదా ఎమర్జెన్సీ కాలింగ్ లేదు"</string> <string name="RestrictedStateContent" msgid="7693575344608618926">"మీ క్యారియర్ తాత్కాలికంగా ఆఫ్ చేయబడింది"</string> <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> కోసం మీ క్యారియర్ తాత్కాలికంగా ఆఫ్ చేశారు"</string> <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు"</string> @@ -100,12 +100,12 @@ <string name="peerTtyModeHco" msgid="5626377160840915617">"అవతలి వారు HCO TTY మోడ్ని అభ్యర్థించారు"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"అవతలి వారు VCO TTY మోడ్ని అభ్యర్థించారు"</string> <string name="peerTtyModeOff" msgid="2420380956369226583">"అవతలి వారు OFF TTY మోడ్ని అభ్యర్థించారు"</string> - <string name="serviceClassVoice" msgid="2065556932043454987">"Voice"</string> + <string name="serviceClassVoice" msgid="2065556932043454987">"వాయిస్"</string> <string name="serviceClassData" msgid="4148080018967300248">"డేటా"</string> <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> @@ -124,7 +124,7 @@ <string name="roamingTextSearching" msgid="5323235489657753486">"సేవ కోసం శోధిస్తోంది"</string> <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Wi‑Fi కాలింగ్ని సెటప్ చేయడం సాధ్యపడలేదు"</string> <string-array name="wfcOperatorErrorAlertMessages"> - <item msgid="468830943567116703">"Wi-Fiతో కాల్స్ను చేయడానికి మరియు మెసేజ్లను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్కి చెప్పండి. ఆ తర్వాత సెట్టింగ్ల నుండి Wi-Fi కాలింగ్ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="468830943567116703">"Wi-Fiతో కాల్స్ను చేయడానికి, మెసేజ్లను పంపించడానికి, ముందుగా ఈ సర్వీస్ను సెటప్ చేయాల్సిందిగా మీ క్యారియర్ను అడగండి. ఆ తర్వాత సెట్టింగ్ల నుండి Wi-Fi కాలింగ్ను మళ్లీ ఆన్ చేయండి. (ఎర్రర్ కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> <item msgid="4795145070505729156">"మీ క్యారియర్తో Wi‑Fi కాలింగ్ని నమోదు చేయడంలో సమస్య: <xliff:g id="CODE">%1$s</xliff:g>"</item> @@ -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> @@ -305,17 +305,17 @@ <string name="permgrouplab_contacts" msgid="4254143639307316920">"కాంటాక్ట్లు"</string> <string name="permgroupdesc_contacts" msgid="9163927941244182567">"మీ కాంటాక్ట్లను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"లొకేషన్"</string> - <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర లొకేషన్ను యాక్సెస్ చేయడానికి"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"క్యాలెండర్"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్ను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> - <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS మెసేజ్లను పంపడం మరియు వీక్షించడం"</string> + <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS మెసేజ్లను పంపడం, వీక్షించడం"</string> <string name="permgrouplab_storage" msgid="1938416135375282333">"ఫైల్స్, మీడియా"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైళ్లను యాక్సెస్ చేయడానికి"</string> <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,33 +349,33 @@ <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> <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"ఇన్కమింగ్ ఫోన్ కాల్స్కు సమాధానమివ్వడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_receiveSms" msgid="505961632050451881">"వచన మెసేజ్లను (SMS) స్వీకరించడం"</string> - <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> - <string name="permlab_receiveMms" msgid="4000650116674380275">"వచన మెసేజ్లను (MMS) స్వీకరించడం"</string> - <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> + <string name="permlab_receiveSms" msgid="505961632050451881">"టెక్స్ట్ మెసేజ్లను (SMS) స్వీకరించడం"</string> + <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. మీ డివైజ్కు వచ్చిన మెసేజ్లను మీకు చూపకుండానే యాప్ పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> + <string name="permlab_receiveMms" msgid="4000650116674380275">"టెక్స్ట్ మెసేజ్లను (MMS) స్వీకరించడం"</string> + <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. మీ డివైజ్కు వచ్చిన మెసేజ్లను మీకు చూపకుండానే యాప్ పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార మెసేజ్లను ఫార్వర్డ్ చేయడం"</string> - <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార మెసేజ్లను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండటానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> + <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార మెసేజ్లను స్వీకరించినప్పుడు, వాటిని ఫార్వర్డ్ చేయడానికి సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండేందుకు యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string> <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"కొనసాగుతున్న కాల్స్ను మేనేజ్ చేయి"</string> <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"మీ పరికరంలో కొనసాగుతున్న కాల్స్ను చూడటానికి అలాగే వాటిని కంట్రోల్ చేయడానికి ఒక యాప్కు అనుమతిస్తోంది."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"సెల్ ప్రసార మెసేజ్లను చదవడం"</string> - <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార మెసేజ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> + <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార మెసేజ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్లను చదవడం"</string> <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్ల గురించి వివరాలను పొందడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_sendSms" msgid="7757368721742014252">"SMS మెసేజ్లను పంపడం మరియు వీక్షించడం"</string> + <string name="permlab_sendSms" msgid="7757368721742014252">"SMS మెసేజ్లను పంపడం, వీక్షించడం"</string> <string name="permdesc_sendSms" msgid="6757089798435130769">"SMS మెసేజ్లు పంపడానికి యాప్ను అనుమతిస్తుంది. దీని వలన ఊహించని ఛార్జీలు విధించబడవచ్చు. హానికరమైన యాప్లు మీ నిర్ధారణ లేకుండానే మెసేజ్లను పంపడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> - <string name="permlab_readSms" msgid="5164176626258800297">"మీ వచన మెసేజ్లు (SMS లేదా MMS) చదవడం"</string> - <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ఈ యాప్ మీ టాబ్లెట్లో నిల్వ చేసిన అన్ని SMS (వచన) మెసేజ్లను చదవగలదు."</string> - <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ఈ యాప్ మీ Android TV పరికరంలో నిల్వ అయిన SMS (వచనం) సందేశాలన్నింటినీ చదవగలదు."</string> - <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన అన్ని SMS (వచన) మెసేజ్లను చదవగలదు."</string> - <string name="permlab_receiveWapPush" msgid="4223747702856929056">"వచన మెసేజ్లను (WAP) స్వీకరించడం"</string> - <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> + <string name="permlab_readSms" msgid="5164176626258800297">"మీ టెక్స్ట్ మెసేజ్లు (SMS లేదా MMS) చదవడం"</string> + <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ఈ యాప్ మీ టాబ్లెట్లో స్టోర్ చేసిన అన్ని SMS (టెక్స్ట్) మెసేజ్లను చదవగలదు."</string> + <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ఈ యాప్ మీ Android TV పరికరంలో స్టోర్ అయిన SMS (టెక్స్ట్) మెసేజ్లు అన్నింటిని చదవగలదు."</string> + <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన అన్ని SMS (టెక్స్ట్) మెసేజ్లను చదవగలదు."</string> + <string name="permlab_receiveWapPush" msgid="4223747702856929056">"టెక్స్ట్ మెసేజ్లను (WAP) స్వీకరించడం"</string> + <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీకు వచ్చిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> <string name="permlab_getTasks" msgid="7460048811831750262">"అమలవుతున్న యాప్లను పునరుద్ధరించడం"</string> <string name="permdesc_getTasks" msgid="7388138607018233726">"ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి యాప్ను అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన యాప్ల గురించి సమాచారాన్ని కనుగొనడానికి యాప్ను అనుమతించవచ్చు."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"ప్రొఫైల్ మరియు పరికర యజమానులను నిర్వహించడం"</string> @@ -410,11 +410,11 @@ <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన టాబ్లెట్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్ని అనుమతిస్తుంది. ఎక్కువగా వినియోగిస్తే అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన టీవీ నెమ్మదిగా పని చేయవచ్చు లేదా అస్థిరంగా మారవచ్చు."</string> <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన ఫోన్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> - <string name="permlab_readContacts" msgid="8776395111787429099">"మీ పరిచయాలను చదవడం"</string> + <string name="permlab_readContacts" msgid="8776395111787429099">"మీ కాంటాక్ట్లను చదవడం"</string> <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"టాబ్లెట్లో నిల్వ చేసిన మీ కాంటాక్ట్లకు సంబంధించిన డేటాను చదవడానికి యాప్ను అనుమతిస్తుంది. కాంటాక్ట్లను సృష్టించిన మీ టాబ్లెట్లోని ఖాతాలకు కూడా యాప్లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్లను అనుమతిస్తుంది, హానికరమైన యాప్లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string> <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"మీ Android TV పరికరంలో నిల్వ చేసిన కాంటాక్ట్లకు సంబంధించిన డేటాను చదవడానికి యాప్ను అనుమతిస్తుంది. కాంటాక్ట్లను సృష్టించిన మీ Android TV పరికరంలోని ఖాతాలకు కూడా యాప్లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్లను అనుమతిస్తుంది, హానికరమైన యాప్లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string> <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ఫోన్లో నిల్వ చేసిన మీ కాంటాక్ట్లకు సంబంధించిన డేటాను చదవడానికి యాప్ను అనుమతిస్తుంది. కాంటాక్ట్లను సృష్టించిన మీ ఫోన్లోని ఖాతాలను కూడా యాప్లు యాక్సెస్ చేయగలవు. ఇందులో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్లను అనుమతిస్తుంది, హానికరమైన యాప్లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string> - <string name="permlab_writeContacts" msgid="8919430536404830430">"మీ పరిచయాలను సవరించడం"</string> + <string name="permlab_writeContacts" msgid="8919430536404830430">"మీ కాంటాక్ట్లను సవరించడం"</string> <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"మీ టాబ్లెట్లో నిల్వ చేసి ఉన్న కాంటాక్ట్లకు సంబంధించిన డేటాను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్లను అనుమతిస్తుంది."</string> <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"మీ Android TV పరికరంలో నిల్వ చేసి ఉన్న కాంటాక్ట్లకు సంబంధించిన డేటాను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్లను అనుమతిస్తుంది."</string> <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"మీ ఫోన్లో నిల్వ చేసి ఉన్న కాంటాక్ట్లకు సంబంధించిన డేటాను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్లను అనుమతిస్తుంది."</string> @@ -431,16 +431,16 @@ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ఈ యాప్ మీ Android TV పరికరంలో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు, మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> <string name="permlab_writeCalendar" msgid="6422137308329578076">"యజమానికి తెలియకుండానే క్యాలెండర్ ఈవెంట్లను జోడించి లేదా సవరించి, అతిథులకు ఇమెయిల్ పంపడం"</string> - <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడం"</string> - <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర స్థాన మూలాల నిర్వహణలో యాప్ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string> - <string name="permlab_accessFineLocation" msgid="6426318438195622966">"స్క్రీన్పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన స్థానాన్ని యాక్సెస్ చేయండి"</string> + <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> + <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> + <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు, లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> + <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్లను యాక్సెస్ చేయడం"</string> + <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర లొకేషన్ సోర్స్ల నిర్వహణలో యాప్ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string> + <string name="permlab_accessFineLocation" msgid="6426318438195622966">"స్క్రీన్పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన లొకేషన్ను యాక్సెస్ చేయండి"</string> <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"యాప్ ఉపయోగంలో ఉన్నప్పుడు మాత్రమే ఈ యాప్ మీ ఖచ్చితమైన లొకేషన్ను లొకేషన్ సర్వీస్ల ద్వారా తెలుసుకోగలదు. లొకేషన్ను యాప్ పొందాలంటే, దాని కోసం మీ పరికరం యొక్క లొకేషన్ సర్వీస్లను తప్పనిసరిగా ఆన్ చేయాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string> <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"స్క్రీన్పై ఉన్నప్పుడు మాత్రమే సుమారు లొకేషన్ను యాక్సెస్ చేయండి"</string> <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"యాప్ ఉపయోగంలో ఉన్నప్పుడు మాత్రమే ఈ యాప్ మీ ఇంచుమించు లొకేషన్ను లొకేషన్ సర్వీస్ల నుండి తెలుసుకోగలదు. లొకేషన్ను యాప్ పొందాలంటే, దాని కోసం మీ పరికరం యొక్క లొకేషన్ సర్వీస్లను తప్పనిసరిగా ఆన్ చేయాలి."</string> - <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"నేపథ్యంలో స్థానాన్ని యాక్సెస్ చేయి"</string> + <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"బ్యాక్గ్రౌండ్లో లొకేషన్ను యాక్సెస్ చేయి"</string> <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"యాప్ ఉపయోగంలో లేనప్పటికీ కూడా, ఈ యాప్, లొకేషన్ను ఎప్పుడైనా యాక్సెస్ చేయగలదు."</string> <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"మీ ఆడియో సెట్టింగ్లను మార్చడం"</string> <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"వాల్యూమ్ మరియు అవుట్పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్లను సవరించడానికి యాప్ను అనుమతిస్తుంది."</string> @@ -453,9 +453,9 @@ <string name="permlab_activityRecognition" msgid="1782303296053990884">"భౌతిక కార్యాకలాపాన్ని గుర్తించండి"</string> <string name="permdesc_activityRecognition" msgid="8667484762991357519">"ఈ యాప్ మీ భౌతిక కార్యాకలాపాన్ని గుర్తించగలదు."</string> <string name="permlab_camera" msgid="6320282492904119413">"చిత్రాలు మరియు వీడియోలు తీయడం"</string> - <string name="permdesc_camera" msgid="5240801376168647151">"యాప్ ఉపయోగంలో ఉన్నపుడు కెమెరాను ఉపయోగించి ఈ యాప్ ఎప్పుడైనా ఫోటోలను తీయగలదు, వీడియోలను రికార్డ్ చేయగలదు."</string> + <string name="permdesc_camera" msgid="5240801376168647151">"యాప్ ఉపయోగంలో ఉన్నపుడు కెమెరాను ఉపయోగించి ఎప్పుడు కావాలంటే అప్పుడు ఈ యాప్ ఫోటోలు తీయగలదు, వీడియోలు రికార్డ్ చేయగలదు."</string> <string name="permlab_backgroundCamera" msgid="7549917926079731681">"బ్యాక్గ్రౌండ్లో ఫోటోలు, వీడియోలను తీయగలదు"</string> - <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"కెమెరాను ఉపయోగించి ఈ యాప్ ఎప్పుడైనా ఫోటోలను తీయగలదు, వీడియోలను రికార్డ్ చేయగలదు."</string> + <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"ఈ యాప్, కెమెరాను ఉపయోగించి ఎప్పుడు కావాలంటే అప్పుడు ఫోటోలు తీయగలదు, వీడియోలు రికార్డ్ చేయగలదు."</string> <string name="permlab_systemCamera" msgid="3642917457796210580">"ఫోటోలు, వీడియోలు తీయడానికి సిస్టమ్ కెమెరాలకు యాప్, లేదా సేవా యాక్సెస్ను అనుమతించండి"</string> <string name="permdesc_systemCamera" msgid="5938360914419175986">"ఈ విశేష లేదా సిస్టమ్ యాప్ ఎప్పుడైనా సిస్టమ్ కెమెరాను ఉపయోగించి ఫోటోలు తీయగలదు, వీడియోలను రికార్డ్ చేయగలదు. యాప్కు android.permission.CAMERA అనుమతి ఇవ్వడం కూడా అవసరం"</string> <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"కెమెరా పరికరాలు తెరుచుకుంటున్నప్పుడు లేదా మూసుకుంటున్నప్పుడు కాల్బ్యాక్లను స్వీకరించడానికి యాప్ను లేదా సర్వీస్ను అనుమతించండి."</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,14 +555,14 @@ <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> + <string name="permlab_mediaLocation" msgid="7368098373378598066">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవండి"</string> + <string name="permdesc_mediaLocation" msgid="597912899423578138">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="biometric_app_setting_name" msgid="3339209978734534457">"బయోమెట్రిక్స్ను ఉపయోగించండి"</string> <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"బయోమెట్రిక్స్ను లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"ఇది మీరేనని వెరిఫై చేసుకోండి"</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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"కొనసాగించడానికి మీ వేలిముద్ర లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ఫేస్ అన్లాక్"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ఫేస్ అన్లాక్తో సమస్య"</string> @@ -645,7 +646,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> @@ -661,16 +662,17 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"కొనసాగించడానికి మీ ముఖం లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string> <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> @@ -848,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"ఇతరం"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"అనుకూలం"</string> <string name="relationTypeCustom" msgid="282938315217441351">"అనుకూలం"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"అసిస్టెంట్"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"సోదరుడు"</string> <string name="relationTypeChild" msgid="9076258911292693601">"బిడ్డ"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"జీవిత భాగస్వామి"</string> @@ -916,12 +918,12 @@ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"మీరు మీ అన్లాక్ నమూనాని <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విజయవంతం కాని ప్రయత్నాల తర్వాత, మీరు మీ Google సైన్ఇన్ను ఉపయోగించి మీ టాబ్లెట్ను అన్లాక్ చేయడానికి అడగబడతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"మీరు మీ అన్లాక్ నమూనాని <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీరు మీ Google సైన్ఇన్ను ఉపయోగించి మీ Android TV పరికరాన్ని అన్లాక్ చేయాల్సిందిగా మీకు తెలపబడుతుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"మీరు మీ అన్లాక్ నమూనాని <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విజయవంతం కాని ప్రయత్నాల తర్వాత, మీరు మీ Google సైన్ఇన్ను ఉపయోగించి మీ ఫోన్ను అన్లాక్ చేయడానికి అడగబడతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> వైఫల్య ప్రయత్నాల తర్వాత, టాబ్లెట్ ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది మరియు మొత్తం వినియోగదారు డేటాను కోల్పోవడం సంభవిస్తుంది."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీ Android TV పరికరం ఫ్యాక్టరీ డిఫాల్ట్కి రీసెట్ చేయబడుతుంది, అలాగే వినియోగదారు డేటా మొత్తాన్ని కోల్పోతారు."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> వైఫల్య ప్రయత్నాల తర్వాత, ఫోన్ ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది మరియు మొత్తం వినియోగదారు డేటాను కోల్పోవడం సంభవిస్తుంది."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. టాబ్లెట్ ఇప్పుడు ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, టాబ్లెట్ ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే మొత్తం యూజర్ డేటాను కోల్పోతారు."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీ Android TV పరికరం ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే యూజర్ డేటా మొత్తాన్ని కోల్పోతారు."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఫోన్, ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే మొత్తం యూజర్ డేటాను కోల్పోతారు."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. టాబ్లెట్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది."</string> <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మీ Android TV పరికరం ఇప్పుడు ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. ఫోన్ ఇప్పుడు ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. ఫోన్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది."</string> <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"నమూనాను మర్చిపోయారా?"</string> <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"ఖాతా అన్లాక్"</string> @@ -1006,15 +1008,15 @@ <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"మీ వెబ్ బుక్మార్క్లు మరియు చరిత్రను చదవడం"</string> <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"బ్రౌజర్ సందర్శించిన అన్ని URLల చరిత్ర గురించి మరియు అన్ని బ్రౌజర్ బుక్మార్క్ల గురించి చదవడానికి యాప్ను అనుమతిస్తుంది. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"వెబ్ బుక్మార్క్లు మరియు చరిత్రను వ్రాయడం"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"మీ టాబ్లెట్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"మీ టాబ్లెట్లో నిల్వ చేయబడిన బ్రౌజర్ హిస్టరీని, బుక్మార్క్లను ఎడిట్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా ఎడిట్ చేయడానికి యాప్ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతిని థర్డ్ పార్టీ బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్లు అమలు చేయకపోవచ్చు."</string> <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"మీ Android TV పరికరంలో నిల్వ చేసిన బ్రౌజర్ చరిత్ర లేదా బుక్మార్క్లను సవరించడానికి యాప్ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను తీసివేయడానికి లేదా సవరించడానికి యాప్ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ-పక్ష బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు కాకపోవచ్చు."</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"మీ ఫోన్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> <string name="permlab_setAlarm" msgid="1158001610254173567">"అలారం సెట్ చేయడం"</string> <string name="permdesc_setAlarm" msgid="2185033720060109640">"ఇన్స్టాల్ చేయబడిన అలారం గడియారం యాప్లో అలారంను సెట్ చేయడానికి యాప్ను అనుమతిస్తుంది. కొన్ని అలారం గల గడియారం యాప్లు ఈ ఫీచర్ను అమలు చేయకపోవచ్చు."</string> <string name="permlab_addVoicemail" msgid="4770245808840814471">"వాయిస్ మెయిల్ను జోడించడం"</string> - <string name="permdesc_addVoicemail" msgid="5470312139820074324">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కి మెసేజ్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permdesc_addVoicemail" msgid="5470312139820074324">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కు మెసేజ్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"బ్రౌజర్ భౌగోళిక స్థానం అనుమతులను సవరించడం"</string> - <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"బ్రౌజర్ యొక్క భౌగోళిక స్థానం అనుమతులను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు ఏకపక్ష వెబ్ సైట్లకు స్థాన సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string> + <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"బ్రౌజర్ యొక్క భౌగోళిక లొకేషన్ అనుమతులను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు ఏకపక్ష వెబ్ సైట్లకు లొకేషన్ సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string> <string name="save_password_message" msgid="2146409467245462965">"మీరు బ్రౌజర్ ఈ పాస్వర్డ్ను గుర్తుపెట్టుకోవాలని కోరుకుంటున్నారా?"</string> <string name="save_password_notnow" msgid="2878327088951240061">"ఇప్పుడు కాదు"</string> <string name="save_password_remember" msgid="6490888932657708341">"గుర్తుంచుకో"</string> @@ -1039,15 +1041,15 @@ <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"delete"</string> <string name="search_go" msgid="2141477624421347086">"సెర్చ్"</string> - <string name="search_hint" msgid="455364685740251925">"వెతుకు..."</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="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"> @@ -1197,7 +1199,7 @@ <string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$sతో సవరించు"</string> <string name="whichEditApplicationLabel" msgid="1463288652070140285">"సవరించు"</string> <string name="whichSendApplication" msgid="4143847974460792029">"షేర్ చేయండి"</string> - <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$sతో భాగస్వామ్యం చేయి"</string> + <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$sతో షేర్ చేయండి"</string> <string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయి"</string> <string name="whichSendToApplication" msgid="77101541959464018">"దీన్ని ఉపయోగించి పంపండి"</string> <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$sని ఉపయోగించి పంపండి"</string> @@ -1208,9 +1210,9 @@ <string name="whichImageCaptureApplication" msgid="2737413019463215284">"దీనితో చిత్రాన్ని క్యాప్చర్ చేయి"</string> <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"%1$sతో చిత్రాన్ని క్యాప్చర్ చేయండి"</string> <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"చిత్రాన్ని క్యాప్చర్ చేయి"</string> - <string name="alwaysUse" msgid="3153558199076112903">"ఈ చర్యకు డిఫాల్ట్గా ఉపయోగించండి."</string> + <string name="alwaysUse" msgid="3153558199076112903">"ఈ చర్యకు ఆటోమేటిక్గా ఉపయోగించండి."</string> <string name="use_a_different_app" msgid="4987790276170972776">"వేరొక యాప్ను ఉపయోగించండి"</string> - <string name="clearDefaultHintMsg" msgid="1325866337702524936">"సిస్టమ్ సెట్టింగ్లు > యాప్లు > డౌన్లోడ్ చేయబడినవిలో డిఫాల్ట్ను క్లియర్ చేయి."</string> + <string name="clearDefaultHintMsg" msgid="1325866337702524936">"సిస్టమ్ సెట్టింగ్లు > యాప్లు > డౌన్లోడ్ చేయబడినవిలో ఆటోమేటిక్ను క్లియర్ చేయి."</string> <string name="chooseActivity" msgid="8563390197659779956">"చర్యను ఎంచుకోండి"</string> <string name="chooseUsbActivity" msgid="2096269989990986612">"USB పరికరం కోసం యాప్ను ఎంచుకోండి"</string> <string name="noApplications" msgid="1186909265235544019">"ఈ చర్యను అమలు చేయగల యాప్లు ఏవీ లేవు."</string> @@ -1274,7 +1276,7 @@ <string name="dump_heap_notification" msgid="5316644945404825032">"<xliff:g id="PROC">%1$s</xliff:g> మెమరీ పరిమితిని మించిపోయింది"</string> <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> హీప్ డంప్ సిద్ధంగా ఉంది"</string> <string name="dump_heap_notification_detail" msgid="8431586843001054050">"కుప్పలు తెప్పలుగా సేకరించబడింది. షేర్ చేయడానికి నొక్కండి"</string> - <string name="dump_heap_title" msgid="4367128917229233901">"హీప్ డంప్ను భాగస్వామ్యం చేయాలా?"</string> + <string name="dump_heap_title" msgid="4367128917229233901">"హీప్ డంప్ను షేర్ చేయాలా?"</string> <string name="dump_heap_text" msgid="1692649033835719336">"ఈ <xliff:g id="PROC">%1$s</xliff:g> ప్రాసెస్ దీని మెమరీ పరిమితి అయిన <xliff:g id="SIZE">%2$s</xliff:g>ని మించిపోయింది. మీరు దీని డెవలపర్తో షేర్ చేయడానికి హీప్ డంప్ అందుబాటులో ఉంది. జాగ్రత్త: ఈ హీప్ డంప్లో అప్లికేషన్ యాక్సెస్ కలిగి ఉన్న మీ వ్యక్తిగత సమాచారం ఏదైనా ఉండవచ్చు."</string> <string name="dump_heap_system_text" msgid="6805155514925350849">"ఈ <xliff:g id="PROC">%1$s</xliff:g> ప్రాసెస్ దాని మెమరీ పరిమితి <xliff:g id="SIZE">%2$s</xliff:g>ని మించిపోయింది. మీరు షేర్ చేయడానికి హీప్ డంప్ అందుబాటులో ఉంది. జాగ్రత్త: ఈ హీప్ డంప్ ప్రాసెస్ విధానంలో గోప్యమైన వ్యక్తిగత సమాచారం యాక్సెస్ చేసే అవకాశం ఉంది, వీటిలో మీరు టైప్ చేసే అంశాలు కూడా ఉండవచ్చు."</string> <string name="dump_heap_ready_text" msgid="5849618132123045516">"మీరు షేర్ చేయదలుచుకున్న <xliff:g id="PROC">%1$s</xliff:g> యొక్క హీప్ డంప్ ప్రాసెస్ విధానం అందుబాటులో ఉంది. జాగ్రత్త: ఈ హీప్ డంప్ ప్రాసెస్ విధానంలో గోప్యమైన వ్యక్తిగత సమాచారం యాక్సెస్ చేసే అవకాశం ఉంది, వీటిలో మీరు టైప్ చేసే అంశాలు కూడా ఉండవచ్చు."</string> @@ -1293,7 +1295,7 @@ <string name="volume_icon_description_incall" msgid="4491255105381227919">"కాల్ వాల్యూమ్"</string> <string name="volume_icon_description_media" msgid="4997633254078171233">"మీడియా వాల్యూమ్"</string> <string name="volume_icon_description_notification" msgid="579091344110747279">"నోటిఫికేషన్ వాల్యూమ్"</string> - <string name="ringtone_default" msgid="9118299121288174597">"డిఫాల్ట్ రింగ్టోన్"</string> + <string name="ringtone_default" msgid="9118299121288174597">"ఆటోమేటిక్ రింగ్టోన్"</string> <string name="ringtone_default_with_actual" msgid="2709686194556159773">"ఆటోమేటిక్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> <string name="ringtone_silent" msgid="397111123930141876">"ఏదీ వద్దు"</string> <string name="ringtone_picker_title" msgid="667342618626068253">"రింగ్టోన్లు"</string> @@ -1385,9 +1387,9 @@ <string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB పోర్ట్ను ఉపయోగించడం సురక్షితం"</string> <string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"ఫోన్ ఇకపై ద్రవ లేదా వ్యర్థ పదార్థాలను గుర్తించదు."</string> <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"బగ్ రిపోర్ట్ను తీస్తోంది…"</string> - <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ రిపోర్ట్ను భాగస్వామ్యం చేయాలా?"</string> - <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్ను భాగస్వామ్యం చేస్తోంది..."</string> - <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్ను అభ్యర్థించారు. యాప్లు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string> + <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ రిపోర్ట్ను షేర్ చేయాలా?"</string> + <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్ను షేర్ చేస్తోంది..."</string> + <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ అడ్మిన్ ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్ను రిక్వెస్ట్ చేశారు. యాప్లు మరియు డేటా షేర్ చేయబడవచ్చు."</string> <string name="share_remote_bugreport_action" msgid="7630880678785123682">"షేర్ చేయి"</string> <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"తిరస్కరిస్తున్నాను"</string> <string name="select_input_method" msgid="3971267998568587025">"ఇన్పుట్ పద్ధతిని ఎంచుకోండి"</string> @@ -1410,7 +1412,7 @@ <string name="ext_media_new_notification_message" msgid="6095403121990786986">"సెటప్ చేయడానికి నొక్కండి"</string> <string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"సెటప్ చేయడానికి ఎంచుకోండి"</string> <string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది. తొలగించడానికి ట్యాప్ చేయండి"</string> - <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ఫోటోలు మరియు మీడియాను బదిలీ చేయడానికి"</string> + <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ఫోటోలు, మీడియాను బదిలీ చేయడానికి"</string> <string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"మీడియా ఫైల్స్ను బ్రౌజ్ చేయండి"</string> <string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>తో సమస్య ఉంది"</string> <string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> పని చేయటం లేదు"</string> @@ -1419,7 +1421,7 @@ <string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది. తొలగించడానికి ట్యాప్ చేయండి"</string> <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>కి మద్దతు లేదు"</string> <string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> పని చేయటం లేదు"</string> - <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కి మద్దతు ఇవ్వదు. మద్దతు కలిగిన ఆకృతిలో సెటప్ చేయడానికి నొక్కండి."</string> + <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కు సపోర్ట్ ఇవ్వదు. సపోర్ట్ ఉన్న ఫార్మాట్లో సెటప్ చేయడానికి నొక్కండి."</string> <string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"సపోర్ట్ చేసే ఫార్మాట్లో <xliff:g id="NAME">%s</xliff:g>ను సెటప్ చేయడానికి ఎంచుకోండి."</string> <string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది"</string> <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ఊహించని విధంగా తీసివేయబడింది"</string> @@ -1474,10 +1476,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 +1488,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> @@ -1522,11 +1524,11 @@ <string name="progress_erasing" msgid="6891435992721028004">"షేర్ చేసిన నిల్వను తొలగిస్తోంది…"</string> <string name="share" msgid="4157615043345227321">"షేర్"</string> <string name="find" msgid="5015737188624767706">"కనుగొనండి"</string> - <string name="websearch" msgid="5624340204512793290">"వెబ్ శోధన"</string> + <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> @@ -1675,12 +1677,12 @@ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"మీరు మీ పిన్ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"మీరు మీ పాస్వర్డ్ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, టాబ్లెట్ ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది మరియు మొత్తం వినియోగదారు డేటాను కోల్పోవడం సంభవిస్తుంది."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీ Android TV పరికరం ఫ్యాక్టరీ డిఫాల్ట్కి రీసెట్ చేయబడుతుంది, అలాగే వినియోగదారు డేటా మొత్తాన్ని కోల్పోతారు."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఫోన్ ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది మరియు మొత్తం వినియోగదారు డేటాను కోల్పోవడం సంభవిస్తుంది."</string> - <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. టాబ్లెట్ ఇప్పుడు ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, టాబ్లెట్ ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే మొత్తం యూజర్ డేటాను కోల్పోతారు."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీ Android TV పరికరం ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే యూజర్, డేటా మొత్తాన్ని కోల్పోతారు."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఫోన్ ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది, అలాగే మొత్తం యూజర్ డేటాను కోల్పోతారు."</string> + <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"మీరు టాబ్లెట్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. టాబ్లెట్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది."</string> <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"మీరు మీ Android TV పరికరాన్ని అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మీ Android TV పరికరం ఇప్పుడు ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string> - <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. ఫోన్ ఇప్పుడు ఫ్యాక్టరీ డిఫాల్ట్కు రీసెట్ చేయబడుతుంది."</string> + <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"మీరు ఫోన్ను అన్లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. ఫోన్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్కు రీసెట్ చేయబడుతుంది."</string> <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్ను అన్లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత మీ Android TV పరికరాన్ని ఇమెయిల్ ఖాతా ద్వారా అన్లాక్ చేయాల్సిందిగా మిమ్మల్ని కోరడం జరుగుతుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్ను అన్లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string> @@ -1713,8 +1715,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> @@ -1875,7 +1877,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"సరే"</string> <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లు, ఇంకా కొన్ని నెట్వర్క్ కనెక్షన్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది."</string> <string name="battery_saver_description" msgid="8518809702138617167">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లు, ఇంకా కొన్ని నెట్వర్క్ కనెక్షన్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది."</string> - <string name="data_saver_description" msgid="4995164271550590517">"డేటా వినియోగాన్ని తగ్గించడంలో డేటా సేవర్ సహాయకరంగా ఉంటుంది. బ్యాక్గ్రౌండ్లో కొన్ని యాప్లు డేటాను పంపకుండా లేదా స్వీకరించకుండా నిరోధిస్తుంది. మీరు ప్రస్తుతం ఉపయోగిస్తోన్న యాప్, డేటాను యాక్సెస్ చేయగలదు. కానీ తక్కువ సార్లు మాత్రమే అలా చేయవచ్చు. ఉదాహరణకు, మీరు నొక్కే వరకు ఫోటోలు ప్రదర్శించబడవు."</string> + <string name="data_saver_description" msgid="4995164271550590517">"డేటా వినియోగాన్ని తగ్గించడంలో డేటా సేవర్ సహాయకరంగా ఉంటుంది. బ్యాక్గ్రౌండ్లో కొన్ని యాప్లు డేటాను పంపకుండా లేదా స్వీకరించకుండా నిరోధిస్తుంది. మీరు ప్రస్తుతం ఉపయోగిస్తోన్న యాప్, డేటాను యాక్సెస్ చేయగలదు. కానీ తక్కువ సార్లు మాత్రమే అలా చేయవచ్చు. ఉదాహరణకు, మీరు నొక్కే వరకు ఇమేజ్లు ప్రదర్శించబడవు."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"డేటా సేవర్ను ఆన్ చేయాలా?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"ఆన్ చేయి"</string> <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273"> @@ -1926,14 +1928,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> @@ -2005,10 +2007,10 @@ <string name="app_category_game" msgid="4534216074910244790">"గేమ్లు"</string> <string name="app_category_audio" msgid="8296029904794676222">"సంగీతం & ఆడియో"</string> <string name="app_category_video" msgid="2590183854839565814">"చలనచిత్రాలు & వీడియో"</string> - <string name="app_category_image" msgid="7307840291864213007">"ఫోటోలు & చిత్రాలు"</string> + <string name="app_category_image" msgid="7307840291864213007">"ఫోటోలు, ఇమేజ్లు"</string> <string name="app_category_social" msgid="2278269325488344054">"సామాజికం & కమ్యూనికేషన్"</string> <string name="app_category_news" msgid="1172762719574964544">"వార్తలు & వార్తాపత్రికలు"</string> - <string name="app_category_maps" msgid="6395725487922533156">"Maps & నావిగేషన్"</string> + <string name="app_category_maps" msgid="6395725487922533156">"మ్యాప్స్ & నావిగేషన్"</string> <string name="app_category_productivity" msgid="1844422703029557883">"ఉత్పాదకత"</string> <string name="app_category_accessibility" msgid="6643521607848547683">"యాక్సెసిబిలిటీ"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"పరికర నిల్వ"</string> @@ -2041,19 +2043,19 @@ <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> - <string name="etws_primary_default_message_test" msgid="4583367373909549421">"అత్యవసర మెసేజ్ల పరీక్ష"</string> + <string name="etws_primary_default_message_test" msgid="4583367373909549421">"అత్యవసర మెసేజ్ల టెస్ట్"</string> <string name="notification_reply_button_accessibility" msgid="5235776156579456126">"రిప్లయి పంపండి"</string> <string name="etws_primary_default_message_others" msgid="7958161706019130739"></string> <string name="mmcc_authentication_reject" msgid="4891965994643876369">"వాయిస్ కోసం SIM అనుమతించబడదు"</string> @@ -2066,10 +2068,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> @@ -2099,7 +2101,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"సరే"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ఆఫ్ చేయండి"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"మరింత తెలుసుకోండి"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్లను, మెరుగైన నోటిఫికేషన్లు భర్తీ చేశాయి. సూచించిన చర్యలు, రిప్లయిలను ఈ ఫీచర్ చూపించి, మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్లు లాంటి వ్యక్తిగత సమాచారంతో సహా నోటిఫికేషన్ కంటెంట్ను మెరుగైన నోటిఫికేషన్లు యాక్సెస్ చేయవచ్చు. ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం లాంటి నోటిఫికేషన్లను విస్మరించడం లేదా ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్లను, మెరుగైన నోటిఫికేషన్లు రీప్లేస్ చేశాయి. ఈ ఫీచర్, సూచించిన చర్యలను, రిప్లయిలను చూపించి, మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్లు లాంటి వ్యక్తిగత సమాచారంతో పాటు నోటిఫికేషన్ కంటెంట్ను మెరుగైన నోటిఫికేషన్లు యాక్సెస్ చేస్తాయి. ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం వంటి నోటిఫికేషన్లను విస్మరించడం లేదా వాటికి ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"రొటీన్ మోడ్ సమాచార నోటిఫికేషన్"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"మామూలుగా ఛార్జ్ చేసేలోపు బ్యాటరీ ఖాళీ కావచ్చు"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"బ్యాటరీ జీవితకాలాన్ని పెంచడానికి బ్యాటరీ సేవర్ యాక్టివేట్ చేయబడింది"</string> @@ -2133,13 +2135,13 @@ <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> <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"ఇటీవలి యాప్లు"</string> <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"నోటిఫికేషన్లు"</string> - <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"శీఘ్ర సెట్టింగ్లు"</string> + <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"క్విక్ సెట్టింగ్లు"</string> <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"పవర్ డైలాగ్ను తెరువు"</string> <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"స్క్రీన్ను లాక్ చేయి"</string> <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"స్క్రీన్షాట్"</string> @@ -2225,17 +2227,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 +2249,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 +2261,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> @@ -2288,7 +2290,7 @@ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్లలో ఆన్ చేయండి"</string> <string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string> <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయండి"</string> - <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"పరికరం కెమెరాను అన్బ్లాక్ చేయండి"</string> + <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"పరికరంలోని కెమెరాను అన్బ్లాక్ చేయండి"</string> <string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> యాప్, ఇతర యాప్లు, సర్వీస్ల కోసం"</string> <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"అన్బ్లాక్ చేయండి"</string> <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"సెన్సార్ గోప్యత"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 379830a8a189..9c6505efc7da 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ใช้ลายนิ้วมือหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"เกิดข้อผิดพลาด ลองอีกครั้ง"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ไอคอนลายนิ้วมือ"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"การปลดล็อกด้วยใบหน้า"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"มีปัญหาเกี่ยวกับฟีเจอร์ปลดล็อกด้วยใบหน้า"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ใช้ใบหน้าหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"เกิดข้อผิดพลาด ลองอีกครั้ง"</string> <string name="face_icon_content_description" msgid="465030547475916280">"ไอคอนใบหน้า"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"อ่านการตั้งค่าการซิงค์"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น การอนุญาตนี้สามารถระบุได้ว่าแอปพลิเคชัน People ซิงค์กับบัญชีหรือไม่"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 73848a33abb8..c0bb5e3d4f96 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gamitin ang iyong fingerprint o lock ng screen para magpatuloy"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nagkaproblema. Subukan ulit."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icon ng fingerprint"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Pag-unlock Gamit ang Mukha"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isyu sa Pag-unlock Gamit ang Mukha"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gamitin ang iyong mukha o lock ng screen para magpatuloy"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nagkaproblema. Subukan ulit."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"basahin ang mga setting ng sync"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Pinapayagan ang app na basahin ang mga setting ng pag-sync para sa isang account. Halimbawa, matutukoy nito kung naka-sync ang app na Mga Tao sa isang account."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 3325e7e96d5e..d69635988c6e 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Devam etmek için parmak izi veya ekran kilidinizi kullanın"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Bir hata oluştu. Tekrar deneyin."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Parmak izi simgesi"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yüz Tanıma Kilidi"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yüz Tanıma Kilidi sorunu"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Devam etmek için yüz veya ekran kilidinizi kullanın"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Bir hata oluştu. Tekrar deneyin."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Yüz simgesi"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"senk. ayarlarını okuma"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Uygulamaya bir hesaba ait senkronizasyon ayarlarını okuma izni verir. Örneğin, bu izne sahip bir uygulama Kişiler uygulamasının bir hesapla senkronize olup olmadığını belirleyebilir."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 4912be887d9e..4b7643d8a97a 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -615,6 +615,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Щоб продовжити, скористайтеся відбитком пальця або даними для розблокування екрана"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Сталася помилка. Повторіть спробу."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок відбитка пальця"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Фейсконтроль"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Сталася помилка з фейсконтролем"</string> @@ -667,6 +668,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Щоб продовжити, скористайтеся фейсконтролем або даними для розблокування екрана"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Сталася помилка. Повторіть спробу."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Значок обличчя"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"читати налаштування синхронізації"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дозволяє програмі читати налаштування синхронізації для облікового запису, наприклад, визначати, чи програма Люди синхронізується з обліковим записом."</string> @@ -1755,7 +1757,7 @@ <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Виберіть функції для кнопки спеціальних можливостей"</string> <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Виберіть функції для комбінації з клавішами гучності"</string> <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="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> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 2936a080723b..16e4549debfc 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"جاری رکھنے کے لیے اپنے فنگر پرنٹ یا اسکرین لاک کا استعمال کریں"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"کچھ غلط ہو گیا۔ دوبارہ کوشش کریں۔"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"فنگر پرنٹ آئیکن"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فیس اَنلاک"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"فیس اَنلاک میں مسئلہ"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"جاری رکھنے کے لیے اپنے چہرے یا اسکرین لاک کا استعمال کریں"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"کچھ غلط ہو گیا۔ دوبارہ کوشش کریں۔"</string> <string name="face_icon_content_description" msgid="465030547475916280">"چہرے کا آئیکن"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"مطابقت پذیری کی ترتیبات پڑھیں"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index df7d4670dc29..48841acdfa95 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davom etish uchun barmoq izi yoki ekran qulfidan foydalaning"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Xatolik yuz berdi. Qayta urining."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmoq izi belgisi"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yuz bilan ochish"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yuz bilan ochishda muammo bor"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davom etish uchun yuz tekshiruvi yoki ekran qulfidan foydalaning"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Xatolik yuz berdi. Qayta urining."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Yuz belgisi"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx-sh sozlamalarini o‘qish"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ilovaga hisobning sinxronlash sozlamalarini o‘qish uchun ruxsat beradi. Masalan, bu \"Odamlar\" ilovasi hisob bilan sinxronlangan yoki aksini aniqlay oladi."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 259696dc587c..fa69be9188fa 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Dùng vân tay của bạn hoặc phương thức khóa màn hình để tiếp tục"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Đã xảy ra lỗi. Hãy thử lại."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Biểu tượng vân tay"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Mở khóa bằng khuôn mặt"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vấn đề với tính năng Mở khóa bằng khuôn mặt"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Dùng khuôn mặt của bạn hoặc phương thức khóa màn hình để tiếp tục"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Đã xảy ra lỗi. Hãy thử lại."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Biểu tượng khuôn mặt"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"đọc cài đặt đồng bộ hóa"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa cho tài khoản. Ví dụ: việc này có thể xác định liệu ứng dụng Mọi người đã được đồng bộ hóa với tài khoản chưa."</string> @@ -1071,7 +1073,7 @@ <string name="weeks" msgid="3516247214269821391">"tuần"</string> <string name="year" msgid="5182610307741238982">"năm"</string> <string name="years" msgid="5797714729103773425">"năm"</string> - <string name="now_string_shortest" msgid="3684914126941650330">"ngay lúc này"</string> + <string name="now_string_shortest" msgid="3684914126941650330">"vừa xong"</string> <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135"> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ph</item> <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ph</item> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 68a5ce7ee349..c43ee058c9e3 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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"使用指纹解锁或屏幕锁定凭据验证身份,才能继续操作"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"出了点问题。请重试。"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指纹图标"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人脸解锁"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人脸解锁存在问题"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"使用人脸解锁或屏幕锁定凭据验证身份,才能继续操作"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"出了点问题。请重试。"</string> <string name="face_icon_content_description" msgid="465030547475916280">"面孔图标"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"读取同步设置"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string> @@ -1216,8 +1218,8 @@ <string name="noApplications" msgid="1186909265235544019">"没有应用可执行此操作。"</string> <string name="aerr_application" msgid="4090916809370389109">"<xliff:g id="APPLICATION">%1$s</xliff:g>已停止运行"</string> <string name="aerr_process" msgid="4268018696970966407">"<xliff:g id="PROCESS">%1$s</xliff:g>已停止运行"</string> - <string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g>屡次停止运行"</string> - <string name="aerr_process_repeated" msgid="1153152413537954974">"<xliff:g id="PROCESS">%1$s</xliff:g>屡次停止运行"</string> + <string name="aerr_application_repeated" msgid="7804378743218496566">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”屡次停止运行"</string> + <string name="aerr_process_repeated" msgid="1153152413537954974">"“<xliff:g id="PROCESS">%1$s</xliff:g>”屡次停止运行"</string> <string name="aerr_restart" msgid="2789618625210505419">"重新打开应用"</string> <string name="aerr_report" msgid="3095644466849299308">"发送反馈"</string> <string name="aerr_close" msgid="3398336821267021852">"关闭"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index fa2fee5f4083..36b616ae6ece 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"發生錯誤,請再試一次。"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"面孔解鎖"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"「面孔解鎖」功能發生問題"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"請使用面孔解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"發生錯誤,請再試一次。"</string> <string name="face_icon_content_description" msgid="465030547475916280">"臉孔圖示"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"讀取同步處理設定"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允許應用程式讀取帳戶的同步設定,例如確定「通訊錄」應用程式是否和某個帳戶保持同步。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 798e06c3f53c..20fcadfb103e 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> @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"發生錯誤,請再試一次。"</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人臉解鎖"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人臉解鎖功能發生問題"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"請使用人臉解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"發生錯誤,請再試一次。"</string> <string name="face_icon_content_description" msgid="465030547475916280">"臉孔圖示"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"讀取同步處理設定"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允許應用程式讀取帳戶的同步處理設定,例如判斷「使用者」應用程式是否和某個帳戶進行同步處理。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index f93b84463874..db19c084316e 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -609,6 +609,7 @@ <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Sebenzisa izigxivizo zakho zomunwe noma ukukhiya isikrini ukuze uqhubeke"</string> <string-array name="fingerprint_error_vendor"> </string-array> + <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kunento engahambanga kahle. Zama futhi."</string> <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Isithonjana sezigxivizo zeminwe"</string> <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ukuvula ubuso"</string> <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Inkinga Ngokuvula ngobuso"</string> @@ -661,6 +662,7 @@ <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Sebenzisa ubuso bakho noma ukukhiya isikrini ukuze uqhubeke"</string> <string-array name="face_error_vendor"> </string-array> + <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kunento engahambanga kahle. Zama futhi."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Isithonjana sobuso"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"funda izilungiselelo zokuvumelanisa"</string> <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ivumela uhlelo lokusebenza ukufunda izilungiselelo zokuvumelanisa ze-akhawunti. Isibonelo, lokhu kungacacisa ukuthi noma ngabe uhlelo lokusebenza le-People livumelanisiwe ne-akhawunti."</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7f6ade48cced..33e38e066f21 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -957,6 +957,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. --> @@ -4581,6 +4595,13 @@ <!-- Indicates whether device has a power button fingerprint sensor. --> <bool name="config_is_powerbutton_fps" translatable="false" >false</bool> + <!-- When each intermediate UDFPS enroll stage ends, as a fraction of total progress. --> + <string-array name="config_udfps_enroll_stage_thresholds" translatable="false"> + <item>0.25</item> + <item>0.5</item> + <item>0.75</item> + </string-array> + <!-- Messages that should not be shown to the user during face auth enrollment. This should be used to hide messages that may be too chatty or messages that the user can't do much about. Entries are defined in android.hardware.biometrics.face@1.0 types.hal --> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index de7a1175b4a3..a666a5b4b796 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -58,6 +58,9 @@ <!-- How much we expand the touchable region of the status bar below the notch to catch touches that just start below the notch. --> <dimen name="display_cutout_touchable_region_size">12dp</dimen> + <!-- The default margin used in immersive mode to capture the start of a swipe gesture from the + edge of the screen to show the system bars. --> + <dimen name="system_gestures_start_threshold">24dp</dimen> <!-- Height of the bottom navigation bar frame; this is different than navigation_bar_height where that is the height reported to all the other windows to resize themselves around the @@ -237,6 +240,9 @@ value is calculated in ConversationLayout#updateActionListPadding() --> <dimen name="notification_actions_padding_start">36dp</dimen> + <!-- The max width of a priority action button when it is collapsed to just the icon. --> + <dimen name="notification_actions_collapsed_priority_width">60dp</dimen> + <!-- The start padding to optionally use (e.g. if there's extra space) for CallStyle notification actions. this = conversation_content_start (80dp) - button inset (4dp) - action padding (12dp) --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 333eabd57e9e..cfffdb25706a 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1652,6 +1652,8 @@ <!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings --> <string-array name="fingerprint_error_vendor"> </string-array> + <!-- Default error message to use when fingerprint_error_vendor does not contain a message. [CHAR LIMIT=NONE] --> + <string name="fingerprint_error_vendor_unknown">Something went wrong. Try again.</string> <!-- Content description which should be used for the fingerprint icon. --> <string name="fingerprint_icon_content_description">Fingerprint icon</string> @@ -1762,6 +1764,8 @@ <!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings --> <string-array name="face_error_vendor"> </string-array> + <!-- Default error message to use when face_error_vendor does not contain a message. [CHAR LIMIT=NONE] --> + <string name="face_error_vendor_unknown">Something went wrong. Try again.</string> <!-- Content description which should be used for the face icon. [CHAR LIMIT=10] --> <string name="face_icon_content_description">Face icon</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5742ae8835fe..bcd80ac1989e 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" /> @@ -1757,6 +1759,7 @@ <java-symbol type="dimen" name="navigation_bar_width_car_mode" /> <java-symbol type="dimen" name="status_bar_height" /> <java-symbol type="dimen" name="display_cutout_touchable_region_size" /> + <java-symbol type="dimen" name="system_gestures_start_threshold" /> <java-symbol type="dimen" name="quick_qs_offset_height" /> <java-symbol type="drawable" name="ic_jog_dial_sound_off" /> <java-symbol type="drawable" name="ic_jog_dial_sound_on" /> @@ -2541,6 +2544,7 @@ <java-symbol type="string" name="fingerprint_error_no_space" /> <java-symbol type="string" name="fingerprint_error_timeout" /> <java-symbol type="array" name="fingerprint_error_vendor" /> + <java-symbol type="string" name="fingerprint_error_vendor_unknown" /> <java-symbol type="string" name="fingerprint_acquired_partial" /> <java-symbol type="string" name="fingerprint_acquired_insufficient" /> <java-symbol type="string" name="fingerprint_acquired_imager_dirty" /> @@ -2580,6 +2584,7 @@ <java-symbol type="string" name="face_error_no_space" /> <java-symbol type="string" name="face_error_timeout" /> <java-symbol type="array" name="face_error_vendor" /> + <java-symbol type="string" name="face_error_vendor_unknown" /> <java-symbol type="string" name="face_error_canceled" /> <java-symbol type="string" name="face_error_user_canceled" /> <java-symbol type="string" name="face_error_lockout" /> @@ -2622,6 +2627,7 @@ <java-symbol type="array" name="config_udfps_sensor_props" /> <java-symbol type="integer" name="config_udfps_illumination_transition_ms" /> <java-symbol type="bool" name="config_is_powerbutton_fps" /> + <java-symbol type="array" name="config_udfps_enroll_stage_thresholds" /> <java-symbol type="array" name="config_face_acquire_enroll_ignorelist" /> <java-symbol type="array" name="config_face_acquire_vendor_enroll_ignorelist" /> @@ -3202,6 +3208,7 @@ <java-symbol type="id" name="notification_action_list_margin_target" /> <java-symbol type="dimen" name="notification_actions_padding_start"/> + <java-symbol type="dimen" name="notification_actions_collapsed_priority_width"/> <java-symbol type="dimen" name="notification_action_disabled_alpha" /> <java-symbol type="id" name="tag_margin_end_when_icon_visible" /> <java-symbol type="id" name="tag_margin_end_when_icon_gone" /> @@ -4431,7 +4438,7 @@ <java-symbol type="string" name="view_and_control_notification_title" /> <java-symbol type="string" name="view_and_control_notification_content" /> <java-symbol type="array" name="config_accessibility_allowed_install_source" /> - + <!-- Translation --> <java-symbol type="string" name="ui_translation_accessibility_translated_text" /> <java-symbol type="string" name="ui_translation_accessibility_translation_finished" /> @@ -4454,4 +4461,6 @@ <java-symbol type="bool" name="config_volumeShowRemoteSessions" /> <java-symbol type="integer" name="config_customizedMaxCachedProcesses" /> + + <java-symbol type="color" name="overview_background"/> </resources> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index cd07d464ee65..34c1763b3286 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -16,9 +16,11 @@ package android.app; -import static androidx.core.graphics.ColorUtils.calculateContrast; +import static android.app.Notification.Builder.ensureColorSpanContrast; import static com.android.compatibility.common.util.SystemUtil.runShellCommand; +import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsAtLeast; +import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsWithinRange; import static com.google.common.truth.Truth.assertThat; @@ -35,6 +37,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.Intent; import android.content.LocusId; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -42,12 +45,21 @@ import android.graphics.drawable.Icon; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.TextAppearanceSpan; import android.widget.RemoteViews; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.R; +import com.android.internal.util.ContrastColorUtil; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -334,6 +346,163 @@ public class NotificationTest { } @Test + public void testBuilder_getFullLengthSpanColor_returnsNullForString() { + assertThat(Notification.Builder.getFullLengthSpanColor("String")).isNull(); + } + + @Test + public void testBuilder_getFullLengthSpanColor_returnsNullWithPartialSpan() { + CharSequence text = new SpannableStringBuilder() + .append("text with ") + .append("some red", new ForegroundColorSpan(Color.RED), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + assertThat(Notification.Builder.getFullLengthSpanColor(text)).isNull(); + } + + @Test + public void testBuilder_getFullLengthSpanColor_worksWithSingleSpan() { + CharSequence text = new SpannableStringBuilder() + .append("text that is all red", new ForegroundColorSpan(Color.RED), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.RED); + } + + @Test + public void testBuilder_getFullLengthSpanColor_worksWithFullAndPartialSpans() { + Spannable text = new SpannableString("blue text with yellow and green"); + text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.BLUE); + } + + @Test + public void testBuilder_getFullLengthSpanColor_worksWithTextAppearance() { + Spannable text = new SpannableString("title text with yellow and green"); + text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(mContext, + R.style.TextAppearance_DeviceDefault_Notification_Title); + int expectedTextColor = textAppearanceSpan.getTextColor().getDefaultColor(); + text.setSpan(textAppearanceSpan, 0, text.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(expectedTextColor); + } + + @Test + public void testBuilder_ensureColorSpanContrast_removesAllFullLengthColorSpans() { + Spannable text = new SpannableString("blue text with yellow and green"); + text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext, + R.style.TextAppearance_DeviceDefault_Notification_Title); + assertThat(taSpan.getTextColor()).isNotNull(); // it must be set to prove it is cleared. + text.setSpan(taSpan, 0, text.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + Spannable result = (Spannable) ensureColorSpanContrast(text, Color.BLACK); + Object[] spans = result.getSpans(0, result.length(), Object.class); + assertThat(spans).hasLength(3); + + assertThat(result.getSpanStart(spans[0])).isEqualTo(15); + assertThat(result.getSpanEnd(spans[0])).isEqualTo(21); + assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW); + + assertThat(result.getSpanStart(spans[1])).isEqualTo(0); + assertThat(result.getSpanEnd(spans[1])).isEqualTo(31); + assertThat(spans[1]).isNotSameInstanceAs(taSpan); // don't mutate the existing span + assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily()); + assertThat(((TextAppearanceSpan) spans[1]).getTextColor()).isNull(); + + assertThat(result.getSpanStart(spans[2])).isEqualTo(26); + assertThat(result.getSpanEnd(spans[2])).isEqualTo(31); + assertThat(((ForegroundColorSpan) spans[2]).getForegroundColor()).isEqualTo(Color.GREEN); + } + + @Test + public void testBuilder_ensureColorSpanContrast_partialLength_adjusted() { + int background = 0xFFFF0101; // Slightly lighter red + CharSequence text = new SpannableStringBuilder() + .append("text with ") + .append("some red", new ForegroundColorSpan(Color.RED), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + CharSequence result = ensureColorSpanContrast(text, background); + + // ensure the span has been updated to have > 1.3:1 contrast ratio with fill color + Object[] spans = ((Spannable) result).getSpans(0, result.length(), Object.class); + assertThat(spans).hasLength(1); + int foregroundColor = ((ForegroundColorSpan) spans[0]).getForegroundColor(); + assertContrastIsWithinRange(foregroundColor, background, 3, 3.2); + } + + @Test + public void testBuilder_ensureColorSpanContrast_worksWithComplexInput() { + Spannable text = new SpannableString("blue text with yellow and green and cyan"); + text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + // cyan TextAppearanceSpan + TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext, + R.style.TextAppearance_DeviceDefault_Notification_Title); + taSpan = new TextAppearanceSpan(taSpan.getFamily(), taSpan.getTextStyle(), + taSpan.getTextSize(), ColorStateList.valueOf(Color.CYAN), null); + text.setSpan(taSpan, 36, 40, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + Spannable result = (Spannable) ensureColorSpanContrast(text, Color.GRAY); + Object[] spans = result.getSpans(0, result.length(), Object.class); + assertThat(spans).hasLength(3); + + assertThat(result.getSpanStart(spans[0])).isEqualTo(15); + assertThat(result.getSpanEnd(spans[0])).isEqualTo(21); + assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW); + + assertThat(result.getSpanStart(spans[1])).isEqualTo(36); + assertThat(result.getSpanEnd(spans[1])).isEqualTo(40); + assertThat(spans[1]).isNotSameInstanceAs(taSpan); // don't mutate the existing span + assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily()); + ColorStateList newCyanList = ((TextAppearanceSpan) spans[1]).getTextColor(); + assertThat(newCyanList).isNotNull(); + assertContrastIsWithinRange(newCyanList.getDefaultColor(), Color.GRAY, 3, 3.2); + + assertThat(result.getSpanStart(spans[2])).isEqualTo(26); + assertThat(result.getSpanEnd(spans[2])).isEqualTo(31); + int newGreen = ((ForegroundColorSpan) spans[2]).getForegroundColor(); + assertThat(newGreen).isNotEqualTo(Color.GREEN); + assertContrastIsWithinRange(newGreen, Color.GRAY, 3, 3.2); + } + + @Test + public void testBuilder_ensureButtonFillContrast_adjustsDarker() { + int background = Color.LTGRAY; + int foreground = Color.LTGRAY; + int result = Notification.Builder.ensureButtonFillContrast(foreground, background); + assertContrastIsWithinRange(result, background, 1.3, 1.5); + assertThat(ContrastColorUtil.calculateLuminance(result)) + .isLessThan(ContrastColorUtil.calculateLuminance(background)); + } + + @Test + public void testBuilder_ensureButtonFillContrast_adjustsLighter() { + int background = Color.DKGRAY; + int foreground = Color.DKGRAY; + int result = Notification.Builder.ensureButtonFillContrast(foreground, background); + assertContrastIsWithinRange(result, background, 1.3, 1.5); + assertThat(ContrastColorUtil.calculateLuminance(result)) + .isGreaterThan(ContrastColorUtil.calculateLuminance(background)); + } + + @Test public void testColors_ensureColors_dayMode_producesValidPalette() { Notification.Colors c = new Notification.Colors(); boolean colorized = false; @@ -399,6 +568,8 @@ public class NotificationTest { assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor()); assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor()); assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor()); + assertEquals(cDay.getTertiaryAccentColor(), cNight.getTertiaryAccentColor()); + assertEquals(cDay.getOnAccentTextColor(), cNight.getOnAccentTextColor()); assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor()); assertEquals(cDay.getContrastColor(), cNight.getContrastColor()); assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha()); @@ -413,30 +584,26 @@ public class NotificationTest { assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getPrimaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getSecondaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); + assertThat(c.getTertiaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); + assertThat(c.getOnAccentTextColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getErrorColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getRippleAlpha()).isAtLeast(0x00); assertThat(c.getRippleAlpha()).isAtMost(0xff); - // Assert that various colors have sufficient contrast + // Assert that various colors have sufficient contrast with the background assertContrastIsAtLeast(c.getPrimaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getSecondaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getErrorColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getContrastColor(), c.getBackgroundColor(), 4.5); - // This accent color is only used for emphasized buttons + // These colors are only used for emphasized buttons; they do not need contrast assertContrastIsAtLeast(c.getSecondaryAccentColor(), c.getBackgroundColor(), 1); - } + assertContrastIsAtLeast(c.getTertiaryAccentColor(), c.getBackgroundColor(), 1); - private void assertContrastIsAtLeast(int foreground, int background, double minContrast) { - try { - assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast); - } catch (AssertionError e) { - throw new AssertionError( - String.format("Insufficient contrast: foreground=#%08x background=#%08x", - foreground, background), e); - } + // The text that is used within the accent color DOES need to have contrast + assertContrastIsAtLeast(c.getOnAccentTextColor(), c.getTertiaryAccentColor(), 4.5); } private void resolveColorsInNightMode(boolean nightMode, Notification.Colors c, int rawColor, diff --git a/core/tests/coretests/src/android/graphics/FontListParserTest.java b/core/tests/coretests/src/android/graphics/FontListParserTest.java index 22f6ec0b24b1..701e6194d4ee 100644 --- a/core/tests/coretests/src/android/graphics/FontListParserTest.java +++ b/core/tests/coretests/src/android/graphics/FontListParserTest.java @@ -27,6 +27,7 @@ import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.fail; +import android.graphics.fonts.FontCustomizationParser; import android.graphics.fonts.FontStyle; import android.os.LocaleList; import android.text.FontConfig; @@ -46,6 +47,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) @@ -318,6 +320,52 @@ public final class FontListParserTest { } } + @Test + public void alias() throws Exception { + String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font>test.ttf</font>" + + " </family>" + + " <family name='custom-family'>" + + " <font>missing.ttf</font>" + + " </family>" + + " <alias name='custom-alias' to='sans-serif'/>" + + "</familyset>"; + FontConfig config = readFamilies(xml, true /* include non-existing font files */); + List<FontConfig.Alias> aliases = config.getAliases(); + assertThat(aliases.size()).isEqualTo(1); + assertThat(aliases.get(0).getName()).isEqualTo("custom-alias"); + assertThat(aliases.get(0).getOriginal()).isEqualTo("sans-serif"); + } + + @Test + public void dropped_FamilyAlias() throws Exception { + String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font>test.ttf</font>" + + " </family>" + + " <family name='custom-family'>" + + " <font>missing.ttf</font>" + + " </family>" + + " <alias name='custom-alias' to='custom-family'/>" + + "</familyset>"; + FontConfig config = readFamilies(xml, false /* exclude not existing file */); + assertThat(config.getAliases()).isEmpty(); + } + + private FontConfig readFamilies(String xml, boolean allowNonExisting) + throws IOException, XmlPullParserException { + ByteArrayInputStream buffer = new ByteArrayInputStream( + xml.getBytes(StandardCharsets.UTF_8)); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(buffer, "UTF-8"); + parser.nextTag(); + return FontListParser.readFamilies(parser, "", new FontCustomizationParser.Result(), null, + 0L /* last modified date */, 0 /* config version */, allowNonExisting); + } + private FontConfig.FontFamily readFamily(String xml) throws IOException, XmlPullParserException { ByteArrayInputStream buffer = new ByteArrayInputStream( diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java index a5a98a98f0be..109b7ab73d6f 100644 --- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java @@ -17,6 +17,8 @@ package android.service.notification; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; @@ -51,6 +53,7 @@ public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock + private Context mRealContext; private PackageManager mPm; private static final String PKG = "com.example.o"; @@ -75,6 +78,8 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); + + mRealContext = InstrumentationRegistry.getContext(); } @Test @@ -199,6 +204,19 @@ public class StatusBarNotificationTest { } + @Test + public void testGetPackageContext_worksWithUserAll() { + String pkg = "com.android.systemui"; + int uid = 1000; + Notification notification = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID).build(); + StatusBarNotification sbn = new StatusBarNotification( + pkg, pkg, ID, TAG, uid, uid, notification, UserHandle.ALL, null, UID); + Context resultContext = sbn.getPackageContext(mRealContext); + assertNotNull(resultContext); + assertNotSame(mRealContext, resultContext); + assertEquals(pkg, resultContext.getPackageName()); + } + private StatusBarNotification getNotification(String pkg, String group, String channelId) { return getNotification(pkg, getNotificationBuilder(group, channelId)); } diff --git a/core/tests/coretests/src/android/window/WindowContextControllerTest.java b/core/tests/coretests/src/android/window/WindowContextControllerTest.java index 020f4a06b892..073e46827bbb 100644 --- a/core/tests/coretests/src/android/window/WindowContextControllerTest.java +++ b/core/tests/coretests/src/android/window/WindowContextControllerTest.java @@ -23,11 +23,13 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.content.res.Configuration; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.IWindowManager; @@ -38,6 +40,8 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; /** * Tests for {@link WindowContextController} @@ -53,15 +57,18 @@ import org.junit.runner.RunWith; @Presubmit public class WindowContextControllerTest { private WindowContextController mController; + @Mock private IWindowManager mMockWms; + @Mock + private WindowTokenClient mMockToken; @Before public void setUp() throws Exception { - mMockWms = mock(IWindowManager.class); - mController = new WindowContextController(new Binder(), mMockWms); - - doReturn(true).when(mMockWms).attachWindowContextToDisplayArea(any(), anyInt(), - anyInt(), any()); + MockitoAnnotations.initMocks(this); + mController = new WindowContextController(mMockToken, mMockWms); + doNothing().when(mMockToken).onConfigurationChanged(any(), anyInt()); + doReturn(new Configuration()).when(mMockWms).attachWindowContextToDisplayArea(any(), + anyInt(), anyInt(), any()); } @Test(expected = IllegalStateException.class) @@ -85,6 +92,7 @@ public class WindowContextControllerTest { null /* options */); assertThat(mController.mAttachedToDisplayArea).isTrue(); + verify(mMockToken).onConfigurationChanged(any(), eq(DEFAULT_DISPLAY)); mController.detachIfNeeded(); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 464412f17722..d4799a8f5fd3 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -23,6 +23,8 @@ import android.app.ActivityManager; import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; import android.os.BatteryStats.Uid.Sensor; +import android.os.Process; +import android.os.UserHandle; import android.os.WorkSource; import android.util.SparseLongArray; import android.view.Display; @@ -53,6 +55,8 @@ import java.util.Map; public class BatteryStatsNoteTest extends TestCase { private static final int UID = 10500; + private static final int ISOLATED_APP_ID = Process.FIRST_ISOLATED_UID + 23; + private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID); private static final WorkSource WS = new WorkSource(UID); /** @@ -114,6 +118,88 @@ public class BatteryStatsNoteTest extends TestCase { assertEquals(120_000, bgTime); } + /** + * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid. + */ + @SmallTest + public void testNoteStartWakeLocked_isolatedUid() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); + + int pid = 10; + String name = "name"; + String historyName = "historyName"; + + WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain(); + isolatedWorkChain.addNode(ISOLATED_UID, name); + + // Map ISOLATED_UID to UID. + bi.addIsolatedUidLocked(ISOLATED_UID, UID); + + bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); + bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName, + WAKE_TYPE_PARTIAL, false); + + clocks.realtime = clocks.uptime = 100; + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + + clocks.realtime = clocks.uptime = 220; + bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName, + WAKE_TYPE_PARTIAL); + + // ISOLATED_UID wakelock time should be attributed to UID. + BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID) + .getAggregatedPartialWakelockTimer(); + long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED); + long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED); + assertEquals(220_000, actualTime); + assertEquals(120_000, bgTime); + } + + /** + * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid, with a race where the + * isolated uid is removed from batterystats before the wakelock has been stopped. + */ + @SmallTest + public void testNoteStartWakeLocked_isolatedUidRace() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); + + int pid = 10; + String name = "name"; + String historyName = "historyName"; + + WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain(); + isolatedWorkChain.addNode(ISOLATED_UID, name); + + // Map ISOLATED_UID to UID. + bi.addIsolatedUidLocked(ISOLATED_UID, UID); + + bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); + bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName, + WAKE_TYPE_PARTIAL, false); + + clocks.realtime = clocks.uptime = 100; + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + + clocks.realtime = clocks.uptime = 150; + bi.maybeRemoveIsolatedUidLocked(ISOLATED_UID, clocks.realtime, clocks.uptime); + + clocks.realtime = clocks.uptime = 220; + bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName, + WAKE_TYPE_PARTIAL); + + // ISOLATED_UID wakelock time should be attributed to UID. + BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID) + .getAggregatedPartialWakelockTimer(); + long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED); + long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED); + assertEquals(220_000, actualTime); + assertEquals(120_000, bgTime); + } + /** * Test BatteryStatsImpl.noteUidProcessStateLocked. @@ -506,7 +592,7 @@ public class BatteryStatsNoteTest extends TestCase { public void testUpdateDisplayMeasuredEnergyStatsLocked() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); - bi.initMeasuredEnergyStats(); + bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); clocks.realtime = 0; int screen = Display.STATE_OFF; @@ -591,7 +677,7 @@ public class BatteryStatsNoteTest extends TestCase { public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); - bi.initMeasuredEnergyStats(); + bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); bi.setOnBatteryInternal(true); final int uid1 = 11500; @@ -605,7 +691,7 @@ public class BatteryStatsNoteTest extends TestCase { public void testUpdateCustomMeasuredEnergyStatsLocked() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); - bi.initMeasuredEnergyStats(); + bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); final int bucketA = 0; // Custom bucket 0 final int bucketB = 1; // Custom bucket 1 diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java index b851f0ad3414..0135fe84909a 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java @@ -403,7 +403,7 @@ public class BatteryStatsSensorTest extends TestCase { assertNotNull(sensor.getSensorBackgroundTime()); // Reset the stats. Since the sensor is still running, we should still see the timer - bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000); + bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000, 0); sensor = uid.getSensorStats().get(SENSOR_ID); assertNotNull(sensor); @@ -413,7 +413,7 @@ public class BatteryStatsSensorTest extends TestCase { bi.noteStopSensorLocked(UID, SENSOR_ID); // Now the sensor timer has stopped so this reset should also take out the sensor. - bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000); + bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000, 0); sensor = uid.getSensorStats().get(SENSOR_ID); assertNull(sensor); @@ -465,7 +465,7 @@ public class BatteryStatsSensorTest extends TestCase { // Reset the stats. Since the sensor is still running, we should still see the timer // but still with 0 times. - bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000); + bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000, 0); assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which)); assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime)); assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which)); @@ -504,7 +504,7 @@ public class BatteryStatsSensorTest extends TestCase { // Reset the stats. Since the sensor is still running, we should still see the timer // but with 0 times. - bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000); + bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000, 0); assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which)); assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime)); assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which)); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java index 0147cdb186f3..74b6dbe76a16 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java @@ -18,6 +18,9 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.app.ActivityManager; import android.content.Context; import android.os.BatteryConsumer; @@ -263,6 +266,39 @@ public class BatteryUsageStatsProviderTest { .of(180.0); } + @Test + public void testAggregateBatteryStats_incompatibleSnapshot() { + Context context = InstrumentationRegistry.getContext(); + MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); + batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"}); + + BatteryUsageStatsStore batteryUsageStatsStore = mock(BatteryUsageStatsStore.class); + + when(batteryUsageStatsStore.listBatteryUsageStatsTimestamps()) + .thenReturn(new long[]{1000, 2000}); + + when(batteryUsageStatsStore.loadBatteryUsageStats(1000)).thenReturn( + new BatteryUsageStats.Builder(batteryStats.getCustomEnergyConsumerNames()) + .setStatsDuration(1234).build()); + + // Add a snapshot, with a different set of custom power components. It should + // be skipped by the aggregation. + when(batteryUsageStatsStore.loadBatteryUsageStats(2000)).thenReturn( + new BatteryUsageStats.Builder(new String[]{"different"}) + .setStatsDuration(4321).build()); + + BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, + batteryStats, batteryUsageStatsStore); + + BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder() + .aggregateSnapshots(0, 3000) + .build(); + final BatteryUsageStats stats = provider.getBatteryUsageStats(query); + assertThat(stats.getCustomPowerComponentNames()) + .isEqualTo(batteryStats.getCustomEnergyConsumerNames()); + assertThat(stats.getStatsDuration()).isEqualTo(1234); + } + private static class TestHandler extends Handler { TestHandler() { super(Looper.getMainLooper()); diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index 99d576d259ec..cee1a0352a7e 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -57,11 +57,10 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { this(new MockClocks()); } - public void initMeasuredEnergyStats() { + public void initMeasuredEnergyStats(String[] customBucketNames) { final boolean[] supportedStandardBuckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; Arrays.fill(supportedStandardBuckets, true); - final String[] customBucketNames = {"FOO", "BAR"}; mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); } diff --git a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java new file mode 100644 index 000000000000..cfe660c77817 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 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.internal.util; + +import static androidx.core.graphics.ColorUtils.calculateContrast; + +import static com.google.common.truth.Truth.assertThat; + +import android.graphics.Color; + +import androidx.test.filters.SmallTest; + +import junit.framework.TestCase; + +public class ContrastColorUtilTest extends TestCase { + + @SmallTest + public void testEnsureTextContrastAgainstDark() { + int darkBg = 0xFF35302A; + + int blueContrastColor = ContrastColorUtil.ensureTextContrast(Color.BLUE, darkBg, true); + assertContrastIsWithinRange(blueContrastColor, darkBg, 4.5, 4.75); + + int redContrastColor = ContrastColorUtil.ensureTextContrast(Color.RED, darkBg, true); + assertContrastIsWithinRange(redContrastColor, darkBg, 4.5, 4.75); + + final int darkGreen = 0xff008800; + int greenContrastColor = ContrastColorUtil.ensureTextContrast(darkGreen, darkBg, true); + assertContrastIsWithinRange(greenContrastColor, darkBg, 4.5, 4.75); + + int grayContrastColor = ContrastColorUtil.ensureTextContrast(Color.DKGRAY, darkBg, true); + assertContrastIsWithinRange(grayContrastColor, darkBg, 4.5, 4.75); + + int selfContrastColor = ContrastColorUtil.ensureTextContrast(darkBg, darkBg, true); + assertContrastIsWithinRange(selfContrastColor, darkBg, 4.5, 4.75); + } + + @SmallTest + public void testEnsureTextContrastAgainstLight() { + int lightBg = 0xFFFFF8F2; + + final int lightBlue = 0xff8888ff; + int blueContrastColor = ContrastColorUtil.ensureTextContrast(lightBlue, lightBg, false); + assertContrastIsWithinRange(blueContrastColor, lightBg, 4.5, 4.75); + + int redContrastColor = ContrastColorUtil.ensureTextContrast(Color.RED, lightBg, false); + assertContrastIsWithinRange(redContrastColor, lightBg, 4.5, 4.75); + + int greenContrastColor = ContrastColorUtil.ensureTextContrast(Color.GREEN, lightBg, false); + assertContrastIsWithinRange(greenContrastColor, lightBg, 4.5, 4.75); + + int grayContrastColor = ContrastColorUtil.ensureTextContrast(Color.LTGRAY, lightBg, false); + assertContrastIsWithinRange(grayContrastColor, lightBg, 4.5, 4.75); + + int selfContrastColor = ContrastColorUtil.ensureTextContrast(lightBg, lightBg, false); + assertContrastIsWithinRange(selfContrastColor, lightBg, 4.5, 4.75); + } + + public static void assertContrastIsWithinRange(int foreground, int background, + double minContrast, double maxContrast) { + assertContrastIsAtLeast(foreground, background, minContrast); + assertContrastIsAtMost(foreground, background, maxContrast); + } + + public static void assertContrastIsAtLeast(int foreground, int background, double minContrast) { + try { + assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast); + } catch (AssertionError e) { + throw new AssertionError( + String.format("Insufficient contrast: foreground=#%08x background=#%08x", + foreground, background), e); + } + } + + public static void assertContrastIsAtMost(int foreground, int background, double maxContrast) { + try { + assertThat(calculateContrast(foreground, background)).isAtMost(maxContrast); + } catch (AssertionError e) { + throw new AssertionError( + String.format("Excessive contrast: foreground=#%08x background=#%08x", + foreground, background), e); + } + } + +} diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml index 40dda6573ccc..eeb65ae8e129 100644 --- a/data/etc/car/com.google.android.car.kitchensink.xml +++ b/data/etc/car/com.google.android.car.kitchensink.xml @@ -48,6 +48,7 @@ <permission name="android.permission.SET_ACTIVITY_WATCHER"/> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.car.permission.CONTROL_APP_BLOCKING"/> <!-- use for rotary fragment to enable/disable packages related to rotary --> <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/> diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 93a336e7a408..96b33259e739 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -25,6 +25,7 @@ import android.graphics.fonts.FontVariationAxis; import android.os.Build; import android.os.LocaleList; import android.text.FontConfig; +import android.util.ArraySet; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; @@ -37,6 +38,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; /** @@ -120,7 +122,23 @@ public class FontListParser { } } - private static FontConfig readFamilies( + /** + * Parses the familyset tag in font.xml + * @param parser a XML pull parser + * @param fontDir A system font directory, e.g. "/system/fonts" + * @param customization A OEM font customization + * @param updatableFontMap A map of updated font files + * @param lastModifiedDate A date that the system font is updated. + * @param configVersion A version of system font config. + * @param allowNonExistingFile true if allowing non-existing font files during parsing fonts.xml + * @return result of fonts.xml + * + * @throws XmlPullParserException + * @throws IOException + * + * @hide + */ + public static FontConfig readFamilies( @NonNull XmlPullParser parser, @NonNull String fontDir, @NonNull FontCustomizationParser.Result customization, @@ -159,7 +177,24 @@ public class FontListParser { } families.addAll(oemNamedFamilies.values()); - return new FontConfig(families, aliases, lastModifiedDate, configVersion); + + // Filters aliases that point to non-existing families. + Set<String> namedFamilies = new ArraySet<>(); + for (int i = 0; i < families.size(); ++i) { + String name = families.get(i).getName(); + if (name != null) { + namedFamilies.add(name); + } + } + List<FontConfig.Alias> filtered = new ArrayList<>(); + for (int i = 0; i < aliases.size(); ++i) { + FontConfig.Alias alias = aliases.get(i); + if (namedFamilies.contains(alias.getOriginal())) { + filtered.add(alias); + } + } + + return new FontConfig(families, filtered, lastModifiedDate, configVersion); } private static boolean keepReading(XmlPullParser parser) diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index f3cfcf18dec1..67358c4f3255 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -579,7 +579,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { // // Note: mNamespace == KeyProperties.NAMESPACE_APPLICATION implies that the target domain // is Domain.APP and Domain.SELINUX is the target domain otherwise. - if (alias != descriptor.alias + if (!alias.equals(descriptor.alias) || descriptor.domain != targetDomain || (descriptor.domain == Domain.SELINUX && descriptor.nspace != targetNamespace)) { throw new KeyStoreException("Can only replace keys with same alias: " + alias diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 1ace3cdacb46..325838581659 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -19,10 +19,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="pip_phone_close" msgid="5783752637260411309">"বন্ধ কৰক"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"বিস্তাৰ কৰক"</string> - <string name="pip_phone_settings" msgid="5468987116750491918">"ছেটিংসমূহ"</string> + <string name="pip_phone_settings" msgid="5468987116750491918">"ছেটিং"</string> <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> চিত্ৰৰ ভিতৰৰ চিত্ৰত আছে"</string> - <string name="pip_notification_message" msgid="8854051911700302620">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g> সুবিধাটো ব্যৱহাৰ কৰিব নোখোজে, তেন্তে ছেটিংসমূহ খুলিবলৈ টিপক আৰু তালৈ গৈ ইয়াক অফ কৰক।"</string> + <string name="pip_notification_message" msgid="8854051911700302620">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g> সুবিধাটো ব্যৱহাৰ কৰিব নোখোজে, তেন্তে ছেটিং খুলিবলৈ টিপক আৰু তালৈ গৈ ইয়াক অফ কৰক।"</string> <string name="pip_play" msgid="3496151081459417097">"প্লে কৰক"</string> <string name="pip_pause" msgid="690688849510295232">"পজ কৰক"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"পৰৱৰ্তী মিডিয়ালৈ যাওক"</string> @@ -31,25 +31,25 @@ <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"লুকুৱাওক"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"দেখুৱাওক"</string> <string name="dock_forced_resizable" msgid="1749750436092293116">"এপ্টোৱে বিভাজিত স্ক্ৰীনৰ সৈতে কাম নকৰিব পাৰে।"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"এপটোৱে বিভাজিত স্ক্ৰীণ সমৰ্থন নকৰে।"</string> + <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"এপ্টোৱে বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।"</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"গৌণ ডিছপ্লেত এপে সঠিকভাৱে কাম নকৰিব পাৰে।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"গৌণ ডিছপ্লেত এপ্ লঞ্চ কৰিব নোৱাৰি।"</string> - <string name="accessibility_divider" msgid="703810061635792791">"স্প্লিট স্ক্ৰীণৰ বিভাজক"</string> - <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"বাওঁফালৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> + <string name="accessibility_divider" msgid="703810061635792791">"স্প্লিট স্ক্ৰীনৰ বিভাজক"</string> + <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"বাওঁফালৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"বাওঁফালৰ স্ক্ৰীণখন ৭০% কৰক"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"বাওঁফালৰ স্ক্ৰীণখন ৫০% কৰক"</string> <string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"বাওঁফালৰ স্ক্ৰীণখন ৩০% কৰক"</string> - <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"সোঁফালৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> - <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"শীৰ্ষ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> + <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"সোঁফালৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> + <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"শীৰ্ষ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> <string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"শীর্ষ স্ক্ৰীণখন ৭০% কৰক"</string> <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ স্ক্ৰীণখন ৫০% কৰক"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"শীর্ষ স্ক্ৰীণখন ৩০% কৰক"</string> - <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"তলৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> + <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"তলৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড ব্যৱহাৰ কৰা"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"বাহিৰ হ’বলৈ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ ছোৱাইপ কৰক অথবা এপ্টোৰ ওপৰত যিকোনো ঠাইত টিপক"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"এখন হাতেৰে ব্যৱহাৰ কৰা ম\'ডটো আৰম্ভ কৰক"</string> <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"এখন হাতেৰে ব্যৱহাৰ কৰা ম\'ডটোৰ পৰা বাহিৰ হওক"</string> - <string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ bubblesৰ ছেটিংসমূহ"</string> + <string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ bubblesৰ ছেটিং"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"অভাৰফ্ল’"</string> <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"ষ্টেকত পুনৰ যোগ দিয়ক"</string> <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="APP_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string> @@ -58,7 +58,7 @@ <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"শীৰ্ষৰ সোঁফালে নিয়ক"</string> <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"বুটামটো বাওঁফালে নিয়ক"</string> <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"তলৰ সোঁফালে নিয়ক"</string> - <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ছেটিংসমূহ"</string> + <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ছেটিং"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"বাবল অগ্ৰাহ্য কৰক"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"বাৰ্তালাপ বাবল নকৰিব"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles ব্যৱহাৰ কৰি চাট কৰক"</string> diff --git a/libs/WindowManager/Shell/res/values-as/strings_tv.xml b/libs/WindowManager/Shell/res/values-as/strings_tv.xml index 6c223f45d9b3..170b2dbd458c 100644 --- a/libs/WindowManager/Shell/res/values-as/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-as/strings_tv.xml @@ -20,5 +20,5 @@ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"চিত্ৰৰ ভিতৰত চিত্ৰ"</string> <string name="pip_notification_unknown_title" msgid="2729870284350772311">"(শিৰোনামবিহীন কাৰ্যক্ৰম)"</string> <string name="pip_close" msgid="9135220303720555525">"পিপ বন্ধ কৰক"</string> - <string name="pip_fullscreen" msgid="7278047353591302554">"সম্পূৰ্ণ স্ক্ৰীণ"</string> + <string name="pip_fullscreen" msgid="7278047353591302554">"সম্পূৰ্ণ স্ক্ৰীন"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index e0654bd6bfef..ad5a68e407a3 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -61,7 +61,7 @@ <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> સેટિંગ"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"બબલને છોડી દો"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"વાતચીતને બબલ કરશો નહીં"</string> - <string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચેટ કરો"</string> + <string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચૅટ કરો"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string> <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"બબલને કોઈપણ સમયે નિયંત્રિત કરો"</string> <string name="bubbles_user_education_manage" msgid="3460756219946517198">"આ ઍપમાંથી બબલને બંધ કરવા માટે મેનેજ કરો પર ટૅપ કરો"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index 9c97ffe2d7e6..3c8aaa4e0778 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -18,7 +18,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string> - <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string> + <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index 9c97ffe2d7e6..3c8aaa4e0778 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -18,7 +18,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string> - <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string> + <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> 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 c0df06f2954f..ac97c8f80617 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 @@ -576,20 +576,17 @@ public class BubbleStackView extends FrameLayout mBubbleContainer.setActiveController(mStackAnimationController); hideFlyoutImmediate(); - if (!mPositioner.showingInTaskbar()) { - // Also, save the magnetized stack so we can dispatch touch events to it. - mMagnetizedObject = mStackAnimationController.getMagnetizedStack( - mMagneticTarget); - mMagnetizedObject.setMagnetListener(mStackMagnetListener); - } else { + if (mPositioner.showingInTaskbar()) { // In taskbar, the stack isn't draggable so we shouldn't dispatch touch events. mMagnetizedObject = null; + } else { + // Save the magnetized stack so we can dispatch touch events to it. + mMagnetizedObject = mStackAnimationController.getMagnetizedStack(); + mMagnetizedObject.clearAllTargets(); + mMagnetizedObject.addTarget(mMagneticTarget); + mMagnetizedObject.setMagnetListener(mStackMagnetListener); } - // Also, save the magnetized stack so we can dispatch touch events to it. - mMagnetizedObject = mStackAnimationController.getMagnetizedStack(mMagneticTarget); - mMagnetizedObject.setMagnetListener(mStackMagnetListener); - mIsDraggingStack = true; // Cancel animations to make the stack temporarily invisible, since we're now @@ -881,7 +878,6 @@ public class BubbleStackView extends FrameLayout mRelativeStackPositionBeforeRotation = null; } - setUpDismissView(); if (mIsExpanded) { // Re-draw bubble row and pointer for new orientation. beforeExpandedViewAnimation(); @@ -1043,10 +1039,9 @@ public class BubbleStackView extends FrameLayout contentResolver, "bubble_dismiss_radius", mBubbleSize * 2 /* default */); // Save the MagneticTarget instance for the newly set up view - we'll add this to the - // MagnetizedObjects. + // MagnetizedObjects when the dismiss view gets shown. mMagneticTarget = new MagnetizedObject.MagneticTarget( mDismissView.getCircle(), dismissRadius); - mBubbleContainer.bringToFront(); } 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 0802fb59a008..636e1452aa9b 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 @@ -1024,11 +1024,9 @@ public class StackAnimationController extends } /** - * Returns the {@link MagnetizedObject} instance for the bubble stack, with the provided - * {@link MagnetizedObject.MagneticTarget} added as a target. + * Returns the {@link MagnetizedObject} instance for the bubble stack. */ - public MagnetizedObject<StackAnimationController> getMagnetizedStack( - MagnetizedObject.MagneticTarget target) { + public MagnetizedObject<StackAnimationController> getMagnetizedStack() { if (mMagnetizedStack == null) { mMagnetizedStack = new MagnetizedObject<StackAnimationController>( mLayout.getContext(), @@ -1053,7 +1051,6 @@ public class StackAnimationController extends loc[1] = (int) mStackPosition.y; } }; - mMagnetizedStack.addTarget(target); mMagnetizedStack.setHapticsEnabled(true); mMagnetizedStack.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt index 9f6dd1f27b62..9e012598554b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt @@ -303,6 +303,13 @@ abstract class MagnetizedObject<T : Any>( } /** + * Removes all associated targets from this object. + */ + fun clearAllTargets() { + associatedTargets.clear() + } + + /** * Provide this method with all motion events that move the magnetized object. If the * location of the motion events moves within the magnetic field of a target, or indicate a * fling-to-target gesture, this method will return true and you should not move the object diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java index d3274706631b..9e1c61aac868 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java @@ -23,6 +23,7 @@ import android.content.Context; import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.view.ContextThemeWrapper; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.animation.LinearInterpolator; @@ -33,7 +34,6 @@ import android.window.DisplayAreaOrganizer; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.appcompat.view.ContextThemeWrapper; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 954ca14b4960..e511bffad247 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -445,6 +445,9 @@ public class OneHandedController implements RemoteCallable<OneHandedController> mOneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, mContext.getContentResolver(), mShortcutEnabledObserver, newUserId); + mOneHandedSettingsUtil.registerSettingsKeyObserver( + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, + mContext.getContentResolver(), mShortcutEnabledObserver, newUserId); } private void unregisterSettingObservers() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java index 7cf4fb7a811d..ff333c8c659d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java @@ -171,9 +171,22 @@ public final class OneHandedSettingsUtil { * @return true if user enabled one-handed shortcut in settings, false otherwise. */ public boolean getShortcutEnabled(ContentResolver resolver, int userId) { - final String targets = Settings.Secure.getStringForUser(resolver, + // Checks SOFTWARE_SHORTCUT_KEY + final String targetsSwKey = Settings.Secure.getStringForUser(resolver, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId); - return TextUtils.isEmpty(targets) ? false : targets.contains(ONE_HANDED_MODE_TARGET_NAME); + if (!TextUtils.isEmpty(targetsSwKey) && targetsSwKey.contains( + ONE_HANDED_MODE_TARGET_NAME)) { + return true; + } + + // Checks HARDWARE_SHORTCUT_KEY + final String targetsHwKey = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId); + if (!TextUtils.isEmpty(targetsHwKey) && targetsHwKey.contains( + ONE_HANDED_MODE_TARGET_NAME)) { + return true; + } + return false; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java index f58c6b173af9..81dd60d715e9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java @@ -32,6 +32,7 @@ import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.LayoutInflater; import android.view.SurfaceControl; @@ -44,7 +45,6 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.appcompat.view.ContextThemeWrapper; import com.android.internal.annotations.VisibleForTesting; import com.android.wm.shell.R; 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 4f3ec96968b2..63f1985aa86e 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 @@ -303,13 +303,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb mOneHandedController = oneHandedController; mPipTransitionController = pipTransitionController; mTaskStackListener = taskStackListener; - mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(), - INPUT_CONSUMER_PIP, mainExecutor); //TODO: move this to ShellInit when PipController can be injected mMainExecutor.execute(this::init); } public void init() { + mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(), + INPUT_CONSUMER_PIP, mMainExecutor); mPipTransitionController.registerPipTransitionCallback(this); mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> { mPipBoundsState.setDisplayId(displayId); 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 a5e96d14dde6..20021ebea834 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.content.res.Configuration; 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 @@ import com.android.wm.shell.common.SyncTransactionQueue; 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; @@ -306,6 +307,10 @@ class SizeCompatUILayout { 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 f634c4586e39..82f69c3e2985 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 @@ class SizeCompatUIWindowManager extends WindowlessWindowManager { } 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/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 29326ec90e31..cdd745ff9794 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -50,6 +50,7 @@ import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; +import android.view.ContextThemeWrapper; import android.view.SurfaceControl; import android.view.View; import android.window.SplashScreenView; @@ -299,6 +300,11 @@ public class SplashscreenContentDrawer { } } + /** Creates the wrapper with system theme to avoid unexpected styles from app. */ + ContextThemeWrapper createViewContextWrapper(Context appContext) { + return new ContextThemeWrapper(appContext, mContext.getTheme()); + } + /** The configuration of the splash screen window. */ public static class SplashScreenWindowAttrs { private int mWindowBgResId = 0; @@ -472,7 +478,8 @@ public class SplashscreenContentDrawer { } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon"); - final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext) + final ContextThemeWrapper wrapper = createViewContextWrapper(mContext); + final SplashScreenView.Builder builder = new SplashScreenView.Builder(wrapper) .setBackgroundColor(mThemeColor) .setOverlayDrawable(mOverlayDrawable) .setIconSize(iconSize) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 147f5e30f9d6..4dae63485f8c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -137,24 +137,11 @@ public class StartingSurfaceDrawer { private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts = new SparseArray<>(1); - /** Obtain proper context for showing splash screen on the provided display. */ - private Context getDisplayContext(Context context, int displayId) { - if (displayId == DEFAULT_DISPLAY) { - // The default context fits. - return context; - } - - final Display targetDisplay = mDisplayManager.getDisplay(displayId); - if (targetDisplay == null) { - // Failed to obtain the non-default display where splash screen should be shown, - // lets not show at all. - return null; - } - - return context.createDisplayContext(targetDisplay); + private Display getDisplay(int displayId) { + return mDisplayManager.getDisplay(displayId); } - private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) { + int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) { return splashScreenThemeResId != 0 ? splashScreenThemeResId : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource() @@ -177,7 +164,7 @@ public class StartingSurfaceDrawer { final int displayId = taskInfo.displayId; final int taskId = taskInfo.taskId; - Context context = mContext; + // replace with the default theme if the application didn't set final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo); if (DEBUG_SPLASH_SCREEN) { @@ -186,13 +173,16 @@ public class StartingSurfaceDrawer { + " suggestType=" + suggestType); } - // Obtain proper context to launch on the right display. - final Context displayContext = getDisplayContext(context, displayId); - if (displayContext == null) { + final Display display = getDisplay(displayId); + if (display == null) { // Can't show splash screen on requested display, so skip showing at all. return; } - context = displayContext; + Context context = displayId == DEFAULT_DISPLAY + ? mContext : mContext.createDisplayContext(display); + if (context == null) { + return; + } if (theme != context.getThemeResId()) { try { context = context.createPackageContextAsUser(activityInfo.packageName, @@ -303,7 +293,8 @@ public class StartingSurfaceDrawer { // Record whether create splash screen view success, notify to current thread after // create splash screen view finished. final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier(); - final FrameLayout rootLayout = new FrameLayout(context); + final FrameLayout rootLayout = new FrameLayout( + mSplashscreenContentDrawer.createViewContextWrapper(context)); rootLayout.setPadding(0, 0, 0, 0); rootLayout.setFitsSystemWindows(false); final Runnable setViewSynchronized = () -> { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index eef0d9bb268f..18b8faf4dbe6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -30,6 +30,7 @@ import static org.junit.Assert.assertNotEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -101,7 +102,6 @@ public class StartingSurfaceDrawerTests { static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{ int mAddWindowForTask = 0; - int mViewThemeResId; TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor, TransactionPool pool) { @@ -113,7 +113,6 @@ public class StartingSurfaceDrawerTests { View view, WindowManager wm, WindowManager.LayoutParams params, int suggestType) { // listen for addView mAddWindowForTask = taskId; - mViewThemeResId = view.getContext().getThemeResId(); // Do not wait for background color return false; } @@ -183,12 +182,15 @@ public class StartingSurfaceDrawerTests { final int taskId = 1; final StartingWindowInfo windowInfo = createWindowInfo(taskId, 0); + final int[] theme = new int[1]; + doAnswer(invocation -> theme[0] = (Integer) invocation.callRealMethod()) + .when(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any()); + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, STARTING_WINDOW_TYPE_SPLASH_SCREEN); waitHandlerIdle(mTestHandler); - verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(), - eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN)); - assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0); + verify(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any()); + assertNotEquals(theme[0], 0); } @Test diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index b8fa55a18dac..35449875d324 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -50,6 +50,7 @@ bool Properties::showDirtyRegions = false; bool Properties::skipEmptyFrames = true; bool Properties::useBufferAge = true; bool Properties::enablePartialUpdates = true; +bool Properties::enableRenderEffectCache = false; DebugLevel Properties::debugLevel = kDebugDisabled; OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default; @@ -84,7 +85,7 @@ float Properties::defaultSdrWhitePoint = 200.f; bool Properties::useHintManager = true; int Properties::targetCpuTimePercentage = 70; -bool Properties::enableWebViewOverlays = false; +bool Properties::enableWebViewOverlays = true; StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI; @@ -139,7 +140,7 @@ bool Properties::load() { targetCpuTimePercentage = base::GetIntProperty(PROPERTY_TARGET_CPU_TIME_PERCENTAGE, 70); if (targetCpuTimePercentage <= 0 || targetCpuTimePercentage > 100) targetCpuTimePercentage = 70; - enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false); + enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, true); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 7df6e2c92247..d224a547ab4d 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -224,6 +224,7 @@ public: static bool skipEmptyFrames; static bool useBufferAge; static bool enablePartialUpdates; + static bool enableRenderEffectCache; // TODO: Move somewhere else? static constexpr float textGamma = 1.45f; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 0c422df65881..b348a6ecaae4 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -341,6 +341,7 @@ std::optional<RenderNode::SnapshotResult> RenderNode::updateSnapshotIfRequired( sk_sp<SkImage> snapshot = layerSurface->makeImageSnapshot(); const auto subset = SkIRect::MakeWH(properties().getWidth(), properties().getHeight()); + uint32_t layerSurfaceGenerationId = layerSurface->generationID(); // If we don't have an ImageFilter just return the snapshot if (imageFilter == nullptr) { mSnapshotResult.snapshot = snapshot; @@ -348,9 +349,10 @@ std::optional<RenderNode::SnapshotResult> RenderNode::updateSnapshotIfRequired( mSnapshotResult.outOffset = SkIPoint::Make(0.0f, 0.0f); mImageFilterClipBounds = clipBounds; mTargetImageFilter = nullptr; - } else if (mSnapshotResult.snapshot == nullptr || - imageFilter != mTargetImageFilter.get() || - mImageFilterClipBounds != clipBounds) { + mTargetImageFilterLayerSurfaceGenerationId = 0; + } else if (mSnapshotResult.snapshot == nullptr || imageFilter != mTargetImageFilter.get() || + mImageFilterClipBounds != clipBounds || + mTargetImageFilterLayerSurfaceGenerationId != layerSurfaceGenerationId) { // Otherwise create a new snapshot with the given filter and snapshot mSnapshotResult.snapshot = snapshot->makeWithFilter(context, @@ -361,6 +363,7 @@ std::optional<RenderNode::SnapshotResult> RenderNode::updateSnapshotIfRequired( &mSnapshotResult.outOffset); mTargetImageFilter = sk_ref_sp(imageFilter); mImageFilterClipBounds = clipBounds; + mTargetImageFilterLayerSurfaceGenerationId = layerSurfaceGenerationId; } return mSnapshotResult; diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 45a4f6c9c70d..da0476259b97 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -396,6 +396,7 @@ private: * SkImageFilter used to create the mSnapshotResult */ sk_sp<SkImageFilter> mTargetImageFilter; + uint32_t mTargetImageFilterLayerSurfaceGenerationId = 0; /** * Clip bounds used to create the mSnapshotResult diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 7556af918170..48145d2331ee 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -231,14 +231,33 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer); SkPaint paint; layerNeedsPaint(layerProperties, alphaMultiplier, &paint); - const auto snapshotResult = renderNode->updateSnapshotIfRequired( - canvas->recordingContext(), - layerProperties.getImageFilter(), - clipBounds.roundOut() - ); - sk_sp<SkImage> snapshotImage = snapshotResult->snapshot; - srcBounds = snapshotResult->outSubset; - offset = snapshotResult->outOffset; + sk_sp<SkImage> snapshotImage; + auto* imageFilter = layerProperties.getImageFilter(); + auto recordingContext = canvas->recordingContext(); + // On some GL vendor implementations, caching the result of + // getLayerSurface->makeImageSnapshot() causes a call to + // Fence::waitForever without a corresponding signal. This would + // lead to ANRs throughout the system. + // Instead only cache the SkImage created with the SkImageFilter + // for supported devices. Otherwise just create a new SkImage with + // the corresponding SkImageFilter each time. + // See b/193145089 and b/197263715 + if (!Properties::enableRenderEffectCache) { + snapshotImage = renderNode->getLayerSurface()->makeImageSnapshot(); + if (imageFilter) { + auto subset = SkIRect::MakeWH(srcBounds.width(), srcBounds.height()); + snapshotImage = snapshotImage->makeWithFilter(recordingContext, imageFilter, + subset, clipBounds.roundOut(), + &srcBounds, &offset); + } + } else { + const auto snapshotResult = renderNode->updateSnapshotIfRequired( + recordingContext, layerProperties.getImageFilter(), clipBounds.roundOut()); + snapshotImage = snapshotResult->snapshot; + srcBounds = snapshotResult->outSubset; + offset = snapshotResult->outOffset; + } + const auto dstBounds = SkIRect::MakeXYWH(offset.x(), offset.y(), srcBounds.width(), diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index a11678189bad..383c79b27918 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -146,6 +146,9 @@ void EglManager::initialize() { LOG_ALWAYS_FATAL("Unsupported wide color space."); } mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension; + + auto* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); + Properties::enableRenderEffectCache = (strcmp(vendor, "Qualcomm") != 0); } EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavior swapBehavior) { diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java index dc1e99fd6a4f..2b978f759a13 100644 --- a/location/java/android/location/GpsNavigationMessage.java +++ b/location/java/android/location/GpsNavigationMessage.java @@ -262,12 +262,8 @@ public class GpsNavigationMessage implements Parcelable { parcel.readByteArray(data); navigationMessage.setData(data); - if (parcel.dataAvail() >= Integer.SIZE) { - int status = parcel.readInt(); - navigationMessage.setStatus((short) status); - } else { - navigationMessage.setStatus(STATUS_UNKNOWN); - } + int status = parcel.readInt(); + navigationMessage.setStatus((short) status); return navigationMessage; } diff --git a/media/OWNERS b/media/OWNERS index abfc8bfa976e..0aff43e00671 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -1,8 +1,7 @@ -chz@google.com +# Bug component: 1344 elaurent@google.com essick@google.com etalvala@google.com -gkasten@google.com hdmoon@google.com hkuang@google.com hunga@google.com @@ -13,16 +12,13 @@ jmtrivi@google.com jsharkey@android.com klhyun@google.com lajos@google.com -marcone@google.com nchalko@google.com philburk@google.com quxiangfang@google.com wonsik@google.com -# LON -andrewlewis@google.com -aquilescanta@google.com -olly@google.com +# go/android-fwk-media-solutions for info on areas of ownership. +include platform/frameworks/av:/media/janitors/media_solutions_OWNERS # SEO sungsoo@google.com diff --git a/media/java/android/media/IMediaRouterClient.aidl b/media/java/android/media/IMediaRouterClient.aidl index 6b754e157cfb..9b4912373122 100644 --- a/media/java/android/media/IMediaRouterClient.aidl +++ b/media/java/android/media/IMediaRouterClient.aidl @@ -23,5 +23,4 @@ oneway interface IMediaRouterClient { void onStateChanged(); void onRestoreRoute(); void onGroupRouteSelected(String routeId); - void onGlobalA2dpChanged(boolean a2dpOn); } diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 345d9b27c8a8..2986f7c75f4d 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -654,9 +654,12 @@ public class MediaRouter { final class Client extends IMediaRouterClient.Stub { @Override public void onStateChanged() { - mHandler.post(() -> { - if (Client.this == mClient) { - updateClientState(); + mHandler.post(new Runnable() { + @Override + public void run() { + if (Client.this == mClient) { + updateClientState(); + } } }); } @@ -690,26 +693,6 @@ public class MediaRouter { } }); } - - // Called when the selection of a connected device (phone speaker or BT devices) - // is changed. - @Override - public void onGlobalA2dpChanged(boolean a2dpOn) { - mHandler.post(() -> { - if (mSelectedRoute == null || mBluetoothA2dpRoute == null) { - return; - } - if (mSelectedRoute.isDefault() && a2dpOn) { - setSelectedRoute(mBluetoothA2dpRoute, /*explicit=*/ false); - dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo); - dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute); - } else if (mSelectedRoute.isBluetooth() && !a2dpOn) { - setSelectedRoute(mDefaultAudioVideo, /*explicit=*/ false); - dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute); - dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo); - } - }); - } } } @@ -1367,9 +1350,6 @@ public class MediaRouter { } static void dispatchRouteSelected(int type, RouteInfo info) { - if (DEBUG) { - Log.d(TAG, "Dispatching route selected: " + info); - } for (CallbackInfo cbi : sStatic.mCallbacks) { if (cbi.filterRouteEvent(info)) { cbi.cb.onRouteSelected(cbi.router, type, info); @@ -1378,9 +1358,6 @@ public class MediaRouter { } static void dispatchRouteUnselected(int type, RouteInfo info) { - if (DEBUG) { - Log.d(TAG, "Dispatching route unselected: " + info); - } for (CallbackInfo cbi : sStatic.mCallbacks) { if (cbi.filterRouteEvent(info)) { cbi.cb.onRouteUnselected(cbi.router, type, info); diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS index cf06fad3e203..813dee3d3e71 100644 --- a/media/java/android/media/OWNERS +++ b/media/java/android/media/OWNERS @@ -1,9 +1,9 @@ # Bug component: 1344 - fgoldfain@google.com elaurent@google.com lajos@google.com -olly@google.com -andrewlewis@google.com sungsoo@google.com jmtrivi@google.com + +# go/android-fwk-media-solutions for info on areas of ownership. +include platform/frameworks/av:/media/janitors/media_solutions_OWNERS diff --git a/mms/OWNERS b/mms/OWNERS index 7f05a2a24d6e..2e419c1e529c 100644 --- a/mms/OWNERS +++ b/mms/OWNERS @@ -9,10 +9,10 @@ jackyu@google.com jminjie@google.com satk@google.com shuoq@google.com -nazaninb@google.com sarahchin@google.com xiaotonj@google.com huiwang@google.com jayachandranc@google.com chinmayd@google.com amruthr@google.com +sasindran@google.com diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS index 0d23f053499c..a2352e20f841 100644 --- a/packages/CarrierDefaultApp/OWNERS +++ b/packages/CarrierDefaultApp/OWNERS @@ -8,11 +8,11 @@ jackyu@google.com jminjie@google.com satk@google.com shuoq@google.com -nazaninb@google.com sarahchin@google.com xiaotonj@google.com huiwang@google.com jayachandranc@google.com chinmayd@google.com amruthr@google.com +sasindran@google.com diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml index 48cdf1647d86..197b7b2b0eaf 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 5d7b9bb36f75..cef9014ec229 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 11e01c7ce51d..806734ffa997 100644 --- a/packages/PackageInstaller/res/values-te/strings.xml +++ b/packages/PackageInstaller/res/values-te/strings.xml @@ -45,14 +45,14 @@ <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ఖాళీ లేదు"</string> <string name="out_of_space_dlg_text" msgid="8727714096031856231">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని ఇన్స్టాల్ చేయడం సాధ్యపడలేదు. కొంత స్థలాన్ని ఖాళీ చేసి మళ్లీ ప్రయత్నించండి."</string> <string name="app_not_found_dlg_title" msgid="5107924008597470285">"యాప్ కనుగొనబడలేదు"</string> - <string name="app_not_found_dlg_text" msgid="5219983779377811611">"ఇన్స్టాల్ చేసిన యాప్ల జాబితాలో యాప్ కనుగొనబడలేదు."</string> + <string name="app_not_found_dlg_text" msgid="5219983779377811611">"ఇన్స్టాల్ చేసిన యాప్ల లిస్ట్లో యాప్ కనుగొనబడలేదు."</string> <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"అనుమతించబడలేదు"</string> <string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"ప్రస్తుత వినియోగదారు ఈ అన్ఇన్స్టాలేషన్ చేసేందుకు అనుమతించబడరు."</string> <string name="generic_error_dlg_title" msgid="5863195085927067752">"లోపం"</string> <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/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java index 5f107d662b75..34e7e3d1cd6b 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java @@ -84,8 +84,7 @@ public class MDNSFilterPlugin implements PrintServicePlugin { */ public MDNSFilterPlugin(@NonNull Context context, @NonNull String name, @NonNull CharSequence packageName, @NonNull List<String> mDNSNames) { - mName = context.getResources().getIdentifier(name, null, - "com.android.printservice.recommendation"); + mName = context.getResources().getIdentifier(name, null, context.getPackageName()); mPackageName = packageName; mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPES, new VendorNameFilter(new HashSet<>(mDNSNames))); diff --git a/packages/PrintSpooler/res/values-as/strings.xml b/packages/PrintSpooler/res/values-as/strings.xml index b6b287ff66aa..a93fceb87959 100644 --- a/packages/PrintSpooler/res/values-as/strings.xml +++ b/packages/PrintSpooler/res/values-as/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDFৰ জৰিয়তে ছেভ কৰক"</string> <string name="print_options_expanded" msgid="6944679157471691859">"প্ৰিণ্ট বিকল্পসমূহ বিস্তাৰ কৰা হ’ল"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"প্ৰিণ্ট বিকল্পসমূহ সংকুচিত কৰা হ’ল"</string> - <string name="search" msgid="5421724265322228497">"Search"</string> + <string name="search" msgid="5421724265322228497">"সন্ধান কৰক"</string> <string name="all_printers_label" msgid="3178848870161526399">"সকলো প্ৰিণ্টাৰ"</string> <string name="add_print_service_label" msgid="5356702546188981940">"সেৱা যোগ কৰক"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সন্ধান বাকচটো দেখুওৱা হ’ল"</string> diff --git a/packages/PrintSpooler/res/values-kn/strings.xml b/packages/PrintSpooler/res/values-kn/strings.xml index 261fe4b0de9a..150ede4f8e62 100644 --- a/packages/PrintSpooler/res/values-kn/strings.xml +++ b/packages/PrintSpooler/res/values-kn/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF ಗೆ ಉಳಿಸು"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ವಿಸ್ತರಿಸಲಾಗಿದೆ"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string> - <string name="search" msgid="5421724265322228497">"Search"</string> + <string name="search" msgid="5421724265322228497">"ಹುಡುಕಿ"</string> <string name="all_printers_label" msgid="3178848870161526399">"ಎಲ್ಲಾ ಪ್ರಿಂಟರ್ಗಳು"</string> <string name="add_print_service_label" msgid="5356702546188981940">"ಸೇವೆಯನ್ನು ಸೇರಿಸು"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯನ್ನು ತೋರಿಸಲಾಗಿದೆ"</string> diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml index 73af95d2e117..dbcd34b1360d 100644 --- a/packages/PrintSpooler/res/values-ml/strings.xml +++ b/packages/PrintSpooler/res/values-ml/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF-ൽ സംരക്ഷിക്കുക"</string> <string name="print_options_expanded" msgid="6944679157471691859">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ വിപുലീകരിച്ചു"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ ചുരുക്കി"</string> - <string name="search" msgid="5421724265322228497">"Search"</string> + <string name="search" msgid="5421724265322228497">"തിരയൽ"</string> <string name="all_printers_label" msgid="3178848870161526399">"എല്ലാ പ്രിന്ററുകളും"</string> <string name="add_print_service_label" msgid="5356702546188981940">"സേവനം ചേർക്കുക"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"തിരയൽ ബോക്സ് ദൃശ്യമാക്കിയിരിക്കുന്നു"</string> diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml index 81194399c00e..e1fa3902cdf0 100644 --- a/packages/PrintSpooler/res/values-mr/strings.xml +++ b/packages/PrintSpooler/res/values-mr/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ वर सेव्ह करा"</string> <string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट पर्याय विस्तृत झाले"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"प्रिंट पर्याय संक्षिप्त झाले"</string> - <string name="search" msgid="5421724265322228497">"Search"</string> + <string name="search" msgid="5421724265322228497">"शोधा"</string> <string name="all_printers_label" msgid="3178848870161526399">"सर्व प्रिंटर"</string> <string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोडा"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"शोध बॉक्स दर्शविला"</string> diff --git a/packages/PrintSpooler/res/values-or/strings.xml b/packages/PrintSpooler/res/values-or/strings.xml index d6f920fa217a..fa10909b92ed 100644 --- a/packages/PrintSpooler/res/values-or/strings.xml +++ b/packages/PrintSpooler/res/values-or/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDFରେ ସେଭ୍ କରନ୍ତୁ"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ବଡ଼ କରାଯାଇଛି"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ଛୋଟ କରାଯାଇଛି"</string> - <string name="search" msgid="5421724265322228497">"Search"</string> + <string name="search" msgid="5421724265322228497">"ସନ୍ଧାନ କରନ୍ତୁ"</string> <string name="all_printers_label" msgid="3178848870161526399">"ସମସ୍ତ ପ୍ରିଣ୍ଟର୍"</string> <string name="add_print_service_label" msgid="5356702546188981940">"ସେବା ଯୋଗ କରନ୍ତୁ"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ସର୍ଚ୍ଚ ବକ୍ସ ଦେଖାଯାଇଛି"</string> diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml index 9e2f4799424c..c471ab188eb5 100644 --- a/packages/PrintSpooler/res/values-ru/strings.xml +++ b/packages/PrintSpooler/res/values-ru/strings.xml @@ -24,7 +24,7 @@ <string name="label_paper_size" msgid="908654383827777759">"Размер бумаги"</string> <string name="label_paper_size_summary" msgid="5668204981332138168">"Размер бумаги:"</string> <string name="label_color" msgid="1108690305218188969">"Печать"</string> - <string name="label_duplex" msgid="5370037254347072243">"Двусторонний"</string> + <string name="label_duplex" msgid="5370037254347072243">"С двух сторон"</string> <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string> <string name="label_pages" msgid="7768589729282182230">"Страницы"</string> <string name="destination_default_text" msgid="5422708056807065710">"Выберите принтер"</string> diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml index cf0e0f6b506e..50e6f3b7dac5 100644 --- a/packages/PrintSpooler/res/values-te/strings.xml +++ b/packages/PrintSpooler/res/values-te/strings.xml @@ -50,8 +50,8 @@ <string name="search" msgid="5421724265322228497">"సెర్చ్"</string> <string name="all_printers_label" msgid="3178848870161526399">"అన్ని ప్రింటర్లు"</string> <string name="add_print_service_label" msgid="5356702546188981940">"సేవను జోడించు"</string> - <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"శోధన పెట్టె చూపబడింది"</string> - <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"శోధన పెట్టె దాచబడింది"</string> + <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"సెర్చ్ బాక్స్ చూపబడింది"</string> + <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"సెర్చ్ బాక్స్ దాచబడింది"</string> <string name="print_add_printer" msgid="1088656468360653455">"ప్రింటర్ను జోడించు"</string> <string name="print_select_printer" msgid="7388760939873368698">"ప్రింటర్ను ఎంచుకోండి"</string> <string name="print_forget_printer" msgid="5035287497291910766">"ప్రింటర్ను విస్మరించు"</string> diff --git a/packages/SettingsLib/SearchWidget/res/values-as/strings.xml b/packages/SettingsLib/SearchWidget/res/values-as/strings.xml index d3f922ab841c..8d95131e0e15 100644 --- a/packages/SettingsLib/SearchWidget/res/values-as/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-as/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"সন্ধান সম্পৰ্কীয় ছেটিংসমূহ"</string> + <string name="search_menu" msgid="1914043873178389845">"সন্ধান সম্পৰ্কীয় ছেটিং"</string> </resources> diff --git a/packages/SettingsLib/SearchWidget/res/values-te/strings.xml b/packages/SettingsLib/SearchWidget/res/values-te/strings.xml index c5ece7454b22..dbad586f48d1 100644 --- a/packages/SettingsLib/SearchWidget/res/values-te/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-te/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"సెట్టింగ్లను వెతకండి"</string> + <string name="search_menu" msgid="1914043873178389845">"సెట్టింగ్లను సెర్చ్ చేయండి"</string> </resources> diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml index 2d55c5367877..a11da1bc9475 100644 --- a/packages/SettingsLib/res/values-as/arrays.xml +++ b/packages/SettingsLib/res/values-as/arrays.xml @@ -232,7 +232,7 @@ <item msgid="8612549335720461635">"৪কে. (সুৰক্ষিত)"</item> <item msgid="7322156123728520872">"৪কে. (বৰ্ধিত)"</item> <item msgid="7735692090314849188">"৪কে. (বৰ্ধিত, সুৰক্ষিত)"</item> - <item msgid="7346816300608639624">"৭২০পি., ১০৮০পি. (দ্বৈত স্ক্ৰীণ)"</item> + <item msgid="7346816300608639624">"৭২০পি., ১০৮০পি. (দ্বৈত স্ক্ৰীন)"</item> </string-array> <string-array name="enable_opengl_traces_entries"> <item msgid="4433736508877934305">"নাই"</item> @@ -247,7 +247,7 @@ </string-array> <string-array name="track_frame_time_entries"> <item msgid="634406443901014984">"অফ হৈ আছে"</item> - <item msgid="1288760936356000927">"স্ক্ৰীণত দণ্ড হিচাপে"</item> + <item msgid="1288760936356000927">"স্ক্ৰীনত দণ্ড হিচাপে"</item> <item msgid="5023908510820531131">"<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>ত"</item> </string-array> <string-array name="debug_hw_overdraw_entries"> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 1ae3452ac847..eafa87bbbf7d 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -155,7 +155,7 @@ <string name="running_process_item_user_label" msgid="3988506293099805796">"ব্যৱহাৰকাৰী: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="3631650616557252926">"কিছুমান ডিফ\'ল্ট ছেট কৰা হৈছে"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"কোনো ডিফ\'ল্ট ছেট কৰা হোৱা নাই"</string> - <string name="tts_settings" msgid="8130616705989351312">"পাঠৰ পৰা কথনৰ ছেটিংসমূহ"</string> + <string name="tts_settings" msgid="8130616705989351312">"পাঠৰ পৰা কথনৰ ছেটিং"</string> <string name="tts_settings_title" msgid="7602210956640483039">"পাঠৰ পৰা কথনৰ আউটপুট"</string> <string name="tts_default_rate_title" msgid="3964187817364304022">"কথা কোৱাৰ হাৰ"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"পাঠ কথনৰ বেগ"</string> @@ -177,8 +177,8 @@ <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> <string name="tts_status_checking" msgid="8026559918948285013">"পৰীক্ষা কৰি থকা হৈছে…"</string> - <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>ৰ বাবে ছেটিংসমূহ"</string> - <string name="tts_engine_settings_button" msgid="477155276199968948">"ইঞ্জিনৰ ছেটিংসমূহ লঞ্চ কৰক"</string> + <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>ৰ ছেটিং"</string> + <string name="tts_engine_settings_button" msgid="477155276199968948">"ইঞ্জিনৰ ছেটিং লঞ্চ কৰক"</string> <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> @@ -201,9 +201,9 @@ <string name="development_settings_enable" msgid="4285094651288242183">"বিকাশকৰ্তা বিষয়ক বিকল্পসমূহ সক্ষম কৰক"</string> <string name="development_settings_summary" msgid="8718917813868735095">"এপৰ বিকাশৰ বাবে বিকল্পসমূহ ছেট কৰক"</string> <string name="development_settings_not_available" msgid="355070198089140951">"এইজন ব্যৱহাৰকাৰীৰ বাবে বিকাশকৰ্তাৰ বিকল্পসমূহ উপলব্ধ নহয়"</string> - <string name="vpn_settings_not_available" msgid="2894137119965668920">"ভিপিএন ছেটিংসমূহ এই ব্যৱহাৰকাৰীজনৰ বাবে উপলব্ধ নহয়"</string> - <string name="tethering_settings_not_available" msgid="266821736434699780">"এই ব্যৱহাৰকাৰীৰ বাবে টেডাৰিং ছেটিংসমূহ উপলব্ধ নহয়"</string> - <string name="apn_settings_not_available" msgid="1147111671403342300">"এই ব্যৱহাৰকাৰীৰ বাবে একচেছ পইণ্টৰ নাম ছেটিংসমূহ উপলব্ধ নহয়"</string> + <string name="vpn_settings_not_available" msgid="2894137119965668920">"ভিপিএন ছেটিং এই ব্যৱহাৰকাৰীজনৰ বাবে উপলব্ধ নহয়"</string> + <string name="tethering_settings_not_available" msgid="266821736434699780">"এই ব্যৱহাৰকাৰীৰ বাবে টেডাৰিং ছেটিং উপলব্ধ নহয়"</string> + <string name="apn_settings_not_available" msgid="1147111671403342300">"এই ব্যৱহাৰকাৰীৰ বাবে এক্সেছ পইণ্টৰ নামৰ ছেটিং উপলব্ধ নহয়"</string> <string name="enable_adb" msgid="8072776357237289039">"ইউএছবি ডিবাগিং"</string> <string name="enable_adb_summary" msgid="3711526030096574316">"ইউএছবি সংযোগ হৈ থকাৰ অৱস্থাত ডিবাগ ম\'ড"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"ইউএছবি ডিবাগিং অনুমতিসমূহ প্ৰত্যাহাৰ কৰক"</string> @@ -238,7 +238,7 @@ <string name="bugreport_in_power" msgid="8664089072534638709">"বাগ ৰিপৰ্টৰ শ্ৱৰ্টকাট"</string> <string name="bugreport_in_power_summary" msgid="1885529649381831775">"পাৱাৰ মেনুত বাগ প্ৰতিবেদন গ্ৰহণ কৰিবলৈ এটা বুটাম দেখুৱাওক"</string> <string name="keep_screen_on" msgid="1187161672348797558">"জাগ্ৰত কৰি ৰাখক"</string> - <string name="keep_screen_on_summary" msgid="1510731514101925829">"চ্চাৰ্জ হৈ থকাৰ সময়ত স্ক্ৰীণ কেতিয়াও সুপ্ত অৱস্থালৈ নাযায়"</string> + <string name="keep_screen_on_summary" msgid="1510731514101925829">"চ্চাৰ্জ হৈ থকাৰ সময়ত স্ক্ৰীন কেতিয়াও সুপ্ত অৱস্থালৈ নাযায়"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ব্লুটুথ HCI স্নুপ ল’গ সক্ষম কৰক"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"ব্লুটুথ পেকেট সংগ্ৰহ কৰক। (এই ছেটিংটো সলনি কৰাৰ পিছত ব্লুটুথ ট’গল কৰক)"</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"ঔইএম আনলক"</string> @@ -305,7 +305,7 @@ <string name="adbwifi_warning_title" msgid="727104571653031865">"ৱায়াৰলেচ ডি\'বাগিংৰ অনুমতি দিবনে?"</string> <string name="adbwifi_warning_message" msgid="8005936574322702388">"ৱায়াৰলেচ ডি\'বাগিং কেৱল বিকাশৰ উদ্দেশ্যেৰে কৰা হয়। আপোনাৰ কম্পিউটাৰ আৰু আপোনাৰ ডিভাইচৰ মাজত ডেটা প্ৰতিলিপি কৰিবলৈ, কোনো জাননী নিদিয়াকৈয়ে আপোনাৰ ডিভাইচত এপ্সমূহ ইনষ্টল কৰিবলৈ আৰু লগ ডেটা পঢ়িবলৈ এইটো ব্যৱহাৰ কৰক।"</string> <string name="adb_keys_warning_message" msgid="2968555274488101220">"আপুনি আগতে ইউএছবি ডিবাগিঙৰ বাবে প্ৰৱেশৰ অনুমতি দিয়া সকলো কম্পিউটাৰৰ পৰা সেই অনুমতি প্ৰত্যাহাৰ কৰেনে?"</string> - <string name="dev_settings_warning_title" msgid="8251234890169074553">"বিকাশৰ কামৰ বাবে থকা ছেটিংবিলাকক অনুমতি দিবনে?"</string> + <string name="dev_settings_warning_title" msgid="8251234890169074553">"বিকাশৰ কামৰ বাবে থকা ছেটিঙৰ অনুমতি দিবনে?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"এই ছেটিংসমূহ বিকাশৰ কামত ব্যৱহাৰ কৰিবলৈ তৈয়াৰ কৰা হৈছে। সেইবিলাকে আপোনাৰ ডিভাইচ আৰু তাত থকা এপ্লিকেশ্বনসমূহক অকামিলা কৰি পেলাব পাৰে আৰু সেইবিলাকৰ কাৰণে এপ্লিকেশ্বনসমূহে অদ্ভুত আচৰণ কৰিব পাৰে।"</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"ইউএছবিৰ যোগেৰে এপৰ সত্যাপন কৰক"</string> <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADTৰ যোগেৰে ইনষ্টল কৰা এপসমূহে কিবা ক্ষতিকাৰক আচৰণ কৰিছে নেকি পৰীক্ষা কৰক।"</string> @@ -331,9 +331,9 @@ <string name="media_category" msgid="8122076702526144053">"মিডিয়া"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"নিৰীক্ষণ কৰি থকা হৈছে"</string> <string name="strict_mode" msgid="889864762140862437">"কঠোৰ ম’ড সক্ষম কৰা হৈছে"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"যেতিয়া এপসমূহে মুখ্য থ্ৰেডত দীঘলীয়া কাৰ্যকলাপ চলাই, তেতিয়া স্ক্ৰীণ ফ্লাশ্ব কৰক"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"যেতিয়া এপ্সমূহে মুখ্য থ্ৰেডত দীঘলীয়া কাৰ্যকলাপ চলাই, তেতিয়া স্ক্ৰীন ফ্লাশ্ব কৰক"</string> <string name="pointer_location" msgid="7516929526199520173">"পইণ্টাৰৰ অৱস্থান"</string> - <string name="pointer_location_summary" msgid="957120116989798464">"চলিত স্পৰ্শ-বিষয়ক তথ্যসহ স্ক্ৰীণ অভাৰলে\'"</string> + <string name="pointer_location_summary" msgid="957120116989798464">"চলিত স্পৰ্শ-বিষয়ক তথ্যসহ স্ক্ৰীন অভাৰলে’"</string> <string name="show_touches" msgid="8437666942161289025">"টেপসমূহ দেখুৱাওক"</string> <string name="show_touches_summary" msgid="3692861665994502193">"টিপিলে দৃশ্যায়িত ফীডবেক দিয়ক"</string> <string name="show_screen_updates" msgid="2078782895825535494">"পৃষ্ঠভাগৰ আপডেইট দেখুৱাওক"</string> @@ -344,7 +344,7 @@ <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"হাৰ্ডৱেৰ লেয়াৰ আপডেইট হওতে সিঁহতক সেউজীয়া ৰঙেৰে ফ্লাশ্ব কৰক"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU অভাৰড্ৰ ডিবাগ কৰক"</string> <string name="disable_overlays" msgid="4206590799671557143">"HW অ’ভাৰলে অক্ষম কৰক"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"স্ক্ৰীণ কম্প’জিট কৰাৰ বাবে সদায় জিপিইউ ব্যৱহাৰ কৰক"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"স্ক্ৰীন কম্প’জিট কৰাৰ বাবে সদায় জিপিইউ ব্যৱহাৰ কৰক"</string> <string name="simulate_color_space" msgid="1206503300335835151">"ৰঙৰ ঠাই ছিমিউলেইট কৰক"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ট্ৰেছ সক্ষম কৰক"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"ইউএছবি অডিঅ\' ৰাউটিং অক্ষম কৰক"</string> @@ -352,7 +352,7 @@ <string name="debug_layout" msgid="1659216803043339741">"লেআউটৰ সময় দেখুৱাওক"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"ক্লিপ বাউণ্ড, মাৰ্জিন আদিসমূহ দেখুৱাওক"</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"আৰটিএল চানেকিৰ দিশ বলেৰে সলনি কৰক"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"সকলো ভাষাৰ বাবে স্ক্ৰীণৰ চানেকিৰ দিশ RTLলৈ বলেৰে সলনি কৰক"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"সকলো ভাষাৰ বাবে স্ক্ৰীনৰ চানেকিৰ দিশ RTLলৈ বলেৰে সলনি কৰক"</string> <string name="window_blurs" msgid="6831008984828425106">"ৱিণ্ড’ স্তৰত অস্পষ্ট কৰাৰ অনুমতি দিয়ক"</string> <string name="force_msaa" msgid="4081288296137775550">"বল ৪গুণ MSAA"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 এপত ৪গুণ MSAA সক্ষম কৰক"</string> @@ -373,7 +373,7 @@ <string name="show_all_anrs" msgid="9160563836616468726">"নেপথ্য এএনআৰবোৰ দেখুৱাওক"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"নেপথ্য এপসমূহৰ বাবে এপে সঁহাৰি দিয়া নাই ডায়ল\'গ প্ৰদৰ্শন কৰক"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"জাননী চ্চেনেলৰ সকীয়নিসমূহ দেখুৱাওক"</string> - <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"কোনো এপে বৈধ চ্চেনেল নোহোৱাকৈ কোনো জাননী প\'ষ্ট কৰিলে স্ক্ৰীণত সকীয়নি প্ৰদৰ্শন হয়"</string> + <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"কোনো এপে বৈধ চ্চেনেল নোহোৱাকৈ কোনো জাননী প\'ষ্ট কৰিলে স্ক্ৰীনত সকীয়নি প্ৰদৰ্শন হয়"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"বাহ্যিক সঞ্চয়াগাৰত এপক বলেৰে অনুমতি দিয়ক"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক সঞ্চয়াগাৰত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"বলেৰে কাৰ্যকলাপসমূহৰ আকাৰ সলনি কৰিব পৰা কৰক"</string> @@ -468,7 +468,7 @@ <string name="external_source_trusted" msgid="1146522036773132905">"অনুমতি দিয়া হৈছে"</string> <string name="external_source_untrusted" msgid="5037891688911672227">"অনুমতি দিয়া হোৱা নাই"</string> <string name="install_other_apps" msgid="3232595082023199454">"অজ্ঞাত এপ্ ইনষ্টল কৰক"</string> - <string name="home" msgid="973834627243661438">"ছেটিংসমূহৰ গৃহপৃষ্ঠা"</string> + <string name="home" msgid="973834627243661438">"Settingsৰ গৃহপৃষ্ঠা"</string> <string-array name="battery_labels"> <item msgid="7878690469765357158">"০%"</item> <item msgid="8894873528875953317">"৫০%"</item> @@ -488,7 +488,7 @@ <string name="retail_demo_reset_title" msgid="1866911701095959800">"পাছৱৰ্ড দৰকাৰী"</string> <string name="active_input_method_subtypes" msgid="4232680535471633046">"সক্ৰিয়হৈ থকা ইনপুট পদ্ধতিসমূহ"</string> <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"ছিষ্টেমৰ ভাষা ব্যৱহাৰ কৰক"</string> - <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>ৰ ছেটিংবিলাক খুলিব পৰা নগ\'ল"</string> + <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>ৰ ছেটিং খুলিব পৰা নগ\'ল"</string> <string name="ime_security_warning" msgid="6547562217880551450">"এই ইনপুট পদ্ধতিটোৱে আপুনি টাইপ কৰা আপোনাৰ ব্যক্তিগত ডেটা যেনে পাছৱৰ্ডসমূহ আৰু ক্ৰেডিট কাৰ্ডৰ নম্বৰসমূহকে ধৰি সকলো পাঠ সংগ্ৰহ কৰিবলৈ সক্ষম হ\'ব পাৰে। <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> এপটোৰ লগত ই সংলগ্ন। এই ইনপুট পদ্ধতিটো ব্যৱহাৰ কৰেনে?"</string> <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"টোকা: ৰিবুট কৰাৰ পিছত আপুনি ফ\'নটো আনলক নকৰালৈকে এই এপটো ষ্টাৰ্ট নহ’ব"</string> <string name="ims_reg_title" msgid="8197592958123671062">"আইএমএছ পঞ্জীয়ন স্থিতি"</string> @@ -546,7 +546,7 @@ <string name="user_add_user_item_title" msgid="2394272381086965029">"ব্যৱহাৰকাৰী"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"সীমিত প্ৰ\'ফাইল"</string> <string name="user_add_user_title" msgid="5457079143694924885">"নতুন ব্যৱহাৰকাৰী যোগ কৰিবনে?"</string> - <string name="user_add_user_message_long" msgid="1527434966294733380">"আপুনি অতিৰিক্ত ব্য়ৱহাৰকাৰীক যোগ কৰি এই ডিভাইচটো অন্য় ব্য়ক্তিৰ সৈতে শ্বেয়াৰ কৰিব পাৰে। প্ৰতিজন ব্য়ৱহাৰকাৰীৰ বাবে নিজাকৈ ঠাই আছে যাক তেওঁলোকে এপ্, ৱালপেপাৰ আৰু অন্য়ান্য় বস্তুৰ বাবে নিজৰ উপযোগিতা অনুযায়ী ব্য়ৱহাৰ কৰিব পাৰে। ব্য়ৱহাৰকাৰীসকলে সকলোকে প্ৰভাৱান্বিত কৰা ৱাই-ফাইৰ নিচিনা ডিভাইচৰ ছেটিংসমূহ সাল-সলনি কৰিবও পাৰে।\n\nআপুনি যেতিয়া কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰে সেই ব্য়ক্তিজনে নিজেই নিজৰ বাবে ঠাই ছেট আপ কৰিব লাগিব।\n\nসকলো ব্য়ৱহাৰকাৰীএ অন্য় ব্য়ৱহাৰকাৰীৰ বাবে এপসমূহ আপডে’ট কৰিব পাৰে। সাধ্য় সুবিধাসমূহৰ ছেটিং আৰু সেৱাসমূহ নতুন ব্য়ৱহাৰকাৰীলৈ স্থানান্তৰ নহ\'বও পাৰে।"</string> + <string name="user_add_user_message_long" msgid="1527434966294733380">"আপুনি অতিৰিক্ত ব্য়ৱহাৰকাৰীক যোগ কৰি এই ডিভাইচটো অন্য় ব্য়ক্তিৰ সৈতে শ্বেয়াৰ কৰিব পাৰে। প্ৰতিজন ব্য়ৱহাৰকাৰীৰ বাবে নিজাকৈ ঠাই আছে যাক তেওঁলোকে এপ্, ৱালপেপাৰ আৰু অন্য়ান্য় বস্তুৰ বাবে নিজৰ উপযোগিতা অনুযায়ী ব্য়ৱহাৰ কৰিব পাৰে। ব্য়ৱহাৰকাৰীসকলে সকলোকে প্ৰভাৱান্বিত কৰা ৱাই-ফাইৰ নিচিনা ডিভাইচৰ ছেটিং সাল-সলনি কৰিবও পাৰে।\n\nআপুনি যেতিয়া কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰে সেই ব্য়ক্তিজনে নিজেই নিজৰ বাবে ঠাই ছেট আপ কৰিব লাগিব।\n\nসকলো ব্য়ৱহাৰকাৰীয়ে অন্য় ব্য়ৱহাৰকাৰীৰ বাবে এপ্সমূহ আপডে’ট কৰিব পাৰে। সাধ্য় সুবিধাসমূহৰ ছেটিং আৰু সেৱাসমূহ নতুন ব্য়ৱহাৰকাৰীলৈ স্থানান্তৰ নহ\'বও পাৰে।"</string> <string name="user_add_user_message_short" msgid="3295959985795716166">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰী যোগ কৰে, তেওঁ নিজৰ ঠাই ছেট আপ কৰা প্ৰয়োজন।\n\nযিকোনো ব্যৱহাৰকাৰীয়ে সকলো ব্যৱহাৰকাৰীৰ বাবে এপ্ আপডেইট কৰিব পাৰে।"</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"ব্যৱহাৰকাৰী এতিয়া ছেট আপ কৰিবনে?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"ডিভাইচটো লৈ নিজৰ ঠাই ছেটআপ কৰিবলৈ নতুন ব্যৱহাৰকাৰী উপলব্ধ থকাটো নিশ্চিত কৰক"</string> @@ -558,7 +558,7 @@ <string name="user_new_profile_name" msgid="2405500423304678841">"নতুন প্ৰ\'ফাইল"</string> <string name="user_info_settings_title" msgid="6351390762733279907">"ব্যৱহাৰকাৰীৰ তথ্য"</string> <string name="profile_info_settings_title" msgid="105699672534365099">"প্ৰ\'ফাইলৰ তথ্য"</string> - <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string> + <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ’ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপ্বিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীন লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string> <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যৱহাৰকাৰী সৃষ্টি কৰি থকা হৈছে…"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 67bc8496b9ed..9876539678ae 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -245,9 +245,9 @@ <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Tillad, at startindlæseren låses op"</string> <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Vil du tillade OEM-oplåsning?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ADVARSEL! Funktioner, der beskytter enheden, fungerer ikke på denne enhed, når denne indstilling er aktiveret."</string> - <string name="mock_location_app" msgid="6269380172542248304">"Vælg app til falsk placering"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"Der er ikke angivet nogen app til falsk placering"</string> - <string name="mock_location_app_set" msgid="4706722469342913843">"App til falsk placering: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="mock_location_app" msgid="6269380172542248304">"Vælg app til falsk lokation"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"Der er ikke angivet nogen app til falsk lokation"</string> + <string name="mock_location_app_set" msgid="4706722469342913843">"App til falsk lokation: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"Netværk"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"Certificering af trådløs skærm"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivér detaljeret Wi-Fi-logføring"</string> @@ -295,8 +295,8 @@ <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Vælg logbuffere, der skal gemmes permanent på enheden"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"Vælg USB-konfiguration"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Vælg USB-konfiguration"</string> - <string name="allow_mock_location" msgid="2102650981552527884">"Imiterede placeringer"</string> - <string name="allow_mock_location_summary" msgid="179780881081354579">"Tillad imiterede placeringer"</string> + <string name="allow_mock_location" msgid="2102650981552527884">"Imiterede lokationer"</string> + <string name="allow_mock_location_summary" msgid="179780881081354579">"Tillad imiterede lokationer"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Aktivér visning af attributinspektion"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Hold altid mobildata aktiveret, selv når Wi-Fi er aktiveret (for at skifte hurtigt mellem netværk)."</string> <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Brug hardwareacceleration ved netdeling, hvis det er muligt"</string> @@ -332,7 +332,7 @@ <string name="debug_monitoring_category" msgid="1597387133765424994">"Overvågning"</string> <string name="strict_mode" msgid="889864762140862437">"Striks tilstand aktiveret"</string> <string name="strict_mode_summary" msgid="1838248687233554654">"Blink med skærmen, når apps foretager handlinger på hovedtråd"</string> - <string name="pointer_location" msgid="7516929526199520173">"Markørens placering"</string> + <string name="pointer_location" msgid="7516929526199520173">"Markørens lokation"</string> <string name="pointer_location_summary" msgid="957120116989798464">"Skærmoverlejringen viser de aktuelle berøringsdata"</string> <string name="show_touches" msgid="8437666942161289025">"Vis tryk"</string> <string name="show_touches_summary" msgid="3692861665994502193">"Vis visuel feedback ved tryk"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index a7f5eac5542b..de974371ee86 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -304,7 +304,7 @@ <string name="adb_warning_message" msgid="8145270656419669221">"USB bidezko arazketa garapen-xedeetarako soilik dago diseinatuta. Erabil ezazu ordenagailuaren eta gailuaren artean datuak kopiatzeko, aplikazioak gailuan jakinarazi gabe instalatzeko eta erregistro-datuak irakurtzeko."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Hari gabeko arazketa baimendu nahi duzu?"</string> <string name="adbwifi_warning_message" msgid="8005936574322702388">"Hari gabeko arazketa garapen-xedeetarako soilik dago diseinatuta. Erabil ezazu ordenagailuaren eta gailuaren artean datuak kopiatzeko, gailuan aplikazioak jakinarazi gabe instalatzeko eta erregistroko datuak irakurtzeko."</string> - <string name="adb_keys_warning_message" msgid="2968555274488101220">"Aurretik baimendutako ordenagailu guztiei USB bidezko arazketarako sarbidea baliogabetu nahi diezu?"</string> + <string name="adb_keys_warning_message" msgid="2968555274488101220">"Aurretik baimendutako ordenagailu guztiei USB bidezko arazketarako sarbidea kendu nahi diezu?"</string> <string name="dev_settings_warning_title" msgid="8251234890169074553">"Baimendu garapenerako ezarpenak?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Ezarpen hauek garapen-xedeetarako pentsatu dira soilik. Baliteke ezarpenen eraginez gailua matxuratzea edo funtzionamendu okerra izatea."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Egiaztatu USB bidezko aplik."</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index b503fdbbc57b..693a6d2076e8 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-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 921caba34e13..108d86d185e0 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -286,7 +286,7 @@ <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Réduit la décharge de la batterie et améliore les performances du réseau"</string> <string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau Wi-Fi où le changement aléatoire d\'adresse MAC est activé"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Facturé à l\'usage"</string> - <string name="wifi_unmetered_label" msgid="6174142840934095093">"Non facturé à l\'usage"</string> + <string name="wifi_unmetered_label" msgid="6174142840934095093">"Sans compteur"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Tailles des tampons de l\'enregistreur"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Tailles enreg. par tampon journal"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Effacer l\'espace de stockage persistant de l\'enregistreur ?"</string> diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml index ea4cf44b342f..20662db52076 100644 --- a/packages/SettingsLib/res/values-in/arrays.xml +++ b/packages/SettingsLib/res/values-in/arrays.xml @@ -23,7 +23,7 @@ <string-array name="wifi_status"> <item msgid="1596683495752107015"></item> <item msgid="3288373008277313483">"Memindai..."</item> - <item msgid="6050951078202663628">"Menyambung…"</item> + <item msgid="6050951078202663628">"Menghubungkan…"</item> <item msgid="8356618438494652335">"Mengautentikasi…"</item> <item msgid="2837871868181677206">"Mendapatkan alamat IP…"</item> <item msgid="4613015005934755724">"Terhubung"</item> @@ -37,7 +37,7 @@ <string-array name="wifi_status_with_ssid"> <item msgid="5969842512724979061"></item> <item msgid="1818677602615822316">"Memindai..."</item> - <item msgid="8339720953594087771">"Menyambung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="8339720953594087771">"Menghubungkan ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="3028983857109369308">"Mengautentikasi dengan <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="4287401332778341890">"Mendapatkan alamat IP dari <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="1043944043827424501">"Terhubung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index c1403082e37b..8b20b87be5bd 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -26,21 +26,21 @@ <string name="wifi_disconnected" msgid="7054450256284661757">"Terputus"</string> <string name="wifi_disabled_generic" msgid="2651916945380294607">"Nonaktif"</string> <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Kegagalan Konfigurasi IP"</string> - <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Tidak tersambung karena jaringan berkualitas rendah"</string> + <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Tidak terhubung karena jaringan berkualitas rendah"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Kegagalan Sambungan Wi-Fi"</string> <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Masalah autentikasi"</string> - <string name="wifi_cant_connect" msgid="5718417542623056783">"Tidak dapat tersambung"</string> - <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Tidak dapat tersambung ke \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> + <string name="wifi_cant_connect" msgid="5718417542623056783">"Tidak dapat terhubung"</string> + <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Tidak dapat terhubung ke \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Periksa sandi dan coba lagi"</string> <string name="wifi_not_in_range" msgid="1541760821805777772">"Tidak dalam jangkauan"</string> - <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Tidak akan tersambung otomatis"</string> + <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Tidak akan terhubung otomatis"</string> <string name="wifi_no_internet" msgid="1774198889176926299">"Tidak ada akses internet"</string> <string name="saved_network" msgid="7143698034077223645">"Disimpan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="connected_to_metered_access_point" msgid="9179693207918156341">"Terhubung ke jaringan berbayar"</string> - <string name="connected_via_network_scorer" msgid="7665725527352893558">"Tersambung otomatis melalui %1$s"</string> - <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Otomatis tersambung melalui penyedia rating jaringan"</string> + <string name="connected_via_network_scorer" msgid="7665725527352893558">"Terhubung otomatis melalui %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Otomatis terhubung melalui penyedia rating jaringan"</string> <string name="connected_via_passpoint" msgid="7735442932429075684">"Terhubung melalui %1$s"</string> - <string name="connected_via_app" msgid="3532267661404276584">"Tersambung melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_app" msgid="3532267661404276584">"Terhubung melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="available_via_passpoint" msgid="1716000261192603682">"Tersedia melalui %1$s"</string> <string name="tap_to_sign_up" msgid="5356397741063740395">"Ketuk untuk mendaftar"</string> <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Tidak ada internet"</string> @@ -49,10 +49,10 @@ <string name="wifi_status_no_internet" msgid="3799933875988829048">"Tidak ada internet"</string> <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Perlu login"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Titik akses penuh untuk sementara"</string> - <string name="connected_via_carrier" msgid="1968057009076191514">"Tersambung melalui %1$s"</string> + <string name="connected_via_carrier" msgid="1968057009076191514">"Terhubung melalui %1$s"</string> <string name="available_via_carrier" msgid="465598683092718294">"Tersedia melalui %1$s"</string> <string name="osu_opening_provider" msgid="4318105381295178285">"Membuka <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="9107873364807159193">"Tidak dapat tersambung"</string> + <string name="osu_connect_failed" msgid="9107873364807159193">"Tidak dapat terhubung"</string> <string name="osu_completing_sign_up" msgid="8412636665040390901">"Menyelesaikan pendaftaran…"</string> <string name="osu_sign_up_failed" msgid="5605453599586001793">"Tidak dapat menyelesaikan pendaftaran. Ketuk untuk mencoba lagi."</string> <string name="osu_sign_up_complete" msgid="7640183358878916847">"Pendaftaran selesai. Menyambungkan…"</string> @@ -66,7 +66,7 @@ <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string> <string name="bluetooth_disconnected" msgid="7739366554710388701">"Sambungan terputus"</string> <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutus sambungan..."</string> - <string name="bluetooth_connecting" msgid="5871702668260192755">"Menyambung…"</string> + <string name="bluetooth_connecting" msgid="5871702668260192755">"Menghubungkan…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Terhubung<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_pairing" msgid="4269046942588193600">"Menyandingkan..."</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Terhubung (tanpa ponsel)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -96,12 +96,12 @@ <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string> <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Alat Bantu Dengar"</string> <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Terhubung ke Alat Bantu Dengar"</string> - <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Tersambung ke media audio"</string> - <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Tersambung ke audio ponsel"</string> + <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Terhubung ke media audio"</string> + <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Terhubung ke audio ponsel"</string> <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Sambungkan ke server transfer file"</string> - <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"Tersambung ke peta"</string> + <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"Terhubung ke peta"</string> <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"Terhubung ke SAP"</string> - <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Tidak tersambung kepada server transfer file"</string> + <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Tidak terhubung kepada server transfer file"</string> <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Terhubung ke perangkat masukan"</string> <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Terhubung ke perangkat untuk akses internet"</string> <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Berbagi koneksi internet lokal dengan perangkat"</string> @@ -116,7 +116,7 @@ <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Sambungkan"</string> <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SAMBUNGKAN"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Batal"</string> - <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Penyandingan memberi akses ke kontak dan histori panggilan saat tersambung"</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Penyandingan memberi akses ke kontak dan histori panggilan saat terhubung"</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Tidak dapat menyambungkan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Tidak dapat menyambungkan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g> karena PIN atau kode sandi salah."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Tidak dapat berkomunikasi dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> @@ -133,7 +133,7 @@ <string name="bluetooth_hearingaid_left_battery_level" msgid="7375621694748104876">"Kiri - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_hearingaid_right_battery_level" msgid="1850094448499089312">"Kanan - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi tidak aktif."</string> - <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi tidak tersambung."</string> + <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi tidak terhubung."</string> <string name="accessibility_wifi_one_bar" msgid="6025652717281815212">"Wi-Fi satu baris."</string> <string name="accessibility_wifi_two_bars" msgid="687800024970972270">"Wi-Fi dua baris"</string> <string name="accessibility_wifi_three_bars" msgid="779895671061950234">"Wi-Fi tiga baris."</string> @@ -205,7 +205,7 @@ <string name="tethering_settings_not_available" msgid="266821736434699780">"Setelan Penambatan tidak tersedia untuk pengguna ini"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"Setelan Nama Titik Akses tidak tersedia untuk pengguna ini"</string> <string name="enable_adb" msgid="8072776357237289039">"Debugging USB"</string> - <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB tersambung"</string> + <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB terhubung"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"Cabut otorisasi debug USB"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"Proses debug nirkabel"</string> <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode debug saat Wi-Fi terhubung"</string> @@ -217,19 +217,19 @@ <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sambungkan perangkat dengan kode penyambungan"</string> <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sambungkan perangkat baru menggunakan kode enam digit"</string> <string name="adb_paired_devices_title" msgid="5268997341526217362">"Perangkat disambungkan"</string> - <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Saat ini tersambung"</string> + <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Saat ini terhubung"</string> <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detail perangkat"</string> <string name="adb_device_forget" msgid="193072400783068417">"Lupakan"</string> <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Sidik jari perangkat: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string> <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Sambungan gagal"</string> - <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tersambung ke jaringan yang tepat"</string> + <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> terhubung ke jaringan yang tepat"</string> <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sambungkan dengan perangkat"</string> <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kode penyambungan Wi-Fi"</string> <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Penyambungan perangkat gagal"</string> <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan perangkat terhubung ke jaringan yang sama."</string> <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string> <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Menyambungkan perangkat…"</string> - <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak tersambung ke jaringan yang sama."</string> + <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak terhubung ke jaringan yang sama."</string> <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP & Port"</string> <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Memindai kode QR"</string> <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string> @@ -335,7 +335,7 @@ <string name="pointer_location" msgid="7516929526199520173">"Lokasi penunjuk"</string> <string name="pointer_location_summary" msgid="957120116989798464">"Hamparan layar menampilkan data sentuhan saat ini"</string> <string name="show_touches" msgid="8437666942161289025">"Tampilkan ketukan"</string> - <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan masukan untuk ketukan"</string> + <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan efek visual untuk ketukan"</string> <string name="show_screen_updates" msgid="2078782895825535494">"Lihat pembaruan permukaan"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"Sorot seluruh permukaan jendela saat diperbarui"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Tampilkan update tampilan"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 2fbe33e88056..0f381c966932 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -47,7 +47,7 @@ <string name="private_dns_broken" msgid="1984159464346556931">"Жеке DNS серверіне кіру мүмкін емес."</string> <string name="wifi_limited_connection" msgid="1184778285475204682">"Шектеулі байланыс"</string> <string name="wifi_status_no_internet" msgid="3799933875988829048">"Интернетпен байланыс жоқ"</string> - <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Есептік жазбаға кіру керек"</string> + <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Аккаунтқа кіру керек"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Кіру нүктесі уақытша бос емес"</string> <string name="connected_via_carrier" msgid="1968057009076191514">"%1$s арқылы қосылды"</string> <string name="available_via_carrier" msgid="465598683092718294">"%1$s арқылы қолжетімді"</string> @@ -542,7 +542,7 @@ <string name="delete_blob_text" msgid="2819192607255625697">"Ортақ деректерді жою"</string> <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Осы ортақ деректерді шынымен жойғыңыз келе ме?"</string> <string name="user_add_user_item_summary" msgid="5748424612724703400">"Пайдаланушылардың өздерінің қолданбалары мен мазмұны болады"</string> - <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Өз есептік жазбаңыздан қолданбалар мен мазмұнға қол жетімділікті шектеуіңізге болады"</string> + <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Өз аккаунтыңыздан қолданбалар мен мазмұнға қол жетімділікті шектеуіңізге болады"</string> <string name="user_add_user_item_title" msgid="2394272381086965029">"Пайдаланушы"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"Шектелген профайл"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Жаңа пайдаланушы қосылсын ба?"</string> diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml index 8322c0614b4f..50935b815d90 100644 --- a/packages/SettingsLib/res/values-ko/arrays.xml +++ b/packages/SettingsLib/res/values-ko/arrays.xml @@ -28,7 +28,7 @@ <item msgid="2837871868181677206">"IP 주소를 가져오는 중..."</item> <item msgid="4613015005934755724">"연결됨"</item> <item msgid="3763530049995655072">"일시 정지됨"</item> - <item msgid="7852381437933824454">"연결을 끊는 중…"</item> + <item msgid="7852381437933824454">"연결 해제 중…"</item> <item msgid="5046795712175415059">"연결 끊김"</item> <item msgid="2473654476624070462">"실패"</item> <item msgid="9146847076036105115">"차단됨"</item> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 97ad0a0ef347..c455c14b1226 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -65,7 +65,7 @@ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"만료됨"</string> <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string> <string name="bluetooth_disconnected" msgid="7739366554710388701">"연결 끊김"</string> - <string name="bluetooth_disconnecting" msgid="7638892134401574338">"연결을 끊는 중…"</string> + <string name="bluetooth_disconnecting" msgid="7638892134401574338">"연결 해제 중…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"연결 중…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"연결됨<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_pairing" msgid="4269046942588193600">"페어링 중..."</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 7387985cf457..29510a7fc422 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -305,7 +305,7 @@ <string name="adbwifi_warning_title" msgid="727104571653031865">"Мүчүлүштүктөрдү Wi-Fi аркылуу оңдоого уруксат бересизби?"</string> <string name="adbwifi_warning_message" msgid="8005936574322702388">"Мүчүлүштүктөрдү Wi-Fi аркылуу аныктоо – өндүрүү максатында гана түзүлгөн. Аны компьютериңиз менен түзмөгүңүздүн ортосунда маалыматты алмашуу, колдонмолорду түзмөгүңүзгө эскертүүсүз орнотуу жана маалыматтар таржымалын окуу үчүн колдонсоңуз болот."</string> <string name="adb_keys_warning_message" msgid="2968555274488101220">"Сиз мурун USB жөндөөлөрүнө уруксат берген бардык компүтерлердин жеткиси жокко чыгарылсынбы?"</string> - <string name="dev_settings_warning_title" msgid="8251234890169074553">"Жөндөөлөрдү өзгөртүү"</string> + <string name="dev_settings_warning_title" msgid="8251234890169074553">"Параметрлерди өзгөртүү"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Бул орнотуулар өндүрүүчүлөр үчүн гана берилген. Булар түзмөгүңүздүн колдонмолорун бузулушуна же туура эмес иштешине алып келиши мүмкүн."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Орнотулуучу колдонмону текшерүү"</string> <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT аркылуу орнотулган колдонмолордун коопсуздугу текшерилет."</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 864f177fcec9..11e443be927b 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -307,7 +307,7 @@ <string name="adb_keys_warning_message" msgid="2968555274488101220">"तुम्ही पूर्वी ऑथोराइझ केलेल्या सर्व संगणकांवरुन USB डीबग करण्यासाठी अॅक्सेस रीव्होक करायचा?"</string> <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिंग्जला अनुमती द्यायची?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"या सेटिंग्जचा हेतू फक्त विकास वापरासाठी आहे. त्यामुळे तुमचे डिव्हाइस आणि त्यावरील ॲप्लिकेशन ब्रेक होऊ शकतात किंवा नेहमीपेक्षा वेगळे वर्तन करू शकतात."</string> - <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB वर अॅप्स पडताळून पाहा"</string> + <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB वर अॅप्स पडताळून पहा"</string> <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक वर्तनासाठी ADB/ADT द्वारे इंस्टॉल अॅप्स तपासा."</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नावांशिवाय ब्लूटूथ डिव्हाइस (फक्त MAC पत्ते) दाखवले जातील"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"रिमोट डिव्हाइसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणाचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटूथ संपूर्ण आवाज वैशिष्ट्य बंद करते."</string> @@ -552,7 +552,7 @@ <string name="user_setup_dialog_message" msgid="269931619868102841">"तो वापरकर्ता डिव्हाइसजवळ आहे आणि त्याचे स्थान सेट करण्यासाठी उपलब्ध आहे याची खात्री करा"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"आता प्रोफाईल सेट करायचा?"</string> <string name="user_setup_button_setup_now" msgid="1708269547187760639">"आता सेट करा"</string> - <string name="user_setup_button_setup_later" msgid="8712980133555493516">"आत्ता नाही"</string> + <string name="user_setup_button_setup_later" msgid="8712980133555493516">"आता नको"</string> <string name="user_add_user_type_title" msgid="551279664052914497">"जोडा"</string> <string name="user_new_user_name" msgid="60979820612818840">"नवीन वापरकर्ता"</string> <string name="user_new_profile_name" msgid="2405500423304678841">"नवीन प्रोफाईल"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index c885c16cb5bf..8938fcf60473 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -155,7 +155,7 @@ <string name="running_process_item_user_label" msgid="3988506293099805796">"ଉପଯୋଗକର୍ତ୍ତା: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="3631650616557252926">"କିଛି ପୂର୍ବ-ନିର୍ଦ୍ଧାରିତ ମାନ ସେଟ୍ ହୋଇଛି"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"କୌଣସି ଡିଫଲ୍ଟ ସେଟ୍ ହୋଇନାହିଁ"</string> - <string name="tts_settings" msgid="8130616705989351312">"ଟେକ୍ସଟ-ରୁ-ସ୍ପିଚ୍ ସେଟିଂସ୍"</string> + <string name="tts_settings" msgid="8130616705989351312">"ଟେକ୍ସଟ୍-ଟୁ-ସ୍ପିଚ୍ ସେଟିଂସ"</string> <string name="tts_settings_title" msgid="7602210956640483039">"ଟେକ୍ସଟ୍-ଟୁ-ସ୍ପିଚ୍ ଆଉଟ୍ପୁଟ୍"</string> <string name="tts_default_rate_title" msgid="3964187817364304022">"ସ୍ପିଚ୍ ରେଟ୍"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"ଲେଖା ପଢ଼ିବାର ବେଗ"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 127f571a5529..940e5d3cac1b 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -164,11 +164,11 @@ <string name="tts_default_lang_title" msgid="4698933575028098940">"ਭਾਸ਼ਾ"</string> <string name="tts_lang_use_system" msgid="6312945299804012406">"ਸਿਸਟਮ ਭਾਸ਼ਾ ਵਰਤੋ"</string> <string name="tts_lang_not_selected" msgid="7927823081096056147">"ਭਾਸ਼ਾ ਨਹੀਂ ਚੁਣੀ"</string> - <string name="tts_default_lang_summary" msgid="9042620014800063470">"ਬੋਲੇ ਗਏ ਟੈਕਸਟ ਲਈ ਭਾਸ਼ਾ-ਵਿਸ਼ੇਸ਼ ਵੌਇਸ ਸੈਟ ਕਰਦਾ ਹੈ"</string> + <string name="tts_default_lang_summary" msgid="9042620014800063470">"ਬੋਲੀ ਗਈ ਲਿਖਤ ਲਈ ਭਾਸ਼ਾ-ਵਿਸ਼ੇਸ਼ ਅਵਾਜ਼ ਸੈੱਟ ਕਰਦਾ ਹੈ"</string> <string name="tts_play_example_title" msgid="1599468547216481684">"ਇੱਕ ਉਦਾਹਰਨ ਲਈ ਸੁਣੋ"</string> <string name="tts_play_example_summary" msgid="634044730710636383">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਛੋਟਾ ਪ੍ਰਦਰਸ਼ਨ ਪਲੇ ਕਰੋ"</string> - <string name="tts_install_data_title" msgid="1829942496472751703">"ਵੌਇਸ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string> - <string name="tts_install_data_summary" msgid="3608874324992243851">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੋੜੀਂਦਾ ਵੌਇਸ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string> + <string name="tts_install_data_title" msgid="1829942496472751703">"ਅਵਾਜ਼ੀ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string> + <string name="tts_install_data_summary" msgid="3608874324992243851">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੋੜੀਂਦਾ ਅਵਾਜ਼ੀ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string> <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> diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml index 93796ef12560..fc4915f3e261 100644 --- a/packages/SettingsLib/res/values-sk/arrays.xml +++ b/packages/SettingsLib/res/values-sk/arrays.xml @@ -59,7 +59,7 @@ <item msgid="6421717003037072581">"Vždy používať kontrolu HDCP"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> - <item msgid="695678520785580527">"Deaktivované"</item> + <item msgid="695678520785580527">"Vypnuté"</item> <item msgid="6336372935919715515">"Aktivované filtrované"</item> <item msgid="2779123106632690576">"Aktivované"</item> </string-array> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 4a3b32a3a90f..839853629569 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -84,7 +84,7 @@ <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"செயலில் உள்ளது"</string> <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"மீடியா ஆடியோ"</string> <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ஃபோன் அழைப்புகள்"</string> - <string name="bluetooth_profile_opp" msgid="6692618568149493430">"கோப்பு இடமாற்றம்"</string> + <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ஃபைல் இடமாற்றம்"</string> <string name="bluetooth_profile_hid" msgid="2969922922664315866">"உள்ளீட்டுச் சாதனம்"</string> <string name="bluetooth_profile_pan" msgid="1006235139308318188">"இணைய அணுகல்"</string> <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"தொடர்புப் பகிர்தல்"</string> @@ -101,7 +101,7 @@ <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ஃபைலைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string> <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"வரைபடத்துடன் இணைக்கப்பட்டது"</string> <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"SAP உடன் இணைக்கப்பட்டது"</string> - <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"கோப்பு இடமாற்றும் சேவையகத்துடன் இணைக்கப்படவில்லை"</string> + <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"ஃபைல் இடமாற்றும் சேவையகத்துடன் இணைக்கப்படவில்லை"</string> <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"உள்ளீட்டுச் சாதனத்துடன் இணைக்கப்பட்டது"</string> <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"சாதனத்துடன் இணைந்தது"</string> <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"சாதனத்துடன் உள்ளூர் இண்டர்நெட்டைப் பகிர்தல்"</string> @@ -110,7 +110,7 @@ <string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"சிம் அணுகலுக்குப் பயன்படுத்தும்"</string> <string name="bluetooth_a2dp_profile_summary_use_for" msgid="7324694226276491807">"மீடியாவின் ஆடியோவிற்குப் பயன்படுத்து"</string> <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"மொபைல் ஆடியோவைப் பயன்படுத்து"</string> - <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"கோப்பு பரிமாற்றத்திற்காகப் பயன்படுத்து"</string> + <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ஃபைல் பரிமாற்றத்திற்காகப் பயன்படுத்து"</string> <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"உள்ளீட்டுக்குப் பயன்படுத்து"</string> <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"செவித்துணை கருவிகளுக்குப் பயன்படுத்தவும்"</string> <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"இணை"</string> @@ -412,11 +412,11 @@ <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string> <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView செயல்படுத்தலை அமை"</string> <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"இனி இந்தத் தேர்வைப் பயன்படுத்த முடியாது. மீண்டும் முயலவும்."</string> - <string name="convert_to_file_encryption" msgid="2828976934129751818">"கோப்பு முறைமையாக்கத்திற்கு மாற்று"</string> + <string name="convert_to_file_encryption" msgid="2828976934129751818">"ஃபைல் முறைமையாக்கத்திற்கு மாற்று"</string> <string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"மாற்று…"</string> - <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"ஏற்கனவே கோப்பு என்க்ரிப்ட் செய்யப்பட்டது"</string> - <string name="title_convert_fbe" msgid="5780013350366495149">"கோப்பு சார்ந்த முறைமையாக்கத்திற்கு மாற்றுதல்"</string> - <string name="convert_to_fbe_warning" msgid="34294381569282109">"தரவுப் பகிர்வை, கோப்பு சார்ந்த முறைமையாக்கத்திற்கு மாற்றவும்.\n !!எச்சரிக்கை!! இது எல்லா தரவையும் அழிக்கும்.\n இது ஆல்பா நிலை அம்சமாக இருப்பதால் சரியாகச் செயல்படாமல் போகக்கூடும்.\n தொடர, \'அழித்து, மாற்று…\' என்பதை அழுத்தவும்."</string> + <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"ஏற்கனவே ஃபைல் என்க்ரிப்ட் செய்யப்பட்டது"</string> + <string name="title_convert_fbe" msgid="5780013350366495149">"ஃபைல் சார்ந்த முறைமையாக்கத்திற்கு மாற்றுதல்"</string> + <string name="convert_to_fbe_warning" msgid="34294381569282109">"தரவுப் பகிர்வை, ஃபைல் சார்ந்த முறைமையாக்கத்திற்கு மாற்றவும்.\n !!எச்சரிக்கை!! இது எல்லா தரவையும் அழிக்கும்.\n இது ஆல்பா நிலை அம்சமாக இருப்பதால் சரியாகச் செயல்படாமல் போகக்கூடும்.\n தொடர, \'அழித்து, மாற்று…\' என்பதை அழுத்தவும்."</string> <string name="button_convert_fbe" msgid="1159861795137727671">"அழித்து மாற்று…"</string> <string name="picture_color_mode" msgid="1013807330552931903">"படத்தின் வண்ணப் பயன்முறை"</string> <string name="picture_color_mode_desc" msgid="151780973768136200">"sRGBஐப் பயன்படுத்தும்"</string> diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml index db3002f2ff23..1ecbb3cbbcc2 100644 --- a/packages/SettingsLib/res/values-te/arrays.xml +++ b/packages/SettingsLib/res/values-te/arrays.xml @@ -25,7 +25,7 @@ <item msgid="3288373008277313483">"స్కాన్ చేస్తోంది…"</item> <item msgid="6050951078202663628">"కనెక్ట్ చేస్తోంది..."</item> <item msgid="8356618438494652335">"ప్రామాణీకరిస్తోంది…"</item> - <item msgid="2837871868181677206">"IP చిరునామాను పొందుతోంది…"</item> + <item msgid="2837871868181677206">"IP అడ్రస్ను పొందుతోంది…"</item> <item msgid="4613015005934755724">"కనెక్ట్ చేయబడింది"</item> <item msgid="3763530049995655072">"తాత్కాలికంగా రద్దు చేయబడింది"</item> <item msgid="7852381437933824454">"డిస్కనెక్ట్ చేస్తోంది..."</item> @@ -39,7 +39,7 @@ <item msgid="1818677602615822316">"స్కాన్ చేస్తోంది…"</item> <item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>కి కనెక్ట్ చేస్తోంది…"</item> <item msgid="3028983857109369308">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>తో ప్రామాణీకరిస్తోంది…"</item> - <item msgid="4287401332778341890">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> నుండి IP చిరునామాను పొందుతోంది…"</item> + <item msgid="4287401332778341890">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> నుండి IP అడ్రస్ను పొందుతోంది…"</item> <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది"</item> <item msgid="7445993821842009653">"తాత్కాలికంగా రద్దు చేయబడింది"</item> <item msgid="1175040558087735707">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> నుండి డిస్కనెక్ట్ చేస్తోంది…"</item> @@ -76,7 +76,7 @@ <item msgid="1963366694959681026">"avrcp16"</item> </string-array> <string-array name="bluetooth_map_versions"> - <item msgid="8786402640610987099">"MAP 1.2 (డిఫాల్ట్)"</item> + <item msgid="8786402640610987099">"MAP 1.2 (ఆటోమేటిక్)"</item> <item msgid="6817922176194686449">"MAP 1.3"</item> <item msgid="3423518690032737851">"MAP 1.4"</item> </string-array> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 6df6d2d00298..545cf9524564 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -26,7 +26,7 @@ <string name="wifi_disconnected" msgid="7054450256284661757">"డిస్కనెక్ట్ అయ్యింది"</string> <string name="wifi_disabled_generic" msgid="2651916945380294607">"డిజేబుల్ చేయబడింది"</string> <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string> - <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"తక్కువ నాణ్యతా నెట్వర్క్ కారణంగా కనెక్ట్ చేయబడలేదు"</string> + <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"తక్కువ క్వాలిటీ నెట్వర్క్ కారణంగా కనెక్ట్ చేయబడలేదు"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi కనెక్షన్ వైఫల్యం"</string> <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ప్రామాణీకరణ సమస్య"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"కనెక్ట్ చేయడం సాధ్యపడదు"</string> @@ -88,9 +88,9 @@ <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_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ భాగస్వామ్యం"</string> - <string name="bluetooth_profile_map" msgid="8907204701162107271">"వచన మెసేజ్లు"</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> <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ఆడియో"</string> @@ -116,7 +116,7 @@ <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"జత చేయి"</string> <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"జత చేయి"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"రద్దు చేయి"</string> - <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"జత చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ పరిచయాలకు మరియు కాల్ చరిత్రకు యాక్సెస్ను మంజూరు చేస్తుంది."</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"పెయిర్ చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ కాంటాక్ట్లకు అలాగే కాల్ హిస్టరీకి యాక్సెస్ను మంజూరు చేస్తుంది."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string> <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"పిన్ లేదా పాస్కీ చెల్లని కారణంగా <xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో పెయిర్ చేయడం సాధ్యపడలేదు."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో కమ్యూనికేట్ చేయడం సాధ్యపడదు."</string> @@ -153,7 +153,7 @@ <string name="user_guest" msgid="6939192779649870792">"గెస్ట్"</string> <string name="unknown" msgid="3544487229740637809">"తెలియదు"</string> <string name="running_process_item_user_label" msgid="3988506293099805796">"యూజర్: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="3631650616557252926">"కొన్ని డిఫాల్ట్లు సెట్ చేయబడ్డాయి"</string> + <string name="launch_defaults_some" msgid="3631650616557252926">"కొన్ని ఆటోమేటిక్ సెట్టింగ్లు సెట్ చేయబడ్డాయి"</string> <string name="launch_defaults_none" msgid="8049374306261262709">"ఆటోమేటిక్ ఆప్షన్లు ఏవీ సెట్ చేయలేదు"</string> <string name="tts_settings" msgid="8130616705989351312">"వచనం నుండి ప్రసంగం సెట్టింగ్లు"</string> <string name="tts_settings_title" msgid="7602210956640483039">"టెక్స్ట్-టు-స్పీచ్ అవుట్పుట్"</string> @@ -167,12 +167,12 @@ <string name="tts_default_lang_summary" msgid="9042620014800063470">"టెక్స్ట్ను చదివి వినిపించేటప్పుడు, ఒక్కో భాషకు వాడాల్సిన నిర్దిష్ట వాయిస్ను సెట్ చేస్తుంది"</string> <string name="tts_play_example_title" msgid="1599468547216481684">"ఒక ఉదాహరణ వినండి"</string> <string name="tts_play_example_summary" msgid="634044730710636383">"ప్రసంగ సమన్వయం గురించి సంక్షిప్త ప్రదర్శనను ప్లే చేయి"</string> - <string name="tts_install_data_title" msgid="1829942496472751703">"వాయిస్ డేటాను ఇన్స్టాల్ చేయి"</string> - <string name="tts_install_data_summary" msgid="3608874324992243851">"ప్రసంగ సమన్వయం కోసం అవసరమైన వాయిస్ డేటాను ఇన్స్టాల్ చేయండి"</string> + <string name="tts_install_data_title" msgid="1829942496472751703">"వాయిస్ డేటాను ఇన్స్టాల్ చేయండి"</string> + <string name="tts_install_data_summary" msgid="3608874324992243851">"స్పీచ్ సమన్వయం కోసం అవసరమైన వాయిస్ డేటాను ఇన్స్టాల్ చేయండి"</string> <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> @@ -246,8 +246,8 @@ <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM అన్లాకింగ్ను అనుమతించాలా?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"హెచ్చరిక: ఈ సెట్టింగ్ ఆన్ చేయబడినప్పుడు పరికరం రక్షణ లక్షణాలు ఈ పరికరంలో పని చేయవు."</string> <string name="mock_location_app" msgid="6269380172542248304">"డమ్మీ లొకేషన్ యాప్ను ఎంచుకోండి"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"అనుకృత స్థాన యాప్ ఏదీ సెట్ చేయబడలేదు"</string> - <string name="mock_location_app_set" msgid="4706722469342913843">"కృత్రిమ స్థాన యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"డమ్మీ లొకేషన్ యాప్ ఏదీ సెట్ చేయబడలేదు"</string> + <string name="mock_location_app_set" msgid="4706722469342913843">"డమ్మీ లొకేషన్ యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"నెట్వర్కింగ్"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"వైర్లెస్ డిస్ప్లే సర్టిఫికేషన్"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi విశదీకృత లాగింగ్ను ప్రారంభించండి"</string> @@ -295,8 +295,8 @@ <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"పరికరంలో నిరంతరం నిల్వ చేయాల్సిన లాగ్ బఫర్లను ఎంచుకోండి"</string> <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string> <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string> - <string name="allow_mock_location" msgid="2102650981552527884">"అనుకృత స్థానాలను అనుమతించు"</string> - <string name="allow_mock_location_summary" msgid="179780881081354579">"అనుకృత స్థానాలను అనుమతించు"</string> + <string name="allow_mock_location" msgid="2102650981552527884">"డమ్మీ లొకేషన్లను అనుమతించండి"</string> + <string name="allow_mock_location_summary" msgid="179780881081354579">"డమ్మీ లొకేషన్లను అనుమతించండి"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"వీక్షణ అట్రిబ్యూట్ పర్యవేక్షణను ఎనేబుల్ చేయి"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ఎల్లప్పుడూ మొబైల్ డేటాను యాక్టివ్గా ఉంచు, Wi‑Fi యాక్టివ్గా ఉన్నా కూడా (వేగవంతమైన నెట్వర్క్ మార్పు కోసం)."</string> <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధిని ఉపయోగించండి"</string> @@ -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 7b0e9c748aac..0ddad5f7d7cd 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 @@ public class WifiStatusTracker { private Network mDefaultNetwork = null; private NetworkCapabilities mDefaultNetworkCapabilities = null; private final Runnable mCallback; - private final boolean mSupportMergedUi; private WifiInfo mWifiInfo; public boolean enabled; @@ -184,7 +183,6 @@ public class WifiStatusTracker { mNetworkScoreManager = networkScoreManager; mConnectivityManager = connectivityManager; mCallback = callback; - mSupportMergedUi = false; } public void setListening(boolean listening) { @@ -226,10 +224,8 @@ public class WifiStatusTracker { } else { ssid = getValidSsid(mWifiInfo); } - if (mSupportMergedUi) { - isCarrierMerged = mWifiInfo.isCarrierMerged(); - subId = mWifiInfo.getSubscriptionId(); - } + isCarrierMerged = mWifiInfo.isCarrierMerged(); + subId = mWifiInfo.getSubscriptionId(); updateRssi(mWifiInfo.getRssi()); maybeRequestNetworkScore(); } @@ -258,16 +254,13 @@ public class WifiStatusTracker { } else { ssid = getValidSsid(mWifiInfo); } + isCarrierMerged = mWifiInfo.isCarrierMerged(); + subId = mWifiInfo.getSubscriptionId(); updateRssi(mWifiInfo.getRssi()); maybeRequestNetworkScore(); wifiStandard = mWifiInfo.getWifiStandard(); vhtMax8SpatialStreamsSupport = mWifiInfo.isVhtMax8SpatialStreamsSupported(); he8ssCapableAp = mWifiInfo.isHe8ssCapableAp(); - if (mSupportMergedUi) { - isCarrierMerged = mWifiInfo.isCarrierMerged(); - subId = mWifiInfo.getSubscriptionId(); - } - updateRssi(mWifiInfo.getRssi()); maybeRequestNetworkScore(); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java index 17d3a2510c0d..a04d038ed423 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java @@ -20,10 +20,13 @@ import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_ import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.getMaxNetworkSelectionDisableReason; import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; import android.net.wifi.WifiInfo; +import android.os.Bundle; import android.os.SystemClock; import androidx.annotation.VisibleForTesting; @@ -36,6 +39,23 @@ public class WifiUtils { private static final int INVALID_RSSI = -127; + /** + * The intent action shows network details settings to allow configuration of Wi-Fi. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: The calling package should put the chosen + * com.android.wifitrackerlib.WifiEntry#getKey() to a string extra in the request bundle into + * the {@link #KEY_CHOSEN_WIFIENTRY_KEY}. + * <p> + * Output: Nothing. + */ + public static final String ACTION_WIFI_DETAILS_SETTINGS = + "android.settings.WIFI_DETAILS_SETTINGS"; + public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key"; + public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args"; + static final int[] WIFI_PIE = { com.android.internal.R.drawable.ic_wifi_signal_0, com.android.internal.R.drawable.ic_wifi_signal_1, @@ -347,7 +367,42 @@ public class WifiUtils { } } + /** + * Wrapper the {@link #getInternetIconResource} for testing compatibility. + */ + public static class InternetIconInjector { + + protected final Context mContext; + + public InternetIconInjector(Context context) { + mContext = context; + } + + /** + * Returns the Internet icon for a given RSSI level. + * + * @param noInternet True if a connected Wi-Fi network cannot access the Internet + * @param level The number of bars to show (0-4) + */ + public Drawable getIcon(boolean noInternet, int level) { + return mContext.getDrawable(WifiUtils.getInternetIconResource(level, noInternet)); + } + } + public static boolean isMeteredOverridden(WifiConfiguration config) { return config.meteredOverride != WifiConfiguration.METERED_OVERRIDE_NONE; } + + /** + * Returns the Intent for Wi-Fi network details settings. + * + * @param key The Wi-Fi entry key + */ + public static Intent getWifiDetailsSettingsIntent(String key) { + final Intent intent = new Intent(ACTION_WIFI_DETAILS_SETTINGS); + final Bundle bundle = new Bundle(); + bundle.putString(KEY_CHOSEN_WIFIENTRY_KEY, key); + intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, bundle); + return intent; + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java index 89960cba2bf5..7c2b904fc576 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java @@ -20,9 +20,12 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.Intent; import android.net.NetworkKey; import android.net.RssiCurve; import android.net.ScoredNetwork; @@ -36,6 +39,8 @@ import android.os.SystemClock; import android.text.format.DateUtils; import android.util.ArraySet; +import androidx.test.core.app.ApplicationProvider; + import com.android.settingslib.R; import org.junit.Before; @@ -44,7 +49,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Set; @@ -69,7 +73,7 @@ public class WifiUtilsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = spy(ApplicationProvider.getApplicationContext()); } @Test @@ -148,6 +152,32 @@ public class WifiUtilsTest { assertThat(WifiUtils.isMeteredOverridden(mWifiConfig)).isTrue(); } + @Test + public void getWifiDetailsSettingsIntent_returnsCorrectValues() { + final String key = "test_key"; + + final Intent intent = WifiUtils.getWifiDetailsSettingsIntent(key); + + assertThat(intent.getAction()).isEqualTo(WifiUtils.ACTION_WIFI_DETAILS_SETTINGS); + final Bundle bundle = intent.getBundleExtra(WifiUtils.EXTRA_SHOW_FRAGMENT_ARGUMENTS); + assertThat(bundle.getString(WifiUtils.KEY_CHOSEN_WIFIENTRY_KEY)).isEqualTo(key); + } + + @Test + public void testInternetIconInjector_getIcon_returnsCorrectValues() { + WifiUtils.InternetIconInjector iconInjector = new WifiUtils.InternetIconInjector(mContext); + + for (int level = 0; level <= 4; level++) { + iconInjector.getIcon(false /* noInternet */, level); + verify(mContext).getDrawable( + WifiUtils.getInternetIconResource(level, false /* noInternet */)); + + iconInjector.getIcon(true /* noInternet */, level); + verify(mContext).getDrawable( + WifiUtils.getInternetIconResource(level, true /* noInternet */)); + } + } + private static ArrayList<ScanResult> buildScanResultCache() { ArrayList<ScanResult> scanResults = new ArrayList<>(); for (int i = 0; i < 5; i++) { diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml index 89b7c1e95482..ead9f4da21ef 100644 --- a/packages/SettingsProvider/res/values-as/strings.xml +++ b/packages/SettingsProvider/res/values-as/strings.xml @@ -19,7 +19,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string> - <string name="wifi_softap_config_change" msgid="5688373762357941645">"হটস্পটৰ ছেটিংসমূহ সলনি হৈছে"</string> + <string name="app_label" msgid="4567566098528588863">"ছেটিঙৰ ষ্ট\'ৰেজ"</string> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"হটস্পটৰ ছেটিং সলনি হৈছে"</string> <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"সবিশেষ চাবলৈ টিপক"</string> </resources> diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java index eb8196176034..a46d28b273e5 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java @@ -76,5 +76,6 @@ public class GlobalSettings { Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, Settings.Global.DEVICE_CONFIG_SYNC_DISABLED, Settings.Global.POWER_BUTTON_LONG_PRESS, + 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 60226084c70d..96f127b6a611 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 @@ public class SecureSettings { 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 @@ public class SecureSettings { 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 5220a04d73e6..84c5febcb5a2 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.media.AudioFormat.SURROUND_SOUND_ENCODING; 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; @@ -140,6 +141,7 @@ public class GlobalSettingsValidators { /* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT)); VALIDATORS.put(Global.DISABLE_WINDOW_BLURS, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.DEVICE_CONFIG_SYNC_DISABLED, BOOLEAN_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 c57786888e8d..6cfcb51239a3 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 @@ public class SettingsHelper { * {@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 @@ public class SettingsHelper { 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 @@ public class SettingsHelper { // 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 @@ public class SettingsHelper { 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 @@ public class SettingsHelper { } 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 c670e46347ac..d68d3d339666 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -763,9 +763,6 @@ class SettingsProtoDumpUtil { Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES); dumpSetting(s, p, - Settings.Global.ANGLE_ALLOWLIST, - GlobalSettingsProto.Gpu.ANGLE_ALLOWLIST); - dumpSetting(s, p, Settings.Global.ANGLE_EGL_FEATURES, GlobalSettingsProto.Gpu.ANGLE_EGL_FEATURES); dumpSetting(s, p, @@ -1198,6 +1195,9 @@ class SettingsProtoDumpUtil { 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, @@ -1479,6 +1479,9 @@ class SettingsProtoDumpUtil { Settings.Global.USE_OPEN_WIFI_PACKAGE, GlobalSettingsProto.USE_OPEN_WIFI_PACKAGE); dumpSetting(s, p, + Settings.Global.UWB_ENABLED, + GlobalSettingsProto.UWB_ENABLED); + dumpSetting(s, p, Settings.Global.VT_IMS_ENABLED, GlobalSettingsProto.VT_IMS_ENABLED); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 3297937e3e75..7db73c697ea7 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -509,7 +509,6 @@ public class SettingsBackupTest { Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, - Settings.Global.ANGLE_ALLOWLIST, Settings.Global.ANGLE_EGL_FEATURES, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, @@ -519,6 +518,7 @@ public class SettingsBackupTest { Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, + Settings.Global.UWB_ENABLED, Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, Settings.Global.GPU_DEBUG_LAYER_APP, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml index c23efc30e133..049d2ac050d5 100644 --- a/packages/Shell/res/values-da/strings.xml +++ b/packages/Shell/res/values-da/strings.xml @@ -28,7 +28,7 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Vælg for at dele din fejlrapport uden et screenshot, eller vent på, at et screenshot er klar"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, og der kan være følsomme data imellem (f.eks. appforbrug og placeringsdata). Del kun fejlrapporter med personer og apps, du har tillid til."</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, og der kan være følsomme data imellem (f.eks. appforbrug og lokationsdata). Del kun fejlrapporter med personer og apps, du har tillid til."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Vis ikke igen"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"Fejlrapportfilen kunne ikke læses"</string> diff --git a/packages/Shell/res/values-te/strings.xml b/packages/Shell/res/values-te/strings.xml index 50b5c8550ef2..2f8623283273 100644 --- a/packages/Shell/res/values-te/strings.xml +++ b/packages/Shell/res/values-te/strings.xml @@ -23,9 +23,9 @@ <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ రిపోర్ట్కు వివరాలను జోడిస్తోంది"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"దయచేసి వేచి ఉండండి..."</string> <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"బగ్ రిపోర్ట్ త్వరలో ఫోన్లో కనిపిస్తుంది"</string> - <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"మీ బగ్ రిపోర్ట్ను భాగస్వామ్యం చేయడానికి ఎంచుకోండి"</string> + <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"మీ బగ్ రిపోర్ట్ను షేర్ చేయడానికి ఎంచుకోండి"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"మీ బగ్ రిపోర్ట్ను షేర్ చేయడానికి నొక్కండి"</string> - <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్షాట్ లేకుండా మీ బగ్ రిపోర్ట్ను భాగస్వామ్యం చేయడానికి ఎంచుకోండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> + <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్షాట్ లేకుండా మీ బగ్ రిపోర్ట్ను షేర్ చేయడానికి ఎంచుకోండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ రిపోర్ట్స్లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం, లొకేషన్ డేటా వంటి) డేటాతో పాటు సిస్టమ్కు సంబంధించిన విభిన్న లాగ్ ఫైళ్ల డేటా ఉంటుంది. బగ్ రిపోర్ట్లను మీరు విశ్వసించే యాప్లు, వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string> diff --git a/packages/SoundPicker/res/values-te/strings.xml b/packages/SoundPicker/res/values-te/strings.xml index 10b4e7cfe615..8f5c34a8018c 100644 --- a/packages/SoundPicker/res/values-te/strings.xml +++ b/packages/SoundPicker/res/values-te/strings.xml @@ -16,7 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="ringtone_default" msgid="798836092118824500">"డిఫాల్ట్ రింగ్టోన్"</string> + <string name="ringtone_default" msgid="798836092118824500">"ఆటోమేటిక్ రింగ్టోన్"</string> <string name="notification_sound_default" msgid="8133121186242636840">"నోటిఫికేషన్ ఆటోమేటిక్ సౌండ్"</string> <string name="alarm_sound_default" msgid="4787646764557462649">"అలారం ఆటోమేటిక్ సౌండ్"</string> <string name="add_ringtone_text" msgid="6642389991738337529">"రింగ్టోన్ను జోడించు"</string> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_media_recommendation_bg_gradient.xml b/packages/SystemUI/res-keyguard/drawable/qs_media_recommendation_bg_gradient.xml new file mode 100644 index 000000000000..495fbb893eac --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_media_recommendation_bg_gradient.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners android:radius="24dp"/> + <gradient + android:angle="0" + android:startColor="#00000000" + android:endColor="#ff000000" + android:type="linear" /> +</shape> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index 967d5cb05b4b..2908bae948d0 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 ac5a58e3efcc..5be929831b34 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 38a7139a9634..f8c8cadbbb03 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 a41cce7b74bf..e87ee927a892 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 62370756e606..edf8ab2b2b23 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 4e7ac49a25d1..bbc5aa0d157c 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 a1d58b789712..60b52ea6bf1e 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 a0ae88a4557d..eca49577042f 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 98b1af6b8710..5cbe02e3f7f5 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 65b0409ecb6a..b6fd676cb29b 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 110b711faa4a..b4f709d3eb4e 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 82579d437806..6092cc7f8cbc 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 371d993d3a47..bb388ea4c577 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 adec7fe2127b..ef36fdd8298d 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-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index ffc875bc22df..f9544af5f6d1 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -40,7 +40,7 @@ <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_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్ను కనెక్ట్ చేయండి."</string> - <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్లాక్ చేయడానికి మెనుని నొక్కండి."</string> + <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్లాక్ చేయడానికి మెనూను నొక్కండి."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్వర్క్ లాక్ చేయబడింది"</string> <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM కార్డ్ లేదు"</string> <string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"SIM కార్డ్ని చొప్పించండి."</string> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index 3c3972c2a1bc..be10a50839a8 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 e9a7e86f8ca6..1f1fff8b4c79 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-keyguard/values/donottranslate.xml b/packages/SystemUI/res-keyguard/values/donottranslate.xml index a4d0ff7269a2..1934457b4bc6 100644 --- a/packages/SystemUI/res-keyguard/values/donottranslate.xml +++ b/packages/SystemUI/res-keyguard/values/donottranslate.xml @@ -21,6 +21,9 @@ <!-- Skeleton string format for displaying the date when an alarm is set. --> <string name="abbrev_wday_month_day_no_year_alarm">EEEMMMd</string> + <!-- Skeleton string format for displaying the date shorter. --> + <string name="abbrev_month_day_no_year">MMMd</string> + <!-- Skeleton string format for displaying the time in 12-hour format. --> <string name="clock_12hr_format">hm</string> diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 72b027af1bf6..098b7e8dedbe 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -142,4 +142,8 @@ <item name="android:shadowColor">@color/keyguard_shadow_color</item> <item name="android:shadowRadius">?attr/shadowRadius</item> </style> + + <style name="TextAppearance.Keyguard.BottomArea.Button"> + <item name="android:shadowRadius">0</item> + </style> </resources> diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml index d2aec4bdccde..2629667d00ee 100644 --- a/packages/SystemUI/res-product/values-kk/strings.xml +++ b/packages/SystemUI/res-product/values-kk/strings.xml @@ -38,8 +38,8 @@ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string> <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string> <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string> - <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> - <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> + <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> + <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string> <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Басқа опцияларды көру үшін телефон құлпын ашыңыз."</string> <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Басқа опцияларды көру үшін планшет құлпын ашыңыз."</string> <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string> diff --git a/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect.xml b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect.xml new file mode 100644 index 000000000000..13133cb451e4 --- /dev/null +++ b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect.xml @@ -0,0 +1,25 @@ +<?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. +--> + +<!-- Copy of progress_indeterminate_horizontal_rect2 in frameworks/base/core/res --> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="2000" + android:propertyXName="translateX" + android:pathData="M -197.60001,0 c 14.28182,0 85.07782,0 135.54689,0 c 54.26191,0 90.42461,0 168.24331,0 c 144.72154,0 316.40982,0 316.40982,0 " + android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_translatex_copy" + android:repeatCount="infinite" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/color/settingslib_state_off.xml b/packages/SystemUI/res/color/settingslib_state_off.xml new file mode 100644 index 000000000000..e8218259087d --- /dev/null +++ b/packages/SystemUI/res/color/settingslib_state_off.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/color/settingslib_state_on.xml b/packages/SystemUI/res/color/settingslib_state_on.xml new file mode 100644 index 000000000000..6d2133c5bacf --- /dev/null +++ b/packages/SystemUI/res/color/settingslib_state_on.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentPrimary"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/color/settingslib_track_off.xml b/packages/SystemUI/res/color/settingslib_track_off.xml new file mode 100644 index 000000000000..21d1dccbf900 --- /dev/null +++ b/packages/SystemUI/res/color/settingslib_track_off.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentSecondary"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/color/settingslib_track_on.xml b/packages/SystemUI/res/color/settingslib_track_on.xml new file mode 100644 index 000000000000..ba7848a5d23e --- /dev/null +++ b/packages/SystemUI/res/color/settingslib_track_on.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentPrimaryVariant"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_arrow_forward.xml b/packages/SystemUI/res/drawable/ic_arrow_forward.xml new file mode 100644 index 000000000000..438e4c70dc71 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_arrow_forward.xml @@ -0,0 +1,26 @@ +<!-- + ~ 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. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:autoMirrored="true" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="@android:color/black" + android:pathData="M6.23,20.23l1.77,1.77l10,-10l-10,-10l-1.77,1.77l8.23,8.23z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_friction_lock_closed.xml b/packages/SystemUI/res/drawable/ic_friction_lock_closed.xml new file mode 100644 index 000000000000..2c34060ccd61 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_friction_lock_closed.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M18,8h-1V6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2H9V6zM18,20H6V10h12V20zM12,17c1.1,0 2,-0.9 2,-2c0,-1.1 -0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2C10,16.1 10.9,17 12,17z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_media_home_devices.xml b/packages/SystemUI/res/drawable/ic_media_home_devices.xml new file mode 100644 index 000000000000..886c64d9bf02 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_media_home_devices.xml @@ -0,0 +1,16 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20,4H4c-1.1,0 -2,0.9 -2,2v11c0,1.1 0.9,2 2,2h4v2h3v-4H4V6h16v1h2V6c0,-1.1 -0.9,-2 -2,-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M17.5,16.5m-2.33,0a2.33,2.33 0,1 1,4.66 0a2.33,2.33 0,1 1,-4.66 0"/> + <path + android:fillColor="@android:color/white" + android:pathData="M21,8h-7c-0.55,0 -1,0.45 -1,1v11c0,0.55 0.45,1 1,1h7c0.55,0 1,-0.45 1,-1L22,9c0,-0.55 -0.45,-1 -1,-1zM17.5,9c0.83,0 1.5,0.67 1.5,1.5s-0.67,1.5 -1.5,1.5 -1.5,-0.67 -1.5,-1.5 0.67,-1.5 1.5,-1.5zM17.5,20c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_settings_24dp.xml b/packages/SystemUI/res/drawable/ic_settings_24dp.xml new file mode 100644 index 000000000000..ac4c43bd35b9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_settings_24dp.xml @@ -0,0 +1,29 @@ +<!-- + Copyright (C) 2015 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. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,12m-3.5,0a3.5,3.5 0,1 1,7 0a3.5,3.5 0,1 1,-7 0"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_signal_strength_zero_bar_no_internet.xml b/packages/SystemUI/res/drawable/ic_signal_strength_zero_bar_no_internet.xml new file mode 100644 index 000000000000..f38a36804bc8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_signal_strength_zero_bar_no_internet.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FF000000" + android:pathData="M2,22l16,0l0,-2l-11,0l13,-13l0,1l2,0l0,-6z" + android:strokeAlpha="0.3" + android:fillAlpha="0.3"/> + <path + android:fillColor="#FF000000" + android:pathData="M20,10h2v8h-2z"/> + <path + android:fillColor="#FF000000" + android:pathData="M20,20h2v2h-2z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/internet_dialog_background.xml b/packages/SystemUI/res/drawable/internet_dialog_background.xml new file mode 100644 index 000000000000..3ceb0f6ac06a --- /dev/null +++ b/packages/SystemUI/res/drawable/internet_dialog_background.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<inset xmlns:android="http://schemas.android.com/apk/res/android"> + <shape android:shape="rectangle"> + <corners android:radius="8dp" /> + <solid android:color="?android:attr/colorBackground" /> + </shape> +</inset> diff --git a/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml b/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml new file mode 100644 index 000000000000..50267fda0b25 --- /dev/null +++ b/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml @@ -0,0 +1,30 @@ +<?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 + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:shape="rectangle"> + <stroke + android:color="?androidprv:attr/colorAccentPrimaryVariant" + android:width="1dp"/> + <corners android:radius="20dp"/> + <padding + android:left="8dp" + android:right="8dp" + android:top="4dp" + android:bottom="4dp" /> + <solid android:color="@android:color/transparent" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml b/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml new file mode 100644 index 000000000000..14672ef3dcfe --- /dev/null +++ b/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml @@ -0,0 +1,22 @@ +<?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. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android"> + <shape android:shape="rectangle"> + <corners + android:topLeftRadius="@dimen/internet_dialog_corner_radius" + android:topRightRadius="@dimen/internet_dialog_corner_radius" + android:bottomLeftRadius="@dimen/internet_dialog_corner_radius" + android:bottomRightRadius="@dimen/internet_dialog_corner_radius"/> + <solid android:color="?android:attr/colorBackground" /> + </shape> +</inset> diff --git a/packages/SystemUI/res/drawable/logout_button_background.xml b/packages/SystemUI/res/drawable/logout_button_background.xml index eafd663f19d9..34434be7aefb 100644 --- a/packages/SystemUI/res/drawable/logout_button_background.xml +++ b/packages/SystemUI/res/drawable/logout_button_background.xml @@ -17,7 +17,8 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="rectangle"> - <solid android:color="@color/logout_button_bg_color"/> + <solid android:color="?androidprv:attr/colorAccentPrimary"/> <corners android:radius="@dimen/logout_button_corner_radius"/> </shape> diff --git a/packages/SystemUI/res/drawable/notif_footer_btn_background.xml b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml index 6725a26c102c..e6266754c0af 100644 --- a/packages/SystemUI/res/drawable/notif_footer_btn_background.xml +++ b/packages/SystemUI/res/drawable/notif_footer_btn_background.xml @@ -14,19 +14,20 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - -<shape xmlns:android="http://schemas.android.com/apk/res/android" +<ripple xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:shape="rectangle"> - <solid - android:color="?androidprv:attr/colorSurface" - /> - <corners android:radius="20dp" /> - - <padding - android:left="20dp" - android:right="20dp"> - </padding> - -</shape>
\ No newline at end of file + android:color="?android:attr/colorControlHighlight"> + <item> + <inset + android:insetBottom="4dp" + android:insetTop="4dp"> + <shape android:shape="rectangle"> + <corners android:radius="20dp" /> + <padding + android:left="20dp" + android:right="20dp" /> + <solid android:color="?androidprv:attr/colorSurface" /> + </shape> + </inset> + </item> +</ripple> diff --git a/packages/SystemUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml b/packages/SystemUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml new file mode 100644 index 000000000000..95209f8eb8ab --- /dev/null +++ b/packages/SystemUI/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml @@ -0,0 +1,23 @@ +<?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. +--> + +<!-- Copy of progress_indeterminate_horizontal_material_trimmed in frameworks/base/core/res --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal_trimmed" > + <target + android:name="rect_grp" + android:animation="@anim/progress_indeterminate_horizontal_rect" /> +</animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml b/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml new file mode 100644 index 000000000000..088e82bb4260 --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_disabled.xml @@ -0,0 +1,26 @@ +<?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. + --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item> + <shape android:shape="rectangle"> + <solid android:color="@color/settingslib_state_off_color"/> + <corners android:radius="@dimen/settingslib_switch_bar_radius"/> + </shape> + </item> +</ripple> diff --git a/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_on.xml b/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_on.xml new file mode 100644 index 000000000000..250188b892f4 --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_switch_bar_bg_on.xml @@ -0,0 +1,26 @@ +<?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. + --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item> + <shape android:shape="rectangle"> + <solid android:color="@color/settingslib_state_on_color"/> + <corners android:radius="@dimen/settingslib_switch_bar_radius"/> + </shape> + </item> +</ripple> diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_disabled.xml b/packages/SystemUI/res/drawable/settingslib_thumb_disabled.xml new file mode 100644 index 000000000000..b41762f7908e --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_thumb_disabled.xml @@ -0,0 +1,33 @@ +<?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. + --> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:top="@dimen/settingslib_switch_thumb_margin" + android:left="@dimen/settingslib_switch_thumb_margin" + android:right="@dimen/settingslib_switch_thumb_margin" + android:bottom="@dimen/settingslib_switch_thumb_margin"> + <shape android:shape="oval"> + <size + android:height="@dimen/settingslib_switch_thumb_size" + android:width="@dimen/settingslib_switch_thumb_size"/> + <solid + android:color="@color/settingslib_thumb_off_color" + android:alpha="?android:attr/disabledAlpha"/> + </shape> + </item> +</layer-list> diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_off.xml b/packages/SystemUI/res/drawable/settingslib_thumb_off.xml new file mode 100644 index 000000000000..87d4aeaac84f --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_thumb_off.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:top="@dimen/settingslib_switch_thumb_margin" + android:bottom="@dimen/settingslib_switch_thumb_margin"> + <shape android:shape="oval"> + <size + android:height="@dimen/settingslib_switch_thumb_size" + android:width="@dimen/settingslib_switch_thumb_size"/> + <solid android:color="@color/settingslib_thumb_off_color"/> + </shape> + </item> +</layer-list> diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_on.xml b/packages/SystemUI/res/drawable/settingslib_thumb_on.xml new file mode 100644 index 000000000000..5566ea3f62fc --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_thumb_on.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:top="@dimen/settingslib_switch_thumb_margin" + android:bottom="@dimen/settingslib_switch_thumb_margin"> + <shape android:shape="oval"> + <size + android:height="@dimen/settingslib_switch_thumb_size" + android:width="@dimen/settingslib_switch_thumb_size"/> + <solid android:color="@color/settingslib_state_on_color"/> + </shape> + </item> +</layer-list> diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_selector.xml b/packages/SystemUI/res/drawable/settingslib_thumb_selector.xml new file mode 100644 index 000000000000..06bb779b91ef --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_thumb_selector.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/settingslib_thumb_on" android:state_checked="true"/> + <item android:drawable="@drawable/settingslib_thumb_off" android:state_checked="false"/> + <item android:drawable="@drawable/settingslib_thumb_disabled" android:state_enabled="false"/> +</selector> diff --git a/packages/SystemUI/res/drawable/settingslib_track_disabled_background.xml b/packages/SystemUI/res/drawable/settingslib_track_disabled_background.xml new file mode 100644 index 000000000000..15dfcb70e25e --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_track_disabled_background.xml @@ -0,0 +1,26 @@ +<?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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle" + android:width="@dimen/settingslib_switch_track_width" + android:height="@dimen/settingslib_switch_track_height"> + <solid + android:color="@color/settingslib_track_off_color" + android:alpha="?android:attr/disabledAlpha"/> + <corners android:radius="@dimen/settingslib_switch_track_radius"/> +</shape> diff --git a/packages/SystemUI/res/drawable/settingslib_track_off_background.xml b/packages/SystemUI/res/drawable/settingslib_track_off_background.xml new file mode 100644 index 000000000000..3a09284d10a0 --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_track_off_background.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle" + android:width="@dimen/settingslib_switch_track_width" + android:height="@dimen/settingslib_switch_track_height"> + <padding android:left="@dimen/settingslib_switch_thumb_margin" + android:right="@dimen/settingslib_switch_thumb_margin"/> + <solid android:color="@color/settingslib_track_off_color"/> + <corners android:radius="@dimen/settingslib_switch_track_radius"/> +</shape> diff --git a/packages/SystemUI/res/drawable/settingslib_track_on_background.xml b/packages/SystemUI/res/drawable/settingslib_track_on_background.xml new file mode 100644 index 000000000000..1d9dacd6c0f9 --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_track_on_background.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle" + android:width="@dimen/settingslib_switch_track_width" + android:height="@dimen/settingslib_switch_track_height"> + <padding android:left="@dimen/settingslib_switch_thumb_margin" + android:right="@dimen/settingslib_switch_thumb_margin"/> + <solid android:color="@color/settingslib_track_on_color"/> + <corners android:radius="@dimen/settingslib_switch_track_radius"/> +</shape> diff --git a/packages/SystemUI/res/drawable/settingslib_track_selector.xml b/packages/SystemUI/res/drawable/settingslib_track_selector.xml new file mode 100644 index 000000000000..a38c3b4241a3 --- /dev/null +++ b/packages/SystemUI/res/drawable/settingslib_track_selector.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/settingslib_track_on_background" android:state_checked="true"/> + <item android:drawable="@drawable/settingslib_track_off_background" android:state_checked="false"/> + <item android:drawable="@drawable/settingslib_track_disabled_background" android:state_enabled="false"/> +</selector> diff --git a/packages/SystemUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml b/packages/SystemUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml new file mode 100644 index 000000000000..aec204f45aa7 --- /dev/null +++ b/packages/SystemUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.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. +--> + +<!-- Variant of vector_drawable_progress_indeterminate_horizontal in frameworks/base/core/res, which + draws the whole height of the progress bar instead having blank space above and below the + bar. --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:height="10dp" + android:width="340dp" + android:viewportHeight="10" + android:viewportWidth="340" > + <group + android:name="progress_group" + android:translateX="180" + android:translateY="5" > + <path + android:name="background_track" + android:pathData="M -180.0,-5.0 l 360.0,0 l 0,10.0 l -360.0,0 Z" + android:fillColor="?androidprv:attr/colorSurfaceVariant"/> + <group + android:name="rect_grp" + android:translateX="-197.60001" + android:scaleX="0.5" > + <path + android:name="rect" + android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z" + android:fillColor="?androidprv:attr/colorAccentPrimaryVariant" /> + </group> + </group> +</vector>
\ No newline at end of file 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 000000000000..1f0899623ddf --- /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/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml index e4a96947aa6a..6a9254cad8f4 100644 --- a/packages/SystemUI/res/layout/global_screenshot_static.xml +++ b/packages/SystemUI/res/layout/global_screenshot_static.xml @@ -36,7 +36,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/screenshot_action_container_margin_horizontal" - android:layout_marginBottom="@dimen/screenshot_action_container_offset_y" android:paddingEnd="@dimen/screenshot_action_container_padding_right" android:paddingVertical="@dimen/screenshot_action_container_padding_vertical" android:elevation="1dp" diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml new file mode 100644 index 000000000000..c88e95f07f12 --- /dev/null +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -0,0 +1,388 @@ +<?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:androidprv="http://schemas.android.com/apk/prv/res/android" + android:id="@+id/internet_connectivity_dialog" + android:layout_width="@dimen/internet_dialog_list_max_width" + android:layout_height="@dimen/internet_dialog_list_max_height" + android:background="@drawable/internet_dialog_rounded_top_corner_background" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="@style/Widget.SliceView.Panel" + android:gravity="center_vertical|center_horizontal" + android:layout_marginTop="24dp" + android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin" + android:orientation="vertical"> + + <TextView + android:id="@+id/internet_dialog_title" + android:gravity="center_vertical|center_horizontal" + android:layout_width="wrap_content" + android:layout_height="32dp" + android:textAppearance="@style/TextAppearance.InternetDialog" + android:textSize="24sp"/> + + <TextView + android:id="@+id/internet_dialog_subtitle" + android:gravity="center_vertical|center_horizontal" + android:layout_width="wrap_content" + android:layout_height="20dp" + android:layout_marginTop="4dp" + android:ellipsize="end" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.InternetDialog.Secondary"/> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin" + android:orientation="vertical"> + + <View + android:id="@+id/divider" + android:layout_gravity="center_vertical|center_horizontal" + android:layout_width="340dp" + android:layout_height="4dp" + android:background="?androidprv:attr/colorSurfaceVariant"/> + + <ProgressBar + android:id="@+id/wifi_searching_progress" + android:indeterminate="true" + android:layout_width="340dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:visibility="gone" + style="@style/TrimmedHorizontalProgressBar"/> + </LinearLayout> + + <androidx.core.widget.NestedScrollView + android:id="@+id/scroll_view" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/scroll_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <LinearLayout + android:id="@+id/ethernet_layout" + style="@style/InternetDialog.Network" + android:background="@drawable/settingslib_switch_bar_bg_on" + android:visibility="gone"> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center_vertical|start" + android:clickable="false"> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:autoMirrored="true" + android:src="@drawable/stat_sys_ethernet_fully" + android:tint="@color/connected_network_primary_color"/> + </FrameLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:orientation="vertical" + android:clickable="false"> + <TextView + android:text="@string/ethernet_label" + style="@style/InternetDialog.NetworkTitle.Active"/> + <TextView + android:text="@string/to_switch_networks_disconnect_ethernet" + style="@style/InternetDialog.NetworkSummary.Active"/> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:id="@+id/mobile_network_layout" + style="@style/InternetDialog.Network"> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:clickable="false" + android:layout_gravity="center_vertical|start"> + <ImageView + android:id="@+id/signal_icon" + android:autoMirrored="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> + + <LinearLayout + android:layout_weight="1" + android:orientation="vertical" + android:clickable="false" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="start|center_vertical"> + <TextView + android:id="@+id/mobile_title" + style="@style/InternetDialog.NetworkTitle"/> + <TextView + android:id="@+id/mobile_summary" + style="@style/InternetDialog.NetworkSummary"/> + </LinearLayout> + + <FrameLayout + android:layout_width="@dimen/settingslib_switch_track_width" + android:layout_height="48dp" + android:layout_gravity="end|center_vertical"> + <Switch + android:id="@+id/mobile_toggle" + android:contentDescription="@string/mobile_data_settings_title" + android:switchMinWidth="@dimen/settingslib_switch_track_width" + android:layout_gravity="center" + android:layout_width="@dimen/settingslib_switch_track_width" + android:layout_height="match_parent" + android:track="@drawable/settingslib_track_selector" + android:thumb="@drawable/settingslib_thumb_selector" + android:theme="@style/MainSwitch.Settingslib"/> + </FrameLayout> + + </LinearLayout> + + <LinearLayout + android:id="@+id/turn_on_wifi_layout" + style="@style/InternetDialog.Network" + android:layout_height="72dp" + android:gravity="center" + android:clickable="false" + android:focusable="false"> + + <FrameLayout + android:layout_weight="1" + android:orientation="vertical" + android:clickable="false" + android:layout_width="wrap_content" + android:layout_height="match_parent"> + <TextView + android:id="@+id/wifi_toggle_title" + android:text="@string/turn_on_wifi" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="start|center_vertical" + android:textAppearance="@style/TextAppearance.InternetDialog"/> + </FrameLayout> + + <FrameLayout + android:layout_width="@dimen/settingslib_switch_track_width" + android:layout_height="48dp" + android:layout_marginTop="10dp" + android:layout_marginBottom="10dp"> + <Switch + android:id="@+id/wifi_toggle" + android:contentDescription="@string/turn_on_wifi" + android:switchMinWidth="@dimen/settingslib_switch_track_width" + android:layout_gravity="center" + android:layout_width="@dimen/settingslib_switch_track_width" + android:layout_height="match_parent" + android:track="@drawable/settingslib_track_selector" + android:thumb="@drawable/settingslib_thumb_selector" + android:theme="@style/MainSwitch.Settingslib"/> + </FrameLayout> + + </LinearLayout> + + <LinearLayout + android:id="@+id/wifi_connected_layout" + style="@style/InternetDialog.Network" + android:layout_height="72dp" + android:paddingStart="20dp" + android:paddingEnd="24dp" + android:background="@drawable/settingslib_switch_bar_bg_on" + android:visibility="gone"> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:clickable="false" + android:layout_gravity="center_vertical|start"> + <ImageView + android:id="@+id/wifi_connected_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> + + <LinearLayout + android:orientation="vertical" + android:clickable="false" + android:layout_width="wrap_content" + android:layout_height="72dp" + android:layout_marginEnd="30dp" + android:layout_weight="1" + android:gravity="start|center_vertical"> + <TextView + android:id="@+id/wifi_connected_title" + style="@style/InternetDialog.NetworkTitle.Active" + android:textSize="14sp"/> + <TextView + android:id="@+id/wifi_connected_summary" + style="@style/InternetDialog.NetworkSummary.Active"/> + </LinearLayout> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="match_parent" + android:clickable="false" + android:layout_gravity="end|center_vertical" + android:gravity="center"> + <ImageView + android:id="@+id/wifi_settings_icon" + android:src="@drawable/ic_settings_24dp" + android:layout_width="24dp" + android:layout_gravity="end|center_vertical" + android:layout_height="wrap_content"/> + </FrameLayout> + + </LinearLayout> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/wifi_list_layout" + android:scrollbars="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:overScrollMode="never" + android:nestedScrollingEnabled="false"/> + + </LinearLayout> + + <LinearLayout + android:id="@+id/see_all_layout" + android:layout_width="match_parent" + android:layout_height="64dp" + android:clickable="true" + android:focusable="true" + android:background="?android:attr/selectableItemBackground" + android:gravity="center_vertical|center_horizontal" + android:orientation="horizontal" + android:paddingStart="22dp" + android:paddingEnd="22dp"> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:clickable="false" + android:layout_gravity="center_vertical|start" + android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"> + <ImageView + android:id="@+id/arrow_forward" + android:src="@drawable/ic_arrow_forward" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> + + <FrameLayout + android:orientation="vertical" + android:clickable="false" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"> + <TextView + android:text="@string/see_all_networks" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="start|center_vertical" + android:textAppearance="@style/TextAppearance.InternetDialog" + android:textSize="14sp"/> + </FrameLayout> + </LinearLayout> + + <LinearLayout + android:id="@+id/wifi_scan_notify_layout" + style="@style/InternetDialog.Network" + android:orientation="vertical" + android:layout_height="wrap_content" + android:paddingBottom="4dp" + android:clickable="false" + android:focusable="false"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minWidth="56dp" + android:gravity="start|top" + android:orientation="horizontal" + android:paddingEnd="12dp" + android:paddingTop="16dp" + android:paddingBottom="4dp"> + <ImageView + android:src="@drawable/ic_info_outline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:tint="?android:attr/textColorTertiary"/> + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + <TextView + android:id="@+id/wifi_scan_notify_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="16dp" + android:paddingBottom="8dp" + android:textColor="?android:attr/textColorSecondary" + android:clickable="true"/> + </LinearLayout> + </LinearLayout> + + <FrameLayout + android:id="@+id/done_layout" + android:layout_width="67dp" + android:layout_height="48dp" + android:layout_marginEnd="24dp" + android:layout_marginBottom="40dp" + android:layout_gravity="end|center_vertical" + android:clickable="true" + android:focusable="true"> + <Button + android:text="@string/inline_done_button" + style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored" + android:layout_width="match_parent" + android:layout_height="36dp" + android:layout_gravity="center" + android:textAppearance="@style/TextAppearance.InternetDialog" + android:textSize="14sp" + android:background="@drawable/internet_dialog_footer_background" + android:clickable="false"/> + </FrameLayout> + </LinearLayout> + </androidx.core.widget.NestedScrollView> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml new file mode 100644 index 000000000000..868331ec830f --- /dev/null +++ b/packages/SystemUI/res/layout/internet_list_item.xml @@ -0,0 +1,74 @@ +<?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" + android:id="@+id/internet_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <LinearLayout + android:id="@+id/wifi_list" + style="@style/InternetDialog.Network" + android:layout_height="72dp" + android:paddingStart="20dp" + android:paddingEnd="24dp"> + <FrameLayout + android:layout_width="24dp" + android:layout_height="24dp" + android:clickable="false" + android:layout_gravity="center_vertical|start"> + <ImageView + android:id="@+id/wifi_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> + + <LinearLayout + android:id="@+id/wifi_network_layout" + android:orientation="vertical" + android:clickable="false" + android:layout_width="wrap_content" + android:layout_height="72dp" + android:layout_marginEnd="30dp" + android:layout_weight="1" + android:gravity="start|center_vertical"> + <TextView + android:id="@+id/wifi_title" + style="@style/InternetDialog.NetworkTitle" + android:textSize="14sp"/> + <TextView + android:id="@+id/wifi_summary" + style="@style/InternetDialog.NetworkSummary"/> + </LinearLayout> + + <FrameLayout + android:layout_width="24dp" + android:layout_height="match_parent" + android:clickable="false" + android:layout_gravity="end|center_vertical"> + <ImageView + android:id="@+id/wifi_end_icon" + android:layout_gravity="end|center_vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + </FrameLayout> + + </LinearLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml index a21a63c3e7c3..9cf09ff328c4 100644 --- a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml +++ b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml @@ -15,19 +15,25 @@ ~ limitations under the License --> <!-- This is a view that shows a user switcher in Keyguard. --> -<com.android.systemui.statusbar.phone.UserAvatarView +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:id="@+id/keyguard_qs_user_switch_view" - android:layout_width="@dimen/kg_framed_avatar_size" - android:layout_height="@dimen/kg_framed_avatar_size" - android:layout_centerHorizontal="true" - android:layout_gravity="top|end" - android:layout_marginEnd="16dp" - systemui:avatarPadding="0dp" - systemui:badgeDiameter="18dp" - systemui:badgeMargin="1dp" - systemui:frameColor="@color/kg_user_avatar_frame" - systemui:framePadding="0dp" - systemui:frameWidth="0dp"> -</com.android.systemui.statusbar.phone.UserAvatarView> + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="end"> + <com.android.systemui.statusbar.phone.UserAvatarView + android:id="@+id/kg_multi_user_avatar" + android:layout_width="@dimen/kg_framed_avatar_size" + android:layout_height="@dimen/kg_framed_avatar_size" + android:layout_centerHorizontal="true" + android:layout_gravity="top|end" + android:layout_marginEnd="16dp" + systemui:avatarPadding="0dp" + systemui:badgeDiameter="18dp" + systemui:badgeMargin="1dp" + systemui:frameColor="@color/kg_user_avatar_frame" + systemui:framePadding="0dp" + systemui:frameWidth="0dp"> + </com.android.systemui.statusbar.phone.UserAvatarView> +</FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml index eb7638233efd..850b01717308 100644 --- a/packages/SystemUI/res/layout/keyguard_status_bar.xml +++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml @@ -30,7 +30,6 @@ android:id="@+id/status_icon_area" android:layout_width="wrap_content" android:layout_height="match_parent" - android:paddingEnd="@dimen/system_icons_keyguard_padding_end" android:paddingTop="@dimen/status_bar_padding_top" android:layout_alignParentEnd="true" android:gravity="center_vertical|end" > @@ -39,6 +38,7 @@ android:layout_height="match_parent" android:layout_weight="1" android:layout_marginStart="@dimen/system_icons_super_container_margin_start" + android:layout_marginEnd="@dimen/status_bar_padding_end" android:gravity="center_vertical|end"> <include layout="@layout/system_icons" /> </FrameLayout> diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index 0e31ecbb6948..419fe4fc2d67 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -48,20 +48,41 @@ android:id="@+id/recommendation_card_icon" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" + android:layout_marginTop="@dimen/qs_media_padding" android:src="@drawable/ic_headset" - style="@style/MediaPlayer.AppIcon"/> + style="@style/MediaPlayer.AppIcon" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" + app:layout_constraintHorizontal_bias="0"/> <TextView android:id="@+id/recommendation_card_text" android:layout_width="0dp" android:layout_height="wrap_content" - android:maxLines="2" + android:maxLines="1" android:text="@string/controls_media_smartspace_rec_title" android:fontFamily="google-sans-medium" android:textDirection="locale" android:textSize="@dimen/qq_aa_media_rec_header_text_size" - android:breakStrategy="balanced" - android:hyphenationFrequency="none"/> + android:hyphenationFrequency="none" + app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" + app:layout_constraintHorizontal_bias="0"/> + + <View + android:id="@+id/recommendation_gradient_view" + android:layout_width="@dimen/qs_aa_media_gradient_bg_width" + android:layout_height="0dp" + android:clipToPadding="false" + android:clipChildren="false" + android:background="@drawable/qs_media_recommendation_bg_gradient" + app:layout_constraintTop_toTopOf="@id/recommendation_card_text" + app:layout_constraintBottom_toBottomOf="@id/recommendation_card_text" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" + app:layout_constraintHorizontal_bias="1"/> <FrameLayout android:id="@+id/media_cover1_container" diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml index 075473aef9ac..566cd25e86a5 100644 --- a/packages/SystemUI/res/layout/media_view.xml +++ b/packages/SystemUI/res/layout/media_view.xml @@ -163,18 +163,6 @@ </LinearLayout> </LinearLayout> - <ImageView - android:id="@+id/media_seamless_fallback" - android:layout_width="@dimen/qs_seamless_fallback_icon_size" - android:layout_height="@dimen/qs_seamless_fallback_icon_size" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginStart="@dimen/qs_center_guideline_padding" - android:layout_marginEnd="@dimen/qs_seamless_fallback_margin" - android:tint="?android:attr/textColor" - android:src="@drawable/ic_cast_connected" - android:forceHasOverlappingRendering="false" /> - <!-- Seek Bar --> <!-- As per Material Design on Biderectionality, this is forced to LTR in code --> <SeekBar diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml index 459fb6611fd7..ee4530cb4377 100644 --- a/packages/SystemUI/res/layout/privacy_dialog.xml +++ b/packages/SystemUI/res/layout/privacy_dialog.xml @@ -24,9 +24,9 @@ android:layout_marginEnd="@dimen/ongoing_appops_dialog_side_margins" android:layout_marginTop="8dp" android:orientation="vertical" - android:paddingBottom="12dp" - android:paddingTop="8dp" + android:paddingBottom="8dp" + android:paddingTop="12dp" + android:paddingHorizontal="@dimen/ongoing_appops_dialog_side_padding" android:background="@drawable/qs_dialog_bg" /> -<!-- 12dp padding bottom so there's 20dp total under the icon --> -<!-- 8dp padding top, as there's 4dp margin in each row -->
\ No newline at end of file +<!-- 8dp padding bottom so there's 16dp total under the icon -->
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/privacy_dialog_item.xml b/packages/SystemUI/res/layout/privacy_dialog_item.xml index 7c8945eddc70..e1f0793f08ad 100644 --- a/packages/SystemUI/res/layout/privacy_dialog_item.xml +++ b/packages/SystemUI/res/layout/privacy_dialog_item.xml @@ -24,8 +24,6 @@ android:layout_marginTop="4dp" android:importantForAccessibility="yes" android:background="?android:attr/selectableItemBackground" - android:paddingLeft="@dimen/ongoing_appops_dialog_side_padding" - android:paddingRight="@dimen/ongoing_appops_dialog_side_padding" android:focusable="true" > <!-- 4dp marginTop makes 20dp minimum between icons --> diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml index 5b9ca1b26158..42a7c895ff84 100644 --- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml +++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml @@ -26,17 +26,38 @@ android:focusable="true" android:theme="@style/Theme.SystemUI.QuickSettings.Header"> - <com.android.systemui.statusbar.policy.Clock - android:id="@+id/clock" + <LinearLayout + android:id="@+id/clock_container" android:layout_width="wrap_content" android:layout_height="match_parent" - android:minWidth="48dp" - android:minHeight="48dp" + android:orientation="horizontal" + android:layout_gravity="center_vertical|start" android:gravity="center_vertical|start" - android:paddingStart="@dimen/status_bar_left_clock_starting_padding" - android:paddingEnd="@dimen/status_bar_left_clock_end_padding" - android:singleLine="true" - android:textAppearance="@style/TextAppearance.QS.Status" /> + > + + <com.android.systemui.statusbar.policy.Clock + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minHeight="48dp" + android:gravity="center_vertical|start" + android:paddingStart="@dimen/status_bar_left_clock_starting_padding" + android:paddingEnd="@dimen/status_bar_left_clock_end_padding" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.QS.Status" /> + + <com.android.systemui.statusbar.policy.VariableDateView + android:id="@+id/date_clock" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginStart="@dimen/status_bar_left_clock_end_padding" + android:gravity="center_vertical|start" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.QS.Status" + systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm" + systemui:shortDatePattern="@string/abbrev_month_day_no_year" + /> + </LinearLayout> <include layout="@layout/qs_carrier_group" android:id="@+id/carrier_group" diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml index bff93a99258a..b1e8c386fe21 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml @@ -36,7 +36,7 @@ android:layout_weight="1" android:gravity="center_vertical|start" > - <com.android.systemui.statusbar.policy.DateView + <com.android.systemui.statusbar.policy.VariableDateView android:id="@+id/date" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -44,9 +44,16 @@ android:gravity="center_vertical" android:singleLine="true" android:textAppearance="@style/TextAppearance.QS.Status" - systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" /> + systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm" + systemui:shortDatePattern="@string/abbrev_month_day_no_year" + /> </FrameLayout> + <!-- We want this to be centered (to align with notches). In order to do that, the following + has to hold (in portrait): + * date_container and privacy_container must have the same width and weight + * header_text_container must be gone + --> <android.widget.Space android:id="@+id/space" android:layout_width="0dp" @@ -73,7 +80,7 @@ android:layout_weight="1" android:gravity="center_vertical|end" > - <include layout="@layout/ongoing_privacy_chip" /> + <include layout="@layout/ongoing_privacy_chip" /> </FrameLayout> </LinearLayout> diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml index d1cc01f0694e..c122829c01b6 100644 --- a/packages/SystemUI/res/layout/screen_record_dialog.xml +++ b/packages/SystemUI/res/layout/screen_record_dialog.xml @@ -113,6 +113,8 @@ android:layout_height="wrap_content" android:minHeight="48dp" android:layout_weight="1" + android:layout_gravity="fill_vertical" + android:gravity="center_vertical" android:text="@string/screenrecord_taps_label" android:textAppearance="?android:attr/textAppearanceMedium" android:fontFamily="@*android:string/config_headlineFontFamily" diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml index 412276d05ea3..bbb8df1c5a4a 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml @@ -30,8 +30,8 @@ style="@style/TextAppearance.NotificationSectionHeaderButton" android:id="@+id/manage_text" android:layout_width="wrap_content" - android:layout_height="40dp" - android:layout_marginTop="16dp" + android:layout_height="48dp" + android:layout_marginTop="12dp" android:layout_gravity="start" android:background="@drawable/notif_footer_btn_background" android:focusable="true" @@ -43,8 +43,8 @@ style="@style/TextAppearance.NotificationSectionHeaderButton" android:id="@+id/dismiss_text" android:layout_width="wrap_content" - android:layout_height="40dp" - android:layout_marginTop="16dp" + android:layout_height="48dp" + android:layout_marginTop="12dp" android:layout_gravity="end" android:background="@drawable/notif_footer_btn_background" android:focusable="true" diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml index bea50e87a29a..71e8fc9991ed 100644 --- a/packages/SystemUI/res/layout/super_notification_shade.xml +++ b/packages/SystemUI/res/layout/super_notification_shade.xml @@ -62,8 +62,7 @@ <com.android.systemui.statusbar.LightRevealScrim android:id="@+id/light_reveal_scrim" android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" /> + android:layout_height="match_parent" /> <include layout="@layout/status_bar_expanded" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 8229661fbc24..3e35addcb236 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou mikrofoon te gebruik."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera te gebruik."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera of mikrofoon te gebruik."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Toestel"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander toestel"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Gelaai"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laai tans"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kragkennisgewingkontroles"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aan"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Af"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aan – gesiggegrond"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Met kragkennisgewingkontroles kan jy \'n belangrikheidvlak van 0 tot 5 vir \'n program se kennisgewings stel. \n\n"<b>"Vlak 5"</b>" \n- Wys aan die bokant van die kennisgewinglys \n- Laat volskermonderbreking toe \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 4"</b>" \n- Verhoed volskermonderbreking \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 3"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n\n"<b>"Vlak 2"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n\n"<b>"Vlak 1"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n- Versteek van sluitskerm en statusbalk \n- Wys aan die onderkant van die kennisgewinglys \n\n"<b>"Vlak 0"</b>" \n- Blokkeer alle kennisgewings van die program af"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Kennisgewings"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Jy sal nie meer hierdie kennisgewings sien nie"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om oop te maak"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data sal nie outomaties koppel nie"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding nie"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen ander netwerke beskikbaar nie"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Geen netwerke beskikbaar nie"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Netwerkbesonderhede"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tik op \'n netwerk om te koppel"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ontsluit om netwerke te bekyk"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Soek tans na netwerke …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kon nie aan netwerk koppel nie"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-fi sal vir nou nie outomaties koppel nie"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Sien alles"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ontkoppel Ethernet om netwerke te wissel"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Om toestelervaring te verbeter, kan programme en dienste steeds enige tyd na wi‑fi-netwerke soek, selfs wanneer wi‑fi af is. Jy kan dit in Wi-fi-opsporing-instellings verander. "<annotation id="link">"Verander"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 7f101d73b925..7ccaefed97f0 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ይህ የእርስዎን ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ይህ ካሜራዎን እንዲጠቀሙ ለተፈቀደላቸው ሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻን እገዳ ያነሳል።"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ይህ የእርስዎን ካሜራ ወይም ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ሌላ መሣሪያ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ባትሪ ሞልቷል"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ኃይል በመሙላት ላይ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"የኃይል ማሳወቂያ መቆጣጠሪያዎች"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"በርቷል"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ጠፍቷል"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"በርቷል - መልክ ላይ የተመሠረተ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"በኃይል ማሳወቂያ መቆጣጠሪያዎች አማካኝነት የአንድ መተግበሪያ ማሳወቂያዎች የአስፈላጊነት ደረጃ ከ0 እስከ 5 ድረስ ማዘጋጀት ይችላሉ። \n\n"<b>"ደረጃ 5"</b>" \n- በማሳወቂያ ዝርዝሩ አናት ላይ አሳይ \n- የሙሉ ማያ ገጽ ማቋረጥን ፍቀድ \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 4"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 3"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- በፍጹም አጮልቀው አይምልከቱ \n\n"<b>"ደረጃ 2"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ እና ንዝረትን በፍጹም አይኑር \n\n"<b>"ደረጃ 1"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ ወይም ንዝረትን በፍጹም አያደርጉ \n- ከመቆለፊያ ገጽ እና የሁኔታ አሞሌ ይደብቁ \n- በማሳወቂያ ዝርዝር ግርጌ ላይ አሳይ \n\n"<b>"ደረጃ 0"</b>" \n- ሁሉንም የመተግበሪያው ማሳወቂያዎች ያግዱ"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ማሳወቂያዎች"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"እነዚህን ማሳወቂያዎችን ከእንግዲህ አይመለከቷቸውም"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ለመክፈት የጣት አሻራ ይጠቀሙ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"የተንቀሳቃሽ ስልክ ውሂብ በራስ-ሰር አይገናኝም"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ግንኙነት የለም"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ሌላ አውታረ መረብ የሉም"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ምንም አውታረ መረቦች የሉም"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"የአውታረ መረብ ዝርዝሮች"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ለመገናኘት አንድ አውታረ መረብ መታ ያድርጉ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"አውታረ መረቦችን ለመመልከት ይክፈቱ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"አውታረ መረቦችን በመፈለግ ላይ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ከአውታረ መረቡ ጋር መገናኘት አልተሳካም"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wifi ለአሁን በራስ-ሰር አይገናኝም"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ሁሉንም ይመልከቱ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"አውታረ መረቦችን ለመቀየር፣ የኢተርኔት ግንኙነት ያቋርጡ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"የመሣሪያ ተሞክሮን ለማሻሻል፣ መተግበሪያዎች እና አገልግሎቶች አሁንም በማንኛውም ጊዜ የWi-Fi አውታረ መረቦችን መቃኘት ይችላሉ፣ Wi-Fi ጠፍቶ ቢሆንም እንኳ። ይህንን በ Wi‑Fi ቅኝት ቅንብሮች ውስጥ መቀየር ይችላሉ። "<annotation id="link">"ቀይር"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 8f230246a70e..bd261923d0a4 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> @@ -442,7 +443,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الميكروفون."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا أو الميكروفون."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"الجهاز"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"جهاز آخر"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"تم الشحن"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"جارٍ الشحن"</string> @@ -721,6 +722,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"عناصر التحكم في إشعارات التشغيل"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"تشغيل"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"إيقاف"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"تفعيل - استنادًا للوجه"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك ضبط مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة القفل وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"الإشعارات"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"لن تتلقى هذه الإشعارات بعد الآن."</string> @@ -1185,4 +1187,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"يمكنك استخدام بصمة الإصبع للفتح"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"المصادقة مطلوبة. المس مستشعر بصمات الإصبع للمصادقة."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"مكالمة هاتفية جارية"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"لن يتم تلقائيًا الاتصال ببيانات الجوّال."</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"لا يتوفّر اتصال بالإنترنت"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"لا تتوفّر شبكات أخرى."</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"لا تتوفّر أي شبكات."</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"تفاصيل الشبكة"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"انقر على إحدى الشبكات للاتصال بالإنترنت"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"فتح القفل لعرض الشبكات"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"جارٍ البحث عن شبكات…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"تعذّر الاتصال بالشبكة."</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"لن يتم الاتصال بشبكة Wi-Fi تلقائيًا في الوقت الحالي."</string> + <string name="see_all_networks" msgid="3773666844913168122">"عرض الكل"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"للتبديل بين الشبكات، يجب فصل إيثرنت."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"لتحسين تجربتك على الجهاز، يظل بإمكان التطبيقات والخدمات البحث عن شبكات Wi‑Fi في أي وقت، حتى عند إيقاف شبكة Wi‑Fi. وبإمكانك تغيير هذا الخيار في إعدادات البحث عن شبكات Wi-Fi. "<annotation id="link">"تغيير"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index c4438fca51e3..e2e4abc49d95 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -24,20 +24,20 @@ <string name="status_bar_no_notifications_title" msgid="7812479124981107507">"কোনো জাননী নাই"</string> <string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"চলিত"</string> <string name="status_bar_latest_events_title" msgid="202755896454005436">"জাননীসমূহ"</string> - <string name="battery_low_title" msgid="6891106956328275225">"বেটাৰি অতি সোনকালে শেষ হ\'ব পাৰে"</string> + <string name="battery_low_title" msgid="6891106956328275225">"বেটাৰী অতি সোনকালে শেষ হ\'ব পাৰে"</string> <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে"</string> <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, আপোনাৰ ব্যৱহাৰক ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী"</string> - <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে। বেটাৰি সঞ্চয়কাৰী অন হৈ আছে।"</string> + <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে। বেটাৰী সঞ্চয়কাৰী অন হৈ আছে।"</string> <string name="invalid_charger" msgid="4370074072117767416">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি। আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string> <string name="invalid_charger_title" msgid="938685362320735167">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string> <string name="battery_low_why" msgid="2056750982959359863">"ছেটিং"</string> - <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"বেটাৰি সঞ্চয়কাৰী অন কৰেনে?"</string> + <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"বেটাৰী সঞ্চয়কাৰী অন কৰেনে?"</string> <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"বেটাৰী সঞ্চয়কাৰীৰ বিষয়ে"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"অন কৰক"</string> - <string name="battery_saver_start_action" msgid="4553256017945469937">"বেটাৰি সঞ্চয়কাৰী অন কৰক"</string> - <string name="status_bar_settings_settings_button" msgid="534331565185171556">"ছেটিংসমূহ"</string> + <string name="battery_saver_start_action" msgid="4553256017945469937">"বেটাৰী সঞ্চয়কাৰী অন কৰক"</string> + <string name="status_bar_settings_settings_button" msgid="534331565185171556">"ছেটিং"</string> <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"ৱাই-ফাই"</string> <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"স্বয়ং-ঘূৰ্ণন স্ক্ৰীন"</string> <string name="status_bar_settings_mute_label" msgid="914392730086057522">"মিউট"</string> @@ -74,9 +74,10 @@ <string name="usb_port_enabled" msgid="531823867664717018">"চাৰ্জাৰ আৰু আনুষংগিক সামগ্ৰী চিনাক্ত কৰিবলৈ USB প’ৰ্ট সক্ষম কৰা হ’ল"</string> <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB সক্ষম কৰক"</string> <string name="learn_more" msgid="4690632085667273811">"অধিক জানক"</string> - <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string> - <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string> + <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> @@ -98,7 +99,7 @@ <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"সোঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string> <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string> - <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীণ ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string> + <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string> <string name="screenrecord_start_label" msgid="1750350278888217473">"ৰেকৰ্ড কৰা আৰম্ভ কৰিবনে?"</string> <string name="screenrecord_description" msgid="1123231719680353736">"ৰেকৰ্ড কৰি থাকোঁতে, Android Systemএ আপোনাৰ স্ক্রীনত দৃশ্যমান হোৱা অথবা আপোনাৰ ডিভাইচত প্লে’ হৈ থকা যিকোনো সংবেনদশীল তথ্য কেপচাৰ কৰিব পাৰে। এইটোত পাছৱর্ড, পৰিশোধৰ তথ্য, ফট’, বার্তাসমূহ আৰু অডিঅ’ অন্তর্ভুক্ত হয়।"</string> <string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিঅ’ ৰেকৰ্ড কৰক"</string> @@ -116,10 +117,10 @@ <string name="screenrecord_resume_label" msgid="4972223043729555575">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string> <string name="screenrecord_cancel_label" msgid="7850926573274483294">"বাতিল কৰক"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"শ্বেয়াৰ কৰক"</string> - <string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রীণ ৰেকৰ্ড কৰাটো বাতিল কৰা হ’ল"</string> + <string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রীন ৰেকৰ্ড কৰাটো বাতিল কৰা হ’ল"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"স্ক্ৰীন ৰেকৰ্ডিং ছেভ কৰা হ’ল"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"চাবলৈ টিপক"</string> - <string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রীণ ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string> + <string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রীন ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string> <string name="screenrecord_permission_error" msgid="7856841237023137686">"অনুমতি পাব পৰা নগ\'ল"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রীন ৰেকৰ্ড কৰা আৰম্ভ কৰোঁতে আসোঁৱাহ হৈছে"</string> <string name="usb_preference_title" msgid="1439924437558480718">"ইউএছবিৰে ফাইল স্থানান্তৰণৰ বিকল্পসমূহ"</string> @@ -130,9 +131,9 @@ <string name="accessibility_home" msgid="5430449841237966217">"গৃহ পৃষ্ঠাৰ বুটাম"</string> <string name="accessibility_menu" msgid="2701163794470513040">"মেনু"</string> <string name="accessibility_accessibility_button" msgid="4089042473497107709">"দিব্যাংগসকলৰ বাবে থকা সুবিধাসমূহ"</string> - <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্ৰীণ ঘূৰাওক"</string> + <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্ৰীন ঘূৰাওক"</string> <string name="accessibility_recent" msgid="901641734769533575">"অৱলোকন"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"সন্ধান কৰক"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"কেমেৰা"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ফ\'ন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string> @@ -189,14 +190,14 @@ <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string> <string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"মুখমণ্ডলৰ আইকন"</string> <string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"উপযোগিতা অনুসৰি জুম কৰা বুটাম।"</string> - <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"স্ক্ৰীণৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string> + <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"স্ক্ৰীনৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string> <string name="accessibility_bluetooth_disconnected" msgid="7195823280221275929">"ব্লুটুথ সংযোগ বিচ্ছিন্ন কৰা হ’ল।"</string> - <string name="accessibility_no_battery" msgid="3789287732041910804">"বেটাৰি শেষ"</string> - <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"বেটাৰিৰ এডাল দণ্ড।"</string> - <string name="accessibility_battery_two_bars" msgid="7895789999668425551">"বেটাৰিৰ দুডাল দণ্ড।"</string> - <string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰিৰ তিনিডাল দণ্ড।"</string> - <string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰি পূৰাকৈ চ্চাৰ্জ হৈছে।"</string> + <string name="accessibility_no_battery" msgid="3789287732041910804">"বেটাৰী শেষ"</string> + <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"বেটাৰীৰ এডাল দণ্ড।"</string> + <string name="accessibility_battery_two_bars" msgid="7895789999668425551">"বেটাৰীৰ দুডাল দণ্ড।"</string> + <string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰীৰ তিনিডাল দণ্ড।"</string> + <string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰী পূৰাকৈ চাৰ্জ হৈছে।"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string> <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string> @@ -228,11 +229,11 @@ <string name="accessibility_airplane_mode" msgid="1899529214045998505">"এয়াৰপ্লে’ন ম’ড।"</string> <string name="accessibility_vpn_on" msgid="8037549696057288731">"ভিপিএন অন অৱস্থাত আছে।"</string> <string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো ছিম কাৰ্ড নাই"</string> - <string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰিৰ বিৱৰণসমূহ খোলক"</string> - <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰি।"</string> + <string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰীৰ বিৱৰণসমূহ খোলক"</string> + <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰী।"</string> <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰী <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> - <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰি চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string> - <string name="accessibility_settings_button" msgid="2197034218538913880">"ছিষ্টেমৰ ছেটিংসমূহ৷"</string> + <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰী চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string> + <string name="accessibility_settings_button" msgid="2197034218538913880">"ছিষ্টেমৰ ছেটিং৷"</string> <string name="accessibility_notifications_button" msgid="3960913924189228831">"জাননীসমূহ।"</string> <string name="accessibility_overflow_action" msgid="8555835828182509104">"সকলো জাননীবোৰ চাওক"</string> <string name="accessibility_remove_notification" msgid="1641455251495815527">"জাননী মচক৷"</string> @@ -247,17 +248,17 @@ <skip /> <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"জাননী অগ্ৰাহ্য কৰা হৈছে।"</string> <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string> - <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিংসমূহ।"</string> - <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীণ।"</string> - <string name="accessibility_desc_settings" msgid="6728577365389151969">"ছেটিংসমূহ"</string> + <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string> + <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string> + <string name="accessibility_desc_settings" msgid="6728577365389151969">"ছেটিং"</string> <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"অৱলোকন।"</string> - <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীণ"</string> + <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string> <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string> <string name="accessibility_quick_settings_wifi" msgid="167707325133803052">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"ৱাই-ফাই অফ কৰা হ’ল।"</string> <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"ৱাই-ফাই অন কৰা হ’ল।"</string> <string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"ম’বাইল <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string> - <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"বেটাৰি <xliff:g id="STATE">%s</xliff:g>।"</string> + <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"বেটাৰী <xliff:g id="STATE">%s</xliff:g>।"</string> <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"এয়াৰপ্লেইন ম\'ড অফ হৈ আছে৷"</string> <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"এয়াৰপ্লেইন ম\'ড অন হৈ আছে৷"</string> <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"এয়াৰপ্লেইন ম\'ড অফ কৰা হ’ল।"</string> @@ -291,7 +292,7 @@ <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"ৰং বিপৰীতকৰণ অন কৰা হ’ল।"</string> <string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"ম’বাইল হটস্পট অফ কৰা হ’ল।"</string> <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"ম’বাইল হটস্পট অন কৰা হ’ল।"</string> - <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"স্ক্ৰীণ কাষ্টিং বন্ধ কৰা হ’ল।"</string> + <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"স্ক্ৰীন কাষ্টিং বন্ধ কৰা হ’ল।"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"কৰ্মস্থান ম’ড পজ হৈ আছে।"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"কৰ্মস্থান ম\'ড অন কৰা হ’ল।"</string> <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ডেটা সঞ্চয়কাৰী সুবিধা অফ কৰা হ’ল।"</string> @@ -317,16 +318,16 @@ <item quantity="other"> ভিতৰত আৰু <xliff:g id="NUMBER_1">%s</xliff:g>টা জাননী আছে।</item> </plurals> <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string> - <string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"জাননীৰ ছেটিংসমূহ"</string> - <string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> ছেটিংসমূহ"</string> - <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"আপোনাৰ ফ\'নৰ স্ক্ৰীণ স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string> - <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"স্ক্ৰীণ লেণ্ডস্কেপ দিশত লক কৰা হ’ল।"</string> - <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"স্ক্ৰীণ প\'ৰ্ট্ৰেইট দিশত লক কৰা হ’ল।"</string> - <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"আপোনাৰ ফ\'নৰ স্ক্ৰীণ এতিয়া স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string> - <string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"স্ক্ৰীণখন এতিয়া লেণ্ডস্কেইপ দিশত লক কৰা অৱস্থাত আছে।"</string> - <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"স্ক্ৰীণখন এতিয়া প\'ৰ্ট্ৰেইট দিশত লক কৰা অৱস্থাত আছে।"</string> + <string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"জাননীৰ ছেটিং"</string> + <string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> ছেটিং"</string> + <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"আপোনাৰ ফ\'নৰ স্ক্ৰীন স্বয়ংক্ৰিয়ভাৱে ঘূৰিব।"</string> + <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"স্ক্ৰীন লেণ্ডস্কে\'প দিশত লক কৰা হ’ল।"</string> + <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"স্ক্ৰীন প\'ৰ্ট্ৰেইট দিশত লক কৰা হ’ল।"</string> + <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"আপোনাৰ ফ\'নৰ স্ক্ৰীন এতিয়া স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string> + <string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"স্ক্ৰীনখন এতিয়া লেণ্ডস্কে\'প স্ক্ৰীনৰ দিশত লক কৰা অৱস্থাত আছে"</string> + <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"স্ক্ৰীনখন এতিয়া প\'ৰ্ট্ৰেইট দিশত লক কৰা অৱস্থাত আছে।"</string> <string name="dessert_case" msgid="9104973640704357717">"মিষ্টান্ন ভাণ্ডাৰ"</string> - <string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীণ ছেভাৰ"</string> + <string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীন ছেভাৰ"</string> <string name="ethernet_label" msgid="2203544727007463351">"ইথাৰনেট"</string> <string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"অধিক বিকল্পৰ বাবে আইকনসমূহ স্পৰ্শ কৰি হেঁচি ধৰক"</string> <string name="quick_settings_dnd_label" msgid="7728690179108024338">"অসুবিধা নিদিব"</string> @@ -337,7 +338,7 @@ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="6595808498429809855">"ব্লুটুথ (<xliff:g id="NUMBER">%d</xliff:g>টা ডিভাইচ)"</string> <string name="quick_settings_bluetooth_off_label" msgid="6375098046500790870">"ব্লুটুথ বন্ধ অৱস্থাত আছে"</string> <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"কোনো যোৰা লগোৱা ডিভাইচ উপলব্ধ নহয়।"</string> - <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> + <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string> <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিঅ’"</string> <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডছেট"</string> <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ইনপুট"</string> @@ -360,7 +361,7 @@ <string name="quick_settings_media_device_label" msgid="8034019242363789941">"মিডিয়া ডিভাইচ"</string> <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string> <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"জৰুৰীকালীন কল মাত্ৰ"</string> - <string name="quick_settings_settings_label" msgid="2214639529565474534">"ছেটিংসমূহ"</string> + <string name="quick_settings_settings_label" msgid="2214639529565474534">"ছেটিং"</string> <string name="quick_settings_time_label" msgid="3352680970557509303">"সময়"</string> <string name="quick_settings_user_label" msgid="1253515509432672496">"মোক"</string> <string name="quick_settings_user_title" msgid="8673045967216204537">"ব্যৱহাৰকাৰী"</string> @@ -375,7 +376,7 @@ <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"ৱাই-ফাই অন হৈ আছে"</string> <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"কোনো ৱাই-ফাই নেটৱৰ্ক নাই"</string> <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"অন কৰি থকা হৈছে…"</string> - <string name="quick_settings_cast_title" msgid="2279220930629235211">"স্ক্ৰীণ কাষ্ট"</string> + <string name="quick_settings_cast_title" msgid="2279220930629235211">"স্ক্ৰীন কাষ্ট"</string> <string name="quick_settings_casting" msgid="1435880708719268055">"কাষ্টিং"</string> <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"নাম নথকা ডিভাইচ"</string> <string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"কাষ্টৰ বাবে সাজু"</string> @@ -390,7 +391,7 @@ <string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন কৰা হ’ল"</string> <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ কৰক"</string> <string name="quick_settings_connected" msgid="3873605509184830379">"সংযোগ কৰা হ’ল"</string> - <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"সংযুক্ত, বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"সংযুক্ত, বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="quick_settings_connecting" msgid="2381969772953268809">"সংযোগ কৰি থকা হৈছে..."</string> <string name="quick_settings_tethering_label" msgid="5257299852322475780">"টেডাৰ কৰি থকা হৈছে"</string> <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"হটস্পট"</string> @@ -434,14 +435,14 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"এইটোৱে আপোনাৰ মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এইটোৱে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এইটোৱে আপোনাৰ কেমেৰা অথবা মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইচ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"চ্চার্জ হ’ল"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"চ্চার্জ হৈ আছে"</string> <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"বেটাৰিৰ চ্চাৰ্জ সম্পূর্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME">%s</xliff:g> বাকী"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"চ্চার্জ কৰি থকা নাই"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"নেটৱৰ্ক \nনিৰীক্ষণ কৰা হ\'ব পাৰে"</string> - <string name="description_target_search" msgid="3875069993128855865">"Search"</string> + <string name="description_target_search" msgid="3875069993128855865">"সন্ধান কৰক"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>ৰ বাবে ওপৰলৈ শ্লাইড কৰক।"</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>ৰ বাবে বাওঁফাললৈ শ্লাইড কৰক।"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string> @@ -463,7 +464,7 @@ <string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string> <string name="voice_hint" msgid="7476017460191291417">"কণ্ঠধ্বনিৰে সহায়ৰ বাবে আইকনৰ পৰা ছোৱাইপ কৰক"</string> <string name="camera_hint" msgid="4519495795000658637">"কেমেৰা খুলিবলৈ আইকনৰপৰা ছোৱাইপ কৰক"</string> - <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"সম্পূর্ণ নিৰৱতা। এই কার্যই স্ক্ৰীণ ৰীডাৰসমূহকো নিৰৱ কৰিব।"</string> + <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"সম্পূর্ণ নীৰৱতা। এই কার্যই স্ক্ৰীন ৰীডাৰসমূহকো নীৰৱ কৰিব।"</string> <string name="interruption_level_none" msgid="219484038314193379">"সম্পূর্ণ নিৰৱতা"</string> <string name="interruption_level_priority" msgid="661294280016622209">"কেৱল গুৰুত্বপূৰ্ণ"</string> <string name="interruption_level_alarms" msgid="2457850481335846959">"কেৱল এলাৰ্মসমূহ"</string> @@ -503,9 +504,9 @@ <string name="user_remove_user_title" msgid="9124124694835811874">"ব্যৱহাৰকাৰীক আঁতৰাবনে?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"এই ব্যৱহাৰকাৰীৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"আঁতৰাওক"</string> - <string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰি সঞ্চয়কাৰী অন হৈ আছে"</string> + <string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰী সঞ্চয়কাৰী অন হৈ আছে"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string> - <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰি সঞ্চয়কাৰী অফ কৰক"</string> + <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰী সঞ্চয়কাৰী অফ কৰক"</string> <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিংৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ৰেকর্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে?"</string> @@ -554,9 +555,9 @@ <string name="disconnect_vpn" msgid="26286850045344557">"ভিপিএন সংযোগ বিচ্ছিন্ন কৰক"</string> <string name="monitoring_button_view_policies" msgid="3869724835853502410">"নীতিসমূহ চাওক"</string> <string name="monitoring_button_view_controls" msgid="8316440345340701117">"নিয়ন্ত্ৰণসমূহ চাওক"</string> - <string name="monitoring_description_named_management" msgid="505833016545056036">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিংসমূহ, কৰ্পৰে’টৰ এক্সেছ, এপ্সমূহ, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> + <string name="monitoring_description_named_management" msgid="505833016545056036">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিং, কৰ্পৰে’টৰ এক্সেছ, এপ্, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g>এ হয়তো এই ডিভাইচটোৰ সৈতে জড়িত হৈ থকা ডেটা এক্সেছ কৰিব, এপ্ পৰিচালনা কৰিব আৰু এই ডিভাইচটোৰ ছেটিং সলনি কৰিব পাৰিব।\n\nআপোনাৰ যদি কিবা প্ৰশ্ন আছে, তেন্তে <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>ৰ সৈতে যোগাযোগ কৰক।"</string> - <string name="monitoring_description_management" msgid="4308879039175729014">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিংসমূহ, কৰ্পৰে’টৰ এক্সেছ, এপ্সমূহ, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> + <string name="monitoring_description_management" msgid="4308879039175729014">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিং, কৰ্পৰে’টৰ এক্সেছ, এপ্, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"আপোনাৰ প্ৰতিষ্ঠানে এই ডিভাইচটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰিছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্ক ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string> <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰিছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string> <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"এই ডিভাইচটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰা হৈছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string> @@ -568,12 +569,12 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"আপোনাৰ ব্যক্তিগত প্ৰ\'ফাইলটো <xliff:g id="VPN_APP">%1$s</xliff:g>ৰে সংযুক্ত হৈ আছে, যিয়ে আপোনাৰ ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string> <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"আপোনাৰ ডিভাইচটো <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>ৰ দ্বাৰা পৰিচালিত।"</string> <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>এ আপোনাৰ ডিভাইচটো পৰিচালনা কৰিবলৈ <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> ব্যৱহাৰ কৰে।"</string> - <string name="monitoring_description_do_body" msgid="7700878065625769970">"আপোনাৰ প্ৰশাসকে আপোনাৰ ডিভাইচৰ লগত জড়িত ছেটিংসমূহ, কৰ্প\'ৰেইট অনুমতি, এপসমূহ, ডেটা আৰু ডিভাইচৰ অৱস্থান সম্পৰ্কীয় তথ্য পৰ্যবেক্ষণ কৰাৰ লগতে পৰিচালনা কৰিব পাৰিব।"</string> + <string name="monitoring_description_do_body" msgid="7700878065625769970">"আপোনাৰ প্ৰশাসকে আপোনাৰ ডিভাইচৰ লগত জড়িত ছেটিং, কৰ্প\'ৰেইট এক্সেছ, এপ্, ডেটা আৰু ডিভাইচৰ অৱস্থান সম্পৰ্কীয় তথ্য পৰ্যবেক্ষণ তথা পৰিচালনা কৰিব পাৰে।"</string> <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string> <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"অধিক জানক"</string> <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"আপুনি <xliff:g id="VPN_APP">%1$s</xliff:g> ৰে সংযুক্ত হৈ আছে, ই ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি আপোনাৰ নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> - <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"ভিপিএন ছেটিংসমূহ খোলক"</string> + <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN ছেটিং খোলক"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"বিশ্বাসী পৰিচয়-পত্ৰসমূহ খোলক"</string> <string name="monitoring_description_network_logging" msgid="577305979174002252">"আপোনাৰ প্ৰশাসকে নেটৱৰ্ক লগিং অন কৰিছে, যিয়ে আপোনাৰ ডিভাইচটোত নেটৱৰ্ক ট্ৰেফিক পৰ্যবেক্ষণ কৰে।\n\nএই সম্পৰ্কে অধিক জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> @@ -595,7 +596,7 @@ <string name="hidden_notifications_setup" msgid="2064795578526982467">"ছেট আপ কৰক"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="volume_zen_end_now" msgid="5901885672973736563">"এতিয়া অফ কৰক"</string> - <string name="accessibility_volume_settings" msgid="1458961116951564784">"ধ্বনিৰ ছেটিংসমূহ"</string> + <string name="accessibility_volume_settings" msgid="1458961116951564784">"ধ্বনিৰ ছেটিং"</string> <string name="accessibility_volume_expand" msgid="7653070939304433603">"সম্প্ৰসাৰণ কৰক"</string> <string name="accessibility_volume_collapse" msgid="2746845391013829996">"সংকুচিত কৰক"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"স্বয়ংক্ৰিয় কেপশ্বন মিডিয়া"</string> @@ -620,7 +621,7 @@ <string name="screen_pinning_start" msgid="7483998671383371313">"এপ্টো পিন কৰা হ’ল"</string> <string name="screen_pinning_exit" msgid="4553787518387346893">"এপ্টো আনপিন কৰা হ’ল"</string> <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> লুকুৱাবনে?"</string> - <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"আপুনি ইয়াক পৰৱৰ্তী সময়ত ছেটিংসমূহত অন কৰিলে ই পুনৰ প্ৰকট হ\'ব।"</string> + <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"আপুনি পৰৱৰ্তী সময়ত ছেটিঙত ইয়াক অন কৰিলে ই পুনৰ প্ৰকট হ\'ব।"</string> <string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"লুকুৱাওক"</string> <string name="stream_voice_call" msgid="7468348170702375660">"কল"</string> <string name="stream_system" msgid="7663148785370565134">"ছিষ্টেম"</string> @@ -656,9 +657,9 @@ <string name="output_service_wifi" msgid="9003667810868222134">"ৱাই-ফাই"</string> <string name="output_service_bt_wifi" msgid="7186882540475524124">"ব্লুটুথ আৰু ৱাই-ফাই"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string> - <string name="show_battery_percentage" msgid="6235377891802910455">"সংযুক্ত বেটাৰিৰ কিমান শতাংশ বাকী আছে দেখুওৱাক"</string> - <string name="show_battery_percentage_summary" msgid="9053024758304102915">"চাৰ্জ হৈ নথকা অৱস্থাত বেটাৰি কিমান শতাংশ বাকী স্থিতি দণ্ডৰ ভিতৰত দেখুৱাওক"</string> - <string name="quick_settings" msgid="6211774484997470203">"ক্ষিপ্ৰ ছেটিংসমূহ"</string> + <string name="show_battery_percentage" msgid="6235377891802910455">"সংযুক্ত বেটাৰীৰ কিমান শতাংশ বাকী আছে দেখুওৱাক"</string> + <string name="show_battery_percentage_summary" msgid="9053024758304102915">"চাৰ্জ হৈ নথকা অৱস্থাত বেটাৰী কিমান শতাংশ বাকী স্থিতি দণ্ডৰ ভিতৰত দেখুৱাওক"</string> + <string name="quick_settings" msgid="6211774484997470203">"ক্ষিপ্ৰ ছেটিং"</string> <string name="status_bar" msgid="4357390266055077437">"স্থিতি দণ্ড"</string> <string name="overview" msgid="3522318590458536816">"অৱলোকন"</string> <string name="demo_mode" msgid="263484519766901593">"ছিষ্টেমৰ UI প্ৰদৰ্শন ম\'ড"</string> @@ -683,21 +684,21 @@ <string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string> <string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> বজাত"</string> <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> বজাত"</string> - <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"ক্ষিপ্ৰ ছেটিংসমূহ, <xliff:g id="TITLE">%s</xliff:g>।"</string> + <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"ক্ষিপ্ৰ ছেটিং, <xliff:g id="TITLE">%s</xliff:g>।"</string> <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"হটস্পট"</string> <string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string> <string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string> <string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string> <string name="tuner_persistent_warning" msgid="230466285569307806">"এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string> <string name="got_it" msgid="477119182261892069">"বুজি পালোঁ"</string> - <string name="tuner_toast" msgid="3812684836514766951">"অভিনন্দন! ছেটিংসমূহত System UI Tuner যোগ কৰা হৈছে"</string> - <string name="remove_from_settings" msgid="633775561782209994">"ছেটিংসমূহৰ পৰা আঁতৰাওক"</string> - <string name="remove_from_settings_prompt" msgid="551565437265615426">"ছেটিংসমূহৰ পৰা System UI Tuner আঁতৰাই ইয়াৰ সুবিধাসমূহ ব্যৱহাৰ কৰাটো বন্ধ কৰিবনে?"</string> + <string name="tuner_toast" msgid="3812684836514766951">"অভিনন্দন! ছেটিঙত System UI Tuner যোগ কৰা হৈছে"</string> + <string name="remove_from_settings" msgid="633775561782209994">"ছেটিঙৰ পৰা আঁতৰাওক"</string> + <string name="remove_from_settings_prompt" msgid="551565437265615426">"ছেটিঙৰ পৰা System UI Tuner আঁতৰাই ইয়াৰ সুবিধাসমূহ ব্যৱহাৰ কৰাটো বন্ধ কৰিবনে?"</string> <string name="activity_not_found" msgid="8711661533828200293">"আপোনাৰ ডিভাইচত এপ্লিকেশ্বনটো ইনষ্টল কৰা হোৱা নাই"</string> <string name="clock_seconds" msgid="8709189470828542071">"ঘড়ীৰ ছেকেণ্ড দেখুৱাওক"</string> - <string name="clock_seconds_desc" msgid="2415312788902144817">"স্থিতি দণ্ডত ঘড়ীৰ ছেকেণ্ড দেখুৱাওক। এই কার্যই বেটাৰিৰ অৱস্থাত প্ৰভাৱ পেলাব পাৰে।"</string> - <string name="qs_rearrange" msgid="484816665478662911">"ক্ষিপ্ৰ ছেটিংসমূহ পুনৰ সজাওক"</string> - <string name="show_brightness" msgid="6700267491672470007">"দ্ৰুত ছেটিংসমূহত উজ্জ্বলতা দেখুৱাওক"</string> + <string name="clock_seconds_desc" msgid="2415312788902144817">"স্থিতি দণ্ডত ঘড়ীৰ ছেকেণ্ড দেখুৱাওক। এই কার্যই বেটাৰীৰ জীৱনকালত প্ৰভাৱ পেলাব পাৰে।"</string> + <string name="qs_rearrange" msgid="484816665478662911">"ক্ষিপ্ৰ ছেটিং পুনৰ সজাওক"</string> + <string name="show_brightness" msgid="6700267491672470007">"দ্ৰুত ছেটিঙত উজ্জ্বলতা দেখুৱাওক"</string> <string name="experimental" msgid="3549865454812314826">"পৰীক্ষামূলক"</string> <string name="enable_bluetooth_title" msgid="866883307336662596">"ব্লুটুথ অন কৰিবনে?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"আপোনাৰ টেবলেটত আপোনাৰ কীব\'ৰ্ড সংযোগ কৰিবলৈ আপুনি প্ৰথমে ব্লুটুথ অন কৰিব লাগিব।"</string> @@ -709,7 +710,8 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্ব"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"অন"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"অফ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্বৰ সৈতে আপুনি এটা এপৰ জাননীৰ গুৰুত্বৰ স্তৰ ০ৰ পৰা ৫লৈ ছেট কৰিব পাৰে।\n\n"<b>"স্তৰ ৫"</b>" \n- জাননী তালিকাৰ একেবাৰে ওপৰত দেখুৱাওক \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ অনুমতি দিয়ক\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৪"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৩"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n\n"<b>"স্তৰ ২"</b>" \n- সম্পূর্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব \n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n- কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব\n\n"<b>" স্তৰ ১"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n-কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব \n- লক স্ক্ৰীণ আৰু স্থিতি দণ্ডৰ পৰা লুকুৱাই ৰাখক \n- জাননী তালিকাৰ একেবাৰে তলত দেখুৱাওক\n\n"<b>"স্তৰ ০"</b>" \n- এই এপৰ সকলো জাননী অৱৰোধ কৰক"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"অন আছে - মুখাৱয়ব ভিত্তিক"</string> + <string name="power_notification_controls_description" msgid="1334963837572708952">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্বৰ সৈতে আপুনি এটা এপৰ জাননীৰ গুৰুত্বৰ স্তৰ ০ৰ পৰা ৫লৈ ছেট কৰিব পাৰে।\n\n"<b>"স্তৰ ৫"</b>" \n- জাননী তালিকাৰ একেবাৰে ওপৰত দেখুৱাওক \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ অনুমতি দিয়ক\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৪"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৩"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n\n"<b>"স্তৰ ২"</b>" \n- সম্পূর্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব \n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n- কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব\n\n"<b>" স্তৰ ১"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n-কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব \n- লক স্ক্ৰীন আৰু স্থিতি দণ্ডৰ পৰা লুকুৱাই ৰাখক \n- জাননী তালিকাৰ একেবাৰে তলত দেখুৱাওক\n\n"<b>"স্তৰ ০"</b>" \n- এই এপৰ আটাইবোৰ জাননী অৱৰোধ কৰক"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"জাননীসমূহ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"আপোনাক এই জাননীসমূহ আৰু দেখুওৱা নহ’ব"</string> <string name="notification_channel_minimized" msgid="6892672757877552959">"এই জাননীসমূহ মিনিমাইজ কৰি থোৱা হ\'ব"</string> @@ -747,7 +749,7 @@ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"বাৰ্তালাপৰ জাননীৰ শীৰ্ষত আৰু প্ৰ’ফাইল চিত্ৰ হিচাপে লক স্ক্ৰীনত দেখুৱায়, এটা বাবল হিচাপে দেখা পোৱা যায়"</string> <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"বাৰ্তালাপৰ জাননীৰ শীৰ্ষত আৰু প্ৰ’ফাইল চিত্ৰ হিচাপে লক স্ক্ৰীনত দেখুৱায়, অসুবিধা নিদিব ম’ডত ব্যাঘাত জন্মায়"</string> <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"বাৰ্তালাপৰ জাননীৰ শীৰ্ষত আৰু প্ৰ’ফাইল চিত্ৰ হিচাপে লক স্ক্ৰীনত দেখুৱায়, এটা বাবল হিচাপে দেখা পোৱা যায়, অসুবিধা নিদিব ম’ডত ব্যাঘাত জন্মায়"</string> - <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ছেটিংসমূহ"</string> + <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ছেটিং"</string> <string name="notification_priority_title" msgid="2079708866333537093">"অগ্ৰাধিকাৰ"</string> <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বাৰ্তালাপৰ সুবিধাসমূহ সমৰ্থন নকৰে"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string> @@ -757,12 +759,12 @@ <string name="see_more_title" msgid="7409317011708185729">"অধিক চাওক"</string> <string name="appops_camera" msgid="5215967620896725715">"এই এপে কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> <string name="appops_microphone" msgid="8805468338613070149">"এই এপে মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string> - <string name="appops_overlay" msgid="4822261562576558490">"এই এপটো আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে।"</string> + <string name="appops_overlay" msgid="4822261562576558490">"এই এপটো আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে।"</string> <string name="appops_camera_mic" msgid="7032239823944420431">"এই এপে মাইক্ৰ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> - <string name="appops_camera_overlay" msgid="6466845606058816484">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> - <string name="appops_mic_overlay" msgid="4609326508944233061">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string> - <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> - <string name="notification_appops_settings" msgid="5208974858340445174">"ছেটিংসমূহ"</string> + <string name="appops_camera_overlay" msgid="6466845606058816484">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> + <string name="appops_mic_overlay" msgid="4609326508944233061">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string> + <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string> + <string name="notification_appops_settings" msgid="5208974858340445174">"ছেটিং"</string> <string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string> <string name="feedback_alerted" msgid="5192459808484271208">"ছিষ্টেমটোৱে স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া <b>গুৰুত্ব ডিফ’ল্ট</b>লৈ বৃদ্ধি কৰিছে।"</string> <string name="feedback_silenced" msgid="9116540317466126457">"ছিষ্টেমটোৱে স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া <b>গুৰুত্ব নীৰৱ</b>লৈ হ্ৰাস কৰিছে।"</string> @@ -790,7 +792,7 @@ <string name="notification_menu_gear_description" msgid="6429668976593634862">"জাননীৰ নিয়ন্ত্ৰণসমূহ"</string> <string name="notification_menu_snooze_description" msgid="4740133348901973244">"জাননীক স্নুজ কৰাৰ বিকল্পসমূহ"</string> <string name="notification_menu_snooze_action" msgid="5415729610393475019">"মোক মনত পেলাই দিব"</string> - <string name="notification_menu_settings_action" msgid="7085494017202764285">"ছেটিংসমূহ"</string> + <string name="notification_menu_settings_action" msgid="7085494017202764285">"ছেটিং"</string> <string name="snooze_undo" msgid="2738844148845992103">"আনডু কৰক"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ৰ বাবে স্নুজ কৰক"</string> <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170"> @@ -801,8 +803,8 @@ <item quantity="one"> %d মিনিট</item> <item quantity="other"> %d মিনিট</item> </plurals> - <string name="battery_panel_title" msgid="5931157246673665963">"বেটাৰিৰ ব্যৱহাৰ"</string> - <string name="battery_detail_charging_summary" msgid="8821202155297559706">"চ্চাৰ্জ কৰি থকাৰ সময়ত বেটাৰি সঞ্চয়কাৰী উপলব্ধ নহয়।"</string> + <string name="battery_panel_title" msgid="5931157246673665963">"বেটাৰীৰ ব্যৱহাৰ"</string> + <string name="battery_detail_charging_summary" msgid="8821202155297559706">"চাৰ্জ কৰি থকাৰ সময়ত বেটাৰী সঞ্চয়কাৰী উপলব্ধ নহয়।"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"বেটাৰী সঞ্চয়কাৰী"</string> <string name="battery_detail_switch_summary" msgid="3668748557848025990">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> বুটাম"</string> @@ -852,10 +854,10 @@ <string name="volume_and_do_not_disturb" msgid="502044092739382832">"অসুবিধা নিদিব"</string> <string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বুটামসমূহৰ শ্বৰ্টকাট"</string> <string name="volume_up_silent" msgid="1035180298885717790">"ভলিউম বঢ়োৱা বুটাম ব্যৱহাৰ কৰি অসুবিধা নিদিব নিষ্ক্ৰিয় কৰক"</string> - <string name="battery" msgid="769686279459897127">"বেটাৰি"</string> + <string name="battery" msgid="769686279459897127">"বেটাৰী"</string> <string name="clock" msgid="8978017607326790204">"ঘড়ী"</string> <string name="headset" msgid="4485892374984466437">"হেডছেট"</string> - <string name="accessibility_long_click_tile" msgid="210472753156768705">"ছেটিংসমূহ খোলক"</string> + <string name="accessibility_long_click_tile" msgid="210472753156768705">"ছেটিং খোলক"</string> <string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"হেডফ\'ন সংযোগ হৈ আছে"</string> <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"হেডছেট সংযোগ হৈ আছে"</string> <string name="data_saver" msgid="3484013368530820763">"ডেটা সঞ্চয়কাৰী"</string> @@ -919,22 +921,22 @@ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থান"</string> <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"টাইল যোগ দিয়া হৈছে"</string> <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"টাইল আঁতৰোৱা হৈছে"</string> - <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ক্ষিপ্ৰ ছেটিংসমূহৰ সম্পাদক।"</string> + <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ক্ষিপ্ৰ ছেটিঙৰ সম্পাদক।"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> জাননী: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ছেটিংসমূহ খোলক।"</string> - <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ক্ষিপ্ৰ ছেটিংসমূহ খোলক।"</string> - <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ক্ষিপ্ৰ ছেটিংসমূহ বন্ধ কৰক।"</string> + <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ছেটিং খোলক।"</string> + <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ক্ষিপ্ৰ ছেটিং খোলক।"</string> + <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ক্ষিপ্ৰ ছেটিং বন্ধ কৰক।"</string> <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"এলার্ম ছেট কৰা হ’ল।"</string> <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> হিচাপে ছাইন ইন হ’ল"</string> <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ব্যৱহাৰকাৰী বাছনি কৰক"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ইণ্টাৰনেট সংযোগ নাই"</string> <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"বিৱৰণসমূহ খোলক।"</string> <string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g>ৰ বাবে উপলব্ধ নহয়"</string> - <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g>ৰ ছেটিংসমূহ খোলক।"</string> - <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ছেটিংসমূহৰ ক্ৰম সম্পাদনা কৰক।"</string> + <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g>ৰ ছেটিং খোলক।"</string> + <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ছেটিঙৰ ক্ৰম সম্পাদনা কৰক।"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাৱাৰ মেনু"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>ৰ পৃষ্ঠা <xliff:g id="ID_1">%1$d</xliff:g>"</string> - <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীণ"</string> + <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীন"</string> <string name="thermal_shutdown_title" msgid="2702966892682930264">"আপোনাৰ ফ\'নটো গৰম হোৱাৰ কাৰণে অফ কৰা হৈছিল"</string> <string name="thermal_shutdown_message" msgid="6142269839066172984">"আপোনাৰ ফ’নটো এতিয়া স্বাভাৱিকভাৱে চলি আছে।\nঅধিক তথ্যৰ বাবে টিপক"</string> <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"আপোনাৰ ফ\'নটো অত্যধিক গৰম হোৱাৰ বাবে ইয়াক ঠাণ্ডা কৰিবলৈ অফ কৰা হৈছিল। আপোনাৰ ফ\'নটো এতিয়া স্বাভাৱিকভাৱে চলি আছে।\n\nআপোনাৰ ফ\'নটো গৰম হ\'ব পাৰে, যদিহে আপুনি:\n • ফ\'নটোৰ হাৰ্ডৱেৰ অত্যধিক মাত্ৰাত ব্যৱহাৰ কৰা এপসমূহ চলালে (যেনে, ভিডিঅ\' গেইম, ভিডিঅ\', দিক্-নিৰ্দেশনা এপসমূহ)\n • খুউব ডাঙৰ আকাৰৰ ফাইল আপল\'ড বা ডাউনল’ড কৰিলে\n • আপোনাৰ ফ\'নটো উচ্চ তাপমাত্ৰাৰ পৰিৱেশত ব্যৱহাৰ কৰিলে"</string> @@ -961,7 +963,7 @@ <string name="tuner_menu" msgid="363690665924769420">"মেনু"</string> <string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> এপ্"</string> <string name="notification_channel_alerts" msgid="3385787053375150046">"সতৰ্কবার্তাসমূহ"</string> - <string name="notification_channel_battery" msgid="9219995638046695106">"বেটাৰি"</string> + <string name="notification_channel_battery" msgid="9219995638046695106">"বেটাৰী"</string> <string name="notification_channel_screenshot" msgid="7665814998932211997">"স্ক্ৰীণশ্বটসমূহ"</string> <string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ষ্ট\'ৰেজ"</string> @@ -985,23 +987,23 @@ <string name="qs_dnd_keep" msgid="3829697305432866434">"Keep"</string> <string name="qs_dnd_replace" msgid="7712119051407052689">"সলনি কৰক"</string> <string name="running_foreground_services_title" msgid="5137313173431186685">"নেপথ্যত চলি থকা এপসমূহ"</string> - <string name="running_foreground_services_msg" msgid="3009459259222695385">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string> + <string name="running_foreground_services_msg" msgid="3009459259222695385">"বেটাৰী আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে সবিশেষ জানিবলৈ টিপক"</string> <string name="mobile_data_disable_title" msgid="5366476131671617790">"ম’বাইল ডেটা অফ কৰিবনে?"</string> <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপুনি <xliff:g id="CARRIER">%s</xliff:g>ৰ জৰিয়তে ডেটা সংযোগ বা ইণ্টাৰনেট সংযোগ নাপাব। কেৱল ৱাই-ফাইৰ যোগেৰে ইণ্টাৰনেট উপলব্ধ হ\'ব।"</string> <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"আপোনাৰ বাহক"</string> - <string name="touch_filtered_warning" msgid="8119511393338714836">"এটা এপে অনুমতি বিচাৰি কৰা অনুৰোধ এটা ঢাকি ধৰা বাবে ছেটিংসমূহে আপোনাৰ উত্তৰ সত্যাপন কৰিব পৰা নাই।"</string> + <string name="touch_filtered_warning" msgid="8119511393338714836">"এটা এপে অনুমতি বিচাৰি কৰা অনুৰোধ এটা ঢাকি ধৰা বাবে ছেটিঙৰ পৰা আপোনাৰ উত্তৰ সত্যাপন কৰিব পৰা নাই।"</string> <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>ক <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাবলৈ অনুমতি দিবনে?"</string> <string name="slice_permission_text_1" msgid="6675965177075443714">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ তথ্য পঢ়িব পাৰে"</string> <string name="slice_permission_text_2" msgid="6758906940360746983">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ ভিতৰত কাৰ্য কৰিব পাৰে"</string> <string name="slice_permission_checkbox" msgid="4242888137592298523">"<xliff:g id="APP">%1$s</xliff:g>ক যিকোনো এপৰ অংশ দেখুওৱাবলৈ অনুমতি দিয়ক"</string> <string name="slice_permission_allow" msgid="6340449521277951123">"অনুমতি দিয়ক"</string> <string name="slice_permission_deny" msgid="6870256451658176895">"অস্বীকাৰ কৰক"</string> - <string name="auto_saver_title" msgid="6873691178754086596">"বেটাৰি সঞ্চয়কাৰীৰ সময়সূচী সক্ৰিয় কৰিবলৈ টিপক"</string> - <string name="auto_saver_text" msgid="3214960308353838764">"বেটাৰি শেষ হোৱাৰ সম্ভাৱনা থাকিলে অন কৰক"</string> + <string name="auto_saver_title" msgid="6873691178754086596">"বেটাৰী সঞ্চয়কাৰীৰ সময়সূচী সক্ৰিয় কৰিবলৈ টিপক"</string> + <string name="auto_saver_text" msgid="3214960308353838764">"বেটাৰী শেষ হোৱাৰ সম্ভাৱনা থাকিলে অন কৰক"</string> <string name="no_auto_saver_action" msgid="7467924389609773835">"নালাগে, ধন্যবাদ"</string> - <string name="auto_saver_enabled_title" msgid="4294726198280286333">"বেটাৰি সঞ্চয়কাৰীৰ সময়সূচী অন কৰা অৱস্থাত আছে"</string> - <string name="auto_saver_enabled_text" msgid="7889491183116752719">"বেটাৰি চ্চাৰ্জৰ স্তৰ <xliff:g id="PERCENTAGE">%d</xliff:g>%%তকৈ কম হোৱাৰ লগে লগে বেটাৰি সঞ্চয়কাৰী স্বয়ংক্ৰিয়ভাৱে অন হ’ব।"</string> - <string name="open_saver_setting_action" msgid="2111461909782935190">"ছেটিংবোৰ"</string> + <string name="auto_saver_enabled_title" msgid="4294726198280286333">"বেটাৰী সঞ্চয়কাৰীৰ সময়সূচী অন কৰা অৱস্থাত আছে"</string> + <string name="auto_saver_enabled_text" msgid="7889491183116752719">"বেটাৰী চাৰ্জৰ স্তৰ <xliff:g id="PERCENTAGE">%d</xliff:g>%%তকৈ কম হোৱাৰ লগে লগে বেটাৰী সঞ্চয়কাৰী স্বয়ংক্ৰিয়ভাৱে অন হ’ব।"</string> + <string name="open_saver_setting_action" msgid="2111461909782935190">"ছেটিং"</string> <string name="auto_saver_okay_action" msgid="7815925750741935386">"বুজি পালোঁ"</string> <string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI হীপ ডাম্প কৰক"</string> <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string> @@ -1013,15 +1015,15 @@ <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(কৰ্মস্থান)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"ফ’ন কল"</string> <string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(<xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>ৰ জৰিয়তে)"</string> - <string name="privacy_type_camera" msgid="7974051382167078332">"কেমেৰা"</string> + <string name="privacy_type_camera" msgid="7974051382167078332">"Camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"অৱস্থান"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্ৰ\'ফ\'ন"</string> <string name="sensor_privacy_mode" msgid="4462866919026513692">"ছেন্সৰ অফ হৈ আছে"</string> <string name="device_services" msgid="1549944177856658705">"ডিভাইচ সেৱা"</string> <string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string> <string name="bubble_accessibility_action_move" msgid="3185080443743819178">"আঁতৰাওক"</string> - <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰা হ’ল। সলনি কৰিবলৈ ছেটিংসমূহ-লৈ যাওক।"</string> - <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰিবলৈ ছেটিংসমূহ-লৈ যাওক"</string> + <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰা হ’ল। সলনি কৰিবলৈ ছেটিঙলৈ যাওক।"</string> + <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰিবলৈ ছেটিঙলৈ যাওক"</string> <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ষ্টেণ্ডবাই"</string> <string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string> <string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string> @@ -1064,7 +1066,7 @@ <string name="controls_favorite_removed" msgid="5276978408529217272">"সকলো নিয়ন্ত্ৰণ আঁতৰোৱা হৈছে"</string> <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"সালসলনিসমূহ ছেভ নহ’ল"</string> <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"অন্য এপ্সমূহ চাওক"</string> - <string name="controls_favorite_load_error" msgid="5126216176144877419">"নিয়ন্ত্ৰণসমূহ ল’ড কৰিবপৰা নগ’ল। এপ্টোৰ ছেটিংসমূহ সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APP">%s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string> + <string name="controls_favorite_load_error" msgid="5126216176144877419">"নিয়ন্ত্ৰণসমূহ ল’ড কৰিবপৰা নগ’ল। এপ্টোৰ ছেটিং সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APP">%s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string> <string name="controls_favorite_load_none" msgid="7687593026725357775">"সমিল নিয়ন্ত্ৰণসমূহ উপলব্ধ নহয়"</string> <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string> <string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহত যোগ দিয়ক"</string> @@ -1087,7 +1089,7 @@ <string name="controls_media_active_session" msgid="3146882316024153337">"বৰ্তমানৰ মিডিয়াৰ ছেশ্বনটো লুকুৱাব নোৱাৰি।"</string> <string name="controls_media_dismiss_button" msgid="9081375542265132213">"অগ্ৰাহ্য কৰক"</string> <string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string> - <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string> + <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিং"</string> <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ত <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ৰ <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ হৈ আছে"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"প্লে’ কৰক"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> খোলক"</string> @@ -1097,7 +1099,7 @@ <string name="controls_error_retryable" msgid="864025882878378470">"আসোঁৱাহ, পুনৰ চেষ্টা কৰি আছে…"</string> <string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string> <string name="controls_error_removed_title" msgid="1207794911208047818">"নিয়ন্ত্ৰণটো উপলব্ধ নহয়"</string> - <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> এক্সেছ কৰিব পৰা নগ’ল। নিয়ন্ত্ৰণটো এতিয়াও উপলব্ধ আৰু এপ্টোৰ ছেটিংসমূহ সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APPLICATION">%2$s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string> + <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> এক্সেছ কৰিব পৰা নগ’ল। নিয়ন্ত্ৰণটো এতিয়াও উপলব্ধ আৰু এপ্টোৰ ছেটিং সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APPLICATION">%2$s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string> <string name="controls_open_app" msgid="483650971094300141">"এপ্টো খোলক"</string> <string name="controls_error_generic" msgid="352500456918362905">"স্থিতি ল’ড কৰিব নোৱাৰি"</string> <string name="controls_error_failed" msgid="960228639198558525">"আসোঁৱাহ হৈছে, আকৌ চেষ্টা কৰক"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলিবলৈ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ আৱশ্যক। বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰিবলৈ ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"চলি থকা ফ’ন কল"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ম’বাইল ডেটা স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"সংযোগ নাই"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"ৱাই-ফাই"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"নেটৱৰ্কৰ সবিশেষ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"সংযোগ কৰিবলৈ এটা নেটৱৰ্কত টিপক"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"নেটৱর্ক চাবলৈ আনলক কৰক"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"নেটৱৰ্ক সন্ধান কৰি থকা হৈছে…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"নেটৱৰ্কৰ সৈতে সংযোগ কৰিব পৰা নগ\'ল"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"এতিয়া ৱাই-ফাই স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string> + <string name="see_all_networks" msgid="3773666844913168122">"আটাইবোৰ চাওক"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটৱৰ্ক সলনি কৰিবলৈ ইথাৰনেটৰ পৰা সংযোগ বিচ্ছিন্ন কৰক"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ডিভাইচ ব্যৱহাৰৰ অভিজ্ঞতা উন্নত কৰিবলৈ ৱাই-ফাই অফ থকা অৱস্থাতো এপ্ আৰু সেৱাসমূহে ৱাই-ফাই নেটৱৰ্কবোৰ স্কেন কৰিব পাৰে। আপুনি ৱাই-ফাই স্কেনিঙৰ ছেটিঙত এইটো সলনি কৰিব পাৰে। "<annotation id="link">"সলনি কৰক"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 7e50b194000a..89dca12e9b8d 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Digər cihaz"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Enerji yığılıb"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Enerji doldurulur"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Enerji bildiriş nəzarəti"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aktiv"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Deaktiv"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktiv - Üz əsaslı"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n"<b>"Səviyyə 5"</b>" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n"<b>"Səviyyə 4"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n"<b>"Level 3"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n"<b>"Level 2"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n"<b>"Səviyyə 1"</b>" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n"<b>"Səviyyə 0"</b>" \n- Bütün bildirişləri tətbiqdən blok edin"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Bildirişlər"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Artıq bu bildirişləri görməyəcəkəsiniz"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmaq üçün barmaq izindən istifadə edin"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Doğrulanma tələb olunur. Doğrulamaq üçün barmaq izi sensoruna toxunun."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Davam edən zəng"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil data avtomatik qoşulmayacaq"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yoxdur"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Heç bir başqa şəbəkə əlçatan deyil"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Əlçatan şəbəkə yoxdur"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Şəbəkə məlumatları"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Qoşulmaq üçün şəbəkəyə toxunun"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Şəbəkələrə baxmaq üçün kilidi açın"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Şəbəkə axtarılır…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Şəbəkəyə qoşulmaq alınmadı"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi hələlik avtomatik qoşulmayacaq"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Hamısına baxın"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Şəbəkəni dəyişmək üçün etherneti ayırın"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Cihaz təcrübəsini yaxşılaşdırmaq üçün Wi-Fi deaktiv olduqda belə, tətbiqlər və xidmətlər Wi-Fi şəbəkəsini axtara biləcək. Bunu Wi-Fi axtarışı ayarlarında dəyişə bilərsiniz. "<annotation id="link">"Dəyişin"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 701765f4036c..7a520473e022 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje mikrofona."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere ili mikrofona."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjena je"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Puni se"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Napredne kontrole za obaveštenja"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Uključeno"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Isključeno"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na osnovu lica"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Pomoću naprednih kontrola za obaveštenja možete da podesite nivo važnosti od 0. do 5. za obaveštenja aplikacije. \n\n"<b>"5. nivo"</b>" \n– Prikazuju se u vrhu liste obaveštenja \n- Dozvoli prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"4. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"3. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n\n"<b>"2. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n\n"<b>"1. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n– Sakrij na zaključanom ekranu i statusnoj traci \n– Prikazuju se u dnu liste obaveštenja \n\n"<b>"0. nivo"</b>" \n– Blokiraj sva obaveštenja iz aplikacije"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Obaveštenja"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Više nećete videti ova obaveštenja"</string> @@ -1013,7 +1015,7 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> - <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Koristi <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Koristi: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedavno koristio/la <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(posao)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je potvrda identiteta. Dodirnite senzor za otisak prsta da biste potvrdili identitet."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktuelni telefonski poziv"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nije uspelo autom. povezivanje preko mob. podataka"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Veza nije uspostavljena"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalji o mreži"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da biste se povezali"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte da biste videli mreže"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traže se mreže…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje sa mrežom nije uspelo"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi trenutno ne može da se automatski poveže"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Pogledajte sve"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da biste promenili mrežu, prekinite eternet vezu"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Radi boljeg doživljaja uređaja, aplikacije i usluge i dalje mogu da traže WiFi mreže u bilo kom trenutku, čak i kada je WiFi isključen. To možete da promenite u podešavanjima WiFi skeniranja. "<annotation id="link">"Promenite"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 5da6cf8b9c35..8aa994f610d0 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць мікрафон."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру ці мікрафон."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Прылада"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Іншая прылада"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зараджаны"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарадка"</string> @@ -702,8 +703,8 @@ <string name="activity_not_found" msgid="8711661533828200293">"Праграма не ўсталявана на вашым тэлефоне"</string> <string name="clock_seconds" msgid="8709189470828542071">"Паказваць секунды гадзінніка"</string> <string name="clock_seconds_desc" msgid="2415312788902144817">"Паказваць секунды гадзінніка на панэлі стану. Можа паўплываць на рэсурс акумулятара."</string> - <string name="qs_rearrange" msgid="484816665478662911">"Змяніць парадак Хуткіх налад"</string> - <string name="show_brightness" msgid="6700267491672470007">"Паказваць яркасць у Хуткіх наладах"</string> + <string name="qs_rearrange" msgid="484816665478662911">"Змяніць парадак хуткіх налад"</string> + <string name="show_brightness" msgid="6700267491672470007">"Паказваць яркасць у хуткіх наладах"</string> <string name="experimental" msgid="3549865454812314826">"Эксперыментальныя"</string> <string name="enable_bluetooth_title" msgid="866883307336662596">"Уключыць Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Для падлучэння клавіятуры да планшэта трэба спачатку ўключыць Bluetooth."</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Пашыранае кіраванне апавяшчэннямі"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Уключана"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Выключана"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Уключана – З улікам паставы галавы"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"З дапамогай пашыранага кіравання апавяшчэннямі вы можаце задаваць узровень важнасці апавяшчэнняў праграмы ад 0 да 5. \n\n"<b>"Узровень 5"</b>" \n- Паказваць уверсе спіса апавяшчэнняў \n- Дазваляць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 4"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 3"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n\n"<b>"Узровень 2"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n\n"<b>"Узровень 1"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n- Хаваць з экрана блакіроўкі і панэлі стану \n- Паказваць унізе спіса апавяшчэнняў \n\n"<b>"Узровень 0"</b>" \n- Блакіраваць усе апавяшчэнні ад праграмы"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Апавяшчэнні"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Вы больш не будзеце бачыць гэтыя апавяшчэнні"</string> @@ -1071,7 +1073,7 @@ <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_subtitle" msgid="6481675111056961083">"Выберыце элементы кіравання, да якіх вы хочаце мець доступ з Хуткіх налад"</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> <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Змяненні не захаваны"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Каб адкрыць, скарыстайце адбітак пальца"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Патрабуецца аўтэнтыфікацыя. Дакраніцеся да сканера адбіткаў пальцаў."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Бягучы тэлефонны выклік"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мабільная перадача даных не ўключаецца аўтаматычна"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма падключэння"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Больш няма даступных сетак"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Няма даступных сетак"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Інфармацыя пра сетку"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Каб падключыцца, націсніце на сетку"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Разблакіраваць для прагляду сетак"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Выконваецца пошук сетак…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не ўдалося падключыцца да сеткі"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Аўтаматычнае падключэнне да Wi-Fi адсутнічае"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Паказаць усе"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Каб падключыцца да сетак, выключыце Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Каб палепшыць працу прылады, вы можаце дазволіць праграмам і сэрвісам шукаць сеткі Wi-Fi, нават калі Wi‑Fi выключаны. Змяніць гэты рэжым можна ў наладах пошуку сетак Wi-Fi. "<annotation id="link">"Змяніць"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 742de25d539c..e9c222ca1cc1 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват микрофона ви."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата ви."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата или микрофона ви."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Друго устройство"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заредена"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарежда се"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Контроли за известията"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Вкл."</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Изкл."</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Вкл. – въз основа на лицето"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"С помощта на контролите за известията можете да зададете ниво на важност от 0 до 5 за известията от дадено приложение. \n\n"<b>"Ниво 5"</b>" \n– Показване най-горе в списъка с известия. \n– Разрешаване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 4"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 3"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n\n"<b>"Ниво 2"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n\n"<b>"Ниво 1"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n– Скриване от заключения екран и лентата на състоянието. \n– Показване най-долу в списъка с известия. \n\n"<b>"Ниво 0"</b>" \n– Блокиране на всички известия от приложението."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Известия"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Вече няма да виждате тези известия"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Използвайте отпечатък за отваряне"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Изисква се удостоверяване на самоличността. За целта докоснете сензора за отпечатъци."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущо телефонно обаждане"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Връзката за мобилни данни няма да е автоматична"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма връзка"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Няма други налични мрежи"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Няма налични мрежи"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Подробности за мрежата"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Докоснете мрежа, за да се свържете"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Отключване с цел преглед на мрежите"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Търсят се мрежи…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Свързването с мрежата не бе успешно"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Засега Wi-Fi няма да се свързва автоматично"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Вижте всички"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"За да превключите мрежите, прекъснете връзката с Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"С цел подобряване на практическата работа с устройството приложенията и услугите пак могат да сканират за Wi‑Fi мрежи по всяко време дори когато функцията за Wi‑Fi e изключена. Можете да промените съответното поведение от настройките за сканиране за Wi‑Fi. "<annotation id="link">"Промяна"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index b35ae1f1efde..3f4746b2c8c5 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"এটার জন্য মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার মাইক্রোফোন ব্যবহার করার অনুমতি দেওয়া হয়েছে।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এটার জন্য ক্যামেরার অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এটার জন্য ক্যামেরা অথবা মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা অথবা মাইক্রোফোন ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইস"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইস"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"চার্জ হয়েছে"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"চার্জ হচ্ছে"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"চালু আছে"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"বন্ধ আছে"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"চালু আছে - মুখের হিসেবে"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনও অ্যাপ্লিকেশনের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n"<b>"লেভেল ৫"</b>" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রিনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৪"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৩"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n\n"<b>"লেভেল ২"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n\n"<b>"লেভেল ১"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n- লক স্ক্রিন এবং স্ট্যাটাস বার থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n"<b>"লেভেল ০"</b>" \n- অ্যাপ্লিকেশন থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"বিজ্ঞপ্তি"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"এই বিজ্ঞপ্তিগুলি আপনাকে আর দেখানো হবে না"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"যাচাইকরণ করতে হবে। যাচাইকরণ করতে আঙুলের ছাপের সেন্সরে টাচ করুন।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ব্যবহারকারী এখন ফোনে কথা বলছেন"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"মোবাইল ডেটা নিজে থেকে কানেক্ট হবে না"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"কানেকশন নেই"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনও নেটওয়ার্ক উপলভ্য নেই"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"কোনও নেটওয়ার্ক উপলভ্য নেই"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"ওয়াই-ফাই"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"নেটওয়ার্কের বিবরণ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"কানেক্ট করতে একটি নেটওয়ার্কে ট্যাপ করুন"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"নেটওয়ার্ক দেখার জন্য আনলক করুন"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"নেটওয়ার্ক সার্চ করা হচ্ছে…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"নেটওয়ার্কে কানেক্ট করা যায়নি"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"এখন ওয়াই-ফাই নিজে থেকে কানেক্ট হবে না"</string> + <string name="see_all_networks" msgid="3773666844913168122">"সবকটি দেখুন"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটওয়ার্ক বদলাতে ইথারনেট ডিসকানেক্ট করুন"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ডিভাইস সংক্রান্ত অভিজ্ঞতা আরও ভাল করতে, অ্যাপ ও পরিষেবা যেকোনও সময় আপনার ওয়াই-ফাই নেটওয়ার্ক স্ক্যান করতে পারবে, এমনকি ডিভাইসের ওয়াই-ফাই বন্ধ করা থাকলেও। ওয়াই-ফাই স্ক্যানিং সেটিংস থেকে আপনি এটি পরিবর্তন করতে পারবেন। "<annotation id="link">"পরিবর্তন করুন"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index b87739732e4b..fdb862a980fc 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vaš mikrofon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru ili mikrofon."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrole obavještenja o napajanju"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Uključeno"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Isključeno"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na osnovu lica"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Obavještenja"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Nećete više vidjeti ova obavještenja"</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor za otisak prsta da autentificirate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u toku"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Prijenos podataka se neće automatski povezati"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani s mrežom"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Druge mreže nisu dostupne"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalji o mreži"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da se povežete"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte da vidite mreže"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traženje mreža…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje s mrežom nije uspjelo"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi se trenutno ne može automatski povezati"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da promijenite mrežu, isključite ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Radi poboljšanja iskustva s uređajem aplikacije i usluge i dalje mogu bilo kada skenirati WiFi mreže, čak i kada je WiFi isključen. Ovo možete promijeniti u Postavkama skeniranja WiFi mreže. "<annotation id="link">"Promijeni"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index a5504f02833e..72964cb134d1 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar el micròfon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera o el micròfon."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositiu"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Un altre dispositiu"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"S\'està carregant"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controls millorats per a notificacions"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activat"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desactivat"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activat: basat en cares"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n"<b>"Nivell 5"</b>" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 4"</b>" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 3"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n"<b>"Nivell 2"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n"<b>"Nivell 1"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n"<b>"Nivell 0"</b>" \n- Bloqueja totes les notificacions de l\'aplicació"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificacions"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Ja no veuràs aquestes notificacions"</string> @@ -1008,7 +1010,7 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> - <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En ús per <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ho està utilitzant"</string> <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Utilitzat recentment per <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(feina)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Trucada"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilitza l\'empremta digital per obrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticació necessària. Toca el sensor d\'empremtes digitals per autenticar-te."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Trucada en curs"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Les dades mòbils no es connectaran automàticament"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sense connexió"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hi ha cap altra xarxa disponible"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No hi ha cap xarxa disponible"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalls de la xarxa"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca una xarxa per connectar-te"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueja per veure xarxes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"S\'estan cercant xarxes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"No s\'ha pogut connectar a la xarxa"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Per ara la Wi‑Fi no es connectarà automàticament"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Mostra-ho tot"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per canviar de xarxa, desconnecta la connexió Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per millorar l\'experiència del dispositiu, les aplicacions i els serveis poden cercar xarxes Wi‑Fi en qualsevol moment, fins i tot quan la Wi‑Fi estigui desactivada. Pots canviar aquesta opció a la configuració de cerca de xarxes Wi‑Fi. "<annotation id="link">"Canvia-la"</annotation>"."</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f48c9fb1cd77..23fc8a52184e 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš mikrofon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát či mikrofon."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Zařízení"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Další zařízení"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabito"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíjení"</string> @@ -715,7 +716,8 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Rozšířené ovládací prvky oznámení"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Zapnuto"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Vypnuto"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 4"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 3"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n"<b>"Úroveň 2"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n"<b>"Úroveň 1"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt z obrazovky uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"<b>";Úroveň 0"</b>" \n– Blokovat všechna oznámení z aplikace"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Zapnuto – podle obličeje"</string> + <string name="power_notification_controls_description" msgid="1334963837572708952">"Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 4"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 3"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n"<b>"Úroveň 2"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n"<b>"Úroveň 1"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt na obrazovce uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"<b>";Úroveň 0"</b>" \n– Blokovat všechna oznámení z aplikace"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Oznámení"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Tato oznámení již nebudete dostávat"</string> <string name="notification_channel_minimized" msgid="6892672757877552959">"Tato oznámení budou minimalizována"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"K otevření použijte otisk prstu"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Je vyžadováno ověření. Dotkněte se snímače otisků prstů."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Probíhající hovor"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilní data se nebudou připojovat automaticky"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Žádné připojení"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Žádné další sítě nejsou k dispozici"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nejsou k dispozici žádné sítě"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Podrobnosti sítě"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Klepněte na síť, ke které se chcete připojit"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sítě uvidíte po odemknutí"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Vyhledávání sítí…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Připojení k síti se nezdařilo"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi se prozatím nebude připojovat automaticky"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Zobrazit vše"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pokud chcete přepnout sítě, odpojte ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Za účelem lepšího fungování zařízení mohou aplikace a služby vyhledávat sítě Wi-Fi, i když je připojení Wi-Fi vypnuté. Toto chování můžete změnit v nastavení vyhledávání Wi-Fi. "<annotation id="link">"Změnit"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index cbef46488c5a..85d976fad13a 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> @@ -274,10 +275,10 @@ <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Der er oprettet forbindelse til Bluetooth."</string> <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"Bluetooth er slået fra."</string> <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"Bluetooth er slået til."</string> - <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Placeringsrapportering er slået fra."</string> - <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"Placeringsrapportering er slået til."</string> - <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"Placeringsrapportering er slået fra."</string> - <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"Placeringsrapportering er slået til."</string> + <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Lokationsrapportering er slået fra."</string> + <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"Lokationsrapportering er slået til."</string> + <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"Lokationsrapportering er slået fra."</string> + <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"Lokationsrapportering er slået til."</string> <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"Alarmen er indstillet til <xliff:g id="TIME">%s</xliff:g>."</string> <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"Luk panelet."</string> <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"Mere tid."</string> @@ -308,7 +309,7 @@ <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Genoptag"</string> <string name="gps_notification_searching_text" msgid="231304732649348313">"Søger efter GPS"</string> <string name="gps_notification_found_text" msgid="3145873880174658526">"Placeringen er angivet ved hjælp af GPS"</string> - <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive placeringsanmodninger"</string> + <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive lokationsanmodninger"</string> <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensorer er slået fra"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Ryd alle notifikationer."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> mere"</string> @@ -351,8 +352,8 @@ <string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"Stående"</string> <string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"Liggende"</string> <string name="quick_settings_ime_label" msgid="3351174938144332051">"Inputmetode"</string> - <string name="quick_settings_location_label" msgid="2621868789013389163">"Placering"</string> - <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Placering fra"</string> + <string name="quick_settings_location_label" msgid="2621868789013389163">"Lokation"</string> + <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokation fra"</string> <string name="quick_settings_camera_label" msgid="5612076679385269339">"Kameraadgang"</string> <string name="quick_settings_mic_label" msgid="8392773746295266375">"Mikrofonadgang"</string> <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Tilgængelig"</string> @@ -383,7 +384,7 @@ <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Manglende Wi-Fi-forbindelse"</string> <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"AUTO"</string> - <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Byt om på farver"</string> + <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Ombyt farver"</string> <string name="quick_settings_color_space_label" msgid="537528291083575559">"Farvekorrigeringstilstand"</string> <string name="quick_settings_more_settings" msgid="2878235926753776694">"Flere indstillinger"</string> <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Brugerindstillinger"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge din mikrofon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera eller din mikrofon."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhed"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Anden enhed"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opladet"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Oplader"</string> @@ -554,9 +555,9 @@ <string name="disconnect_vpn" msgid="26286850045344557">"Afbryd VPN-forbindelse"</string> <string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se politikker"</string> <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Se indstillinger"</string> - <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string> + <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds lokationsdata.\n\nKontakt din it-administrator for at få mere at vide."</string> <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> kan muligvis administrere apps, få adgang til data, der er tilknyttet denne enhed, og ændre enhedens indstillinger.\n\nKontakt <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>, hvis du har spørgsmål."</string> - <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string> + <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds lokationsdata.\n\nKontakt din it-administrator for at få mere at vide."</string> <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Din organisation har installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string> <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Din organisation har installeret et nøglecenter på din arbejdsprofil. Din sikre netværkstrafik kan overvåges eller ændres."</string> <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string> @@ -568,7 +569,7 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Din personlige profil har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string> <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"Din enhed administreres af <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string> <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> bruger <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> til at administrere din enhed."</string> - <string name="monitoring_description_do_body" msgid="7700878065625769970">"Din administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps og data, der er knyttet til denne enhed, samt enhedens placeringsoplysninger."</string> + <string name="monitoring_description_do_body" msgid="7700878065625769970">"Din administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps og data, der er knyttet til denne enhed, samt enhedens lokationsoplysninger."</string> <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string> <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"Få flere oplysninger"</string> <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Du har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites."</string> @@ -579,7 +580,7 @@ <string name="monitoring_description_network_logging" msgid="577305979174002252">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed.\n\nKontakt din administrator for at få flere oplysninger."</string> <string name="monitoring_description_vpn" msgid="1685428000684586870">"Du gav en app tilladelse til at konfigurere en VPN-forbindelse.\n\nDenne app kan overvåge din enhed og netværksaktivitet, bl.a. e-mails, apps og websites."</string> <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger.\n\nDu har også forbindelse til et VPN, som kan overvåge din netværksaktivitet."</string> - <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din placering og din skærmtid."</string> + <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din lokation og din skærmtid."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="monitoring_description_app" msgid="376868879287922929">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string> <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din private netværksaktivitet, bl.a. e-mails, apps og websites."</string> @@ -677,8 +678,8 @@ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string> <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string> - <string name="add_tile" msgid="6239678623873086686">"Tilføj et felt"</string> - <string name="broadcast_tile" msgid="5224010633596487481">"Broadcast-ikon"</string> + <string name="add_tile" msgid="6239678623873086686">"Tilføj felt"</string> + <string name="broadcast_tile" msgid="5224010633596487481">"Broadcast-felt"</string> <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>, medmindre du slår funktionen fra inden da"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="alarm_template" msgid="2234991538018805736">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrolelementer til notifikation om strøm"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Til"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Fra"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Til – ansigtsbaseret"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Med kontrolelementer til notifikationer om strøm kan du konfigurere et vigtighedsniveau fra 0 til 5 for en apps notifikationer. \n\n"<b>"Niveau 5"</b>\n"- Vis øverst på listen over notifikationer \n- Tillad afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 4"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 3"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n\n"<b>"Niveau 2"</b>\n"- Ingen afbrydelse af fuld skærm \n Se aldrig smugkig \n- Ingen lyd og vibration \n\n"<b>"Niveau 1"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n- Ingen lyd eller vibration \n- Skjul fra låseskærm og statusbjælke \n- Vis nederst på listen over notifikationer \n\n"<b>"Niveau 0"</b>\n"- Bloker alle notifikationer fra appen."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifikationer"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Du får ikke længere vist disse notifikationer"</string> @@ -910,15 +912,15 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for notifikationer med lav prioritet"</string> <string name="other" msgid="429768510980739978">"Andet"</string> - <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjern kortet"</string> - <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"føj kortet til slutningen"</string> - <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt kortet"</string> - <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj et kort"</string> + <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjern felt"</string> + <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"føj feltet til slutningen"</string> + <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt felt"</string> + <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj felt"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string> - <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til placering <xliff:g id="POSITION">%1$d</xliff:g>"</string> - <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Placering <xliff:g id="POSITION">%1$d</xliff:g>"</string> - <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kortet blev tilføjet"</string> - <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kortet blev fjernet"</string> + <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string> + <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string> + <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Feltet blev tilføjet"</string> + <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Feltet blev fjernet"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åbn Indstillinger."</string> @@ -1014,7 +1016,7 @@ <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonopkald"</string> <string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(via <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kameraet"</string> - <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string> + <string name="privacy_type_location" msgid="7991481648444066703">"lokation"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonen"</string> <string name="sensor_privacy_mode" msgid="4462866919026513692">"Deaktiver sensorer"</string> <string name="device_services" msgid="1549944177856658705">"Enhedstjenester"</string> @@ -1132,8 +1134,8 @@ <string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g> har snart fødselsdag"</string> <string name="anniversary_status" msgid="1790034157507590838">"Årsdag"</string> <string name="anniversary_status_content_description" msgid="8212171790843327442">"<xliff:g id="NAME">%1$s</xliff:g> har jubilæum i dag"</string> - <string name="location_status" msgid="1294990572202541812">"Deler placering"</string> - <string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> deler sin placering"</string> + <string name="location_status" msgid="1294990572202541812">"Deler lokation"</string> + <string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> deler sin lokation"</string> <string name="new_story_status" msgid="9012195158584846525">"Ny historie"</string> <string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> har delt en ny historie"</string> <string name="video_status" msgid="4548544654316843225">"Ser"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Brug fingeraftryk for at åbne"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Godkendelse er påkrævet. Sæt fingeren på fingeraftrykslæseren for at godkende."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Igangværende telefonopkald"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Der oprettes ikke automatisk mobildataforbindelse"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Der er ingen forbindelse"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Der er ingen andre tilgængelige netværk"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Der er ingen tilgængelige netværk"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Netværksoplysninger"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tryk på et netværk for at oprette forbindelse"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås op for at se netværk"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søger efter netværk…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Der kunne ikke oprettes forbindelse til netværket"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Ingen automatisk forbindelse til Wi-Fi i øjeblikket"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Afbryd ethernetforbindelsen for at skifte netværk"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"For at forbedre brugeroplevelsen på enheden kan apps og tjenester stadig til enhver tid scanne efter Wi‑Fi-netværk, også selvom Wi‑Fi er deaktiveret. Du kan ændre dette i indstillingerne for Wi-Fi-scanning. "<annotation id="link">"Skift indstilling"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 50fcdfb7032a..e929104cc3e6 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die dein Mikrofon verwenden dürfen."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera verwenden dürfen."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera oder dein Mikrofon verwenden dürfen."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Gerät"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Sonstiges Gerät"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Aufgeladen"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Wird aufgeladen"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Erweiterte Benachrichtigungseinstellungen"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"An"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Aus"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"An – gesichtsbasiert"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Mit den erweiterten Benachrichtigungseinstellungen kannst du für App-Benachrichtigungen eine Wichtigkeitsstufe von 0 bis 5 festlegen. \n\n"<b>"Stufe 5"</b>" \n- Auf der Benachrichtigungsleiste ganz oben anzeigen \n- Vollbildunterbrechung zulassen \n- Immer kurz einblenden \n\n"<b>"Stufe 4"</b>" \n- Keine Vollbildunterbrechung \n- Immer kurz einblenden \n\n"<b>"Stufe 3"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n\n"<b>"Stufe 2"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n\n"<b>"Stufe 1"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n- Auf Sperrbildschirm und Statusleiste verbergen \n- Auf der Benachrichtigungsleiste ganz unten anzeigen \n\n"<b>"Stufe 0"</b>" \n- Alle Benachrichtigungen der App sperren"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Benachrichtigungen"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Du erhältst diese Benachrichtigungen nicht mehr"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Mit Fingerabdruck öffnen"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentifizierung erforderlich. Tippe dazu einfach auf den Fingerabdrucksensor."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktiver Anruf"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Keine automatische Verbindung über mobile Daten"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Keine Verbindung"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Keine anderen Netzwerke verfügbar"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Keine Netzwerke verfügbar"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WLAN"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Netzwerkdetails"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tippe auf ein Netzwerk, um eine Verbindung herzustellen"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Entsperren, um Netzwerke anzuzeigen"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Netzwerke werden gesucht…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Netzwerkverbindung konnte nicht hergestellt werden"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Zurzeit wird keine automatische WLAN-Verbindung hergestellt"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Alle ansehen"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Trenne das Ethernetkabel, um das Netzwerk zu wechseln"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Zur Verbesserung der Gerätenutzung können Apps und Dienste weiter nach WLANs suchen, auch wenn die WLAN-Funktion deaktiviert ist. Dies lässt sich in den Einstellungen für die WLAN-Suche ändern. "<annotation id="link">"Ändern"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index b8d357f3ff95..5930f4c67952 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν το μικρόφωνό σας."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερά σας."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερα ή το μικρόφωνό σας."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Συσκευή"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Άλλη συσκευή"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Φορτίστηκε"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Φόρτιση"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Στοιχεία ελέγχου ειδοποίησης ισχύος"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ενεργό"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Ανενεργή"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ενεργό - Βάσει προσώπου"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Με τα στοιχεία ελέγχου ειδοποίησης ισχύος, μπορείτε να ορίσετε ένα επίπεδο βαρύτητας από 0 έως 5 για τις ειδοποιήσεις μιας εφαρμογής. \n\n"<b>"Επίπεδο 5"</b>" \n- Εμφάνιση στην κορυφή της λίστας ειδοποιήσεων \n- Να επιτρέπεται η διακοπή πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 4"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 3"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n\n"<b>"Επίπεδο 2"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n\n"<b>"Επίπεδο 1"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n- Απόκρυψη από την οθόνη κλειδώματος και τη γραμμή κατάστασης \n- Εμφάνιση στο κάτω μέρος της λίστας ειδοποιήσεων \n\n"<b>"Επίπεδο 0"</b>" \n- Αποκλεισμός όλων των ειδοποιήσεων από την εφαρμογή"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Ειδοποιήσεις"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Δεν θα βλέπετε πλέον αυτές τις ειδοποιήσεις"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Χρήση δακτυλικού αποτυπώματος για άνοιγμα"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Απαιτείται έλεγχος ταυτότητας. Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων για έλεγχο ταυτότητας."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Τηλεφωνική κλήση σε εξέλιξη"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Χωρίς αυτόματη σύνδεση δεδομένων κινητ. τηλεφωνίας"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Χωρίς σύνδεση"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Δεν υπάρχουν άλλα διαθέσιμα δίκτυα"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Δεν υπάρχουν διαθέσιμα δίκτυα"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Λεπτομέρειες δικτύου"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Πατήστε ένα δίκτυο για να συνδεθείτε"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ξεκλειδώστε για προβολή δικτύων"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Αναζήτηση δικτύων…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Αποτυχία σύνδεσης στο δίκτυο"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Δεν θα γίνεται προς το παρόν αυτόματη σύνδεση Wi-Fi."</string> + <string name="see_all_networks" msgid="3773666844913168122">"Εμφάνιση όλων"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Για εναλλαγή δικτύων, αποσυνδέστε το ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Για βελτίωση της εμπειρίας στη συσκευή, οι εφαρμογές και οι υπηρεσίες μπορούν ακόμα να εκτελούν σάρωση για δίκτυα Wi‑Fi ανά πάσα στιγμή, ακόμα και όταν το Wi‑Fi είναι απενεργοποιημένο. Μπορείτε να αλλάξετε αυτήν τη ρύθμιση στις ρυθμίσεις της Σάρωσης Wi‑Fi. "<annotation id="link">"Αλλαγή"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index d69a95bba878..96b50bd08e74 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"You won\'t see these notifications anymore"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string> + <string name="see_all_networks" msgid="3773666844913168122">"See all"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 3666069ee54b..5361b9fd4082 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"You won\'t see these notifications anymore"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string> + <string name="see_all_networks" msgid="3773666844913168122">"See all"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index d69a95bba878..96b50bd08e74 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"You won\'t see these notifications anymore"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string> + <string name="see_all_networks" msgid="3773666844913168122">"See all"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index d69a95bba878..96b50bd08e74 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"You won\'t see these notifications anymore"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string> + <string name="see_all_networks" msgid="3773666844913168122">"See all"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 030c5884d3e3..78d60f605934 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Face-based"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"You won\'t see these notifications anymore"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string> + <string name="see_all_networks" msgid="3773666844913168122">"See all"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation>""</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index bb43d81596be..8f6f93a0af68 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar el micrófono."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción permite que todas las aplicaciones y servicios que tengan permiso puedan usar la cámara o el micrófono."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de activación de notificaciones"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activado"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desactivado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activa - En función del rostro"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Con los controles de activación de notificaciones, puedes establecer un nivel de importancia para las notificaciones de una app. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones. \n- Permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 4"</b>" \n- No permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 3"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n\n"<b>"Nivel 2"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n\n"<b>"Nivel 1"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n- Ocultar de la pantalla bloqueada y la barra de estado. \n- Mostrar al final de la lista de notificaciones. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la app."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificaciones"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Ya no verás estas notificaciones"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella dactilar para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"No se conectarán automáticamente los datos móviles"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No hay redes disponibles"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalles de la red"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Presiona una red para conectarte a ella"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloquea para ver las redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Se produjo un error al establecer conexión con la red"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por ahora, el Wi-Fi no se conectará automáticamente"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de red, desconéctate de Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las apps y los servicios pueden seguir buscando redes Wi-Fi en cualquier momento, incluso cuando la conexión Wi-Fi esté desactivada. Puedes cambiar este parámetro en la configuración de búsqueda de Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml index 5634f790f234..4f738c50c8a3 100644 --- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml @@ -58,8 +58,8 @@ </string-array> <string-array name="tile_states_flashlight"> <item msgid="3465257127433353857">"No disponible"</item> - <item msgid="5044688398303285224">"Desactivado"</item> - <item msgid="8527389108867454098">"Activado"</item> + <item msgid="5044688398303285224">"Desactivada"</item> + <item msgid="8527389108867454098">"Activada"</item> </string-array> <string-array name="tile_states_rotation"> <item msgid="4578491772376121579">"No disponible"</item> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 820c708e4fe1..30a6d09ea4d3 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> @@ -123,8 +124,8 @@ <string name="screenrecord_permission_error" msgid="7856841237023137686">"No se han podido obtener los permisos"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"No se ha podido empezar a grabar la pantalla"</string> <string name="usb_preference_title" msgid="1439924437558480718">"Opciones de transferencia de archivos por USB"</string> - <string name="use_mtp_button_title" msgid="5036082897886518086">"Activar como reproductor de medios (MTP)"</string> - <string name="use_ptp_button_title" msgid="7676427598943446826">"Activar como cámara (PTP)"</string> + <string name="use_mtp_button_title" msgid="5036082897886518086">"Montar como reproductor de medios (MTP)"</string> + <string name="use_ptp_button_title" msgid="7676427598943446826">"Montar como cámara (PTP)"</string> <string name="installer_cd_button_title" msgid="5499998592841984743">"Instalar Android File Transfer para Mac"</string> <string name="accessibility_back" msgid="6530104400086152611">"Atrás"</string> <string name="accessibility_home" msgid="5430449841237966217">"Inicio"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu micrófono."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara o tu micrófono."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string> @@ -662,8 +663,8 @@ <string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string> <string name="overview" msgid="3522318590458536816">"Aplicaciones recientes"</string> <string name="demo_mode" msgid="263484519766901593">"Modo de demostración de UI del sistema"</string> - <string name="enable_demo_mode" msgid="3180345364745966431">"Habilitar modo de demostración"</string> - <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demostración"</string> + <string name="enable_demo_mode" msgid="3180345364745966431">"Habilitar modo demo"</string> + <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo demo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> @@ -677,12 +678,12 @@ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string> - <string name="add_tile" msgid="6239678623873086686">"Añadir icono"</string> - <string name="broadcast_tile" msgid="5224010633596487481">"Icono de emisión"</string> + <string name="add_tile" msgid="6239678623873086686">"Añadir recuadro"</string> + <string name="broadcast_tile" msgid="5224010633596487481">"Recuadro de emisión"</string> <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>) a menos que desactives esta opción antes"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string> <string name="alarm_template" msgid="2234991538018805736">"a las <xliff:g id="WHEN">%1$s</xliff:g>"</string> - <string name="alarm_template_far" msgid="3561752195856839456">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string> + <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Ajustes rápidos, <xliff:g id="TITLE">%s</xliff:g>."</string> <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Compartir Internet"</string> <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de energía de las notificaciones"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activado"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desactivado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activado: basado en caras"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Los controles de energía de las notificaciones permiten establecer un nivel de importancia de 0 a 5 para las notificaciones de las aplicaciones. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones \n- Permitir interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 4"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 3"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n\n"<b>"Nivel 2"</b>" \n- Evitar interrumpir en el modo de pantalla completa\n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n\n"<b>"Nivel 1"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n- Ocultar de la pantalla de bloqueo y de la barra de estado \n- Mostrar en la parte inferior de la lista de notificaciones \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la aplicación"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificaciones"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"No volverás a ver estas notificaciones"</string> @@ -892,10 +894,10 @@ <string name="right_keycode" msgid="2480715509844798438">"Código de teclado a la derecha"</string> <string name="left_icon" msgid="5036278531966897006">"Icono a la izquierda"</string> <string name="right_icon" msgid="1103955040645237425">"Icono a la derecha"</string> - <string name="drag_to_add_tiles" msgid="8933270127508303672">"Pulsa y arrastra para añadir funciones"</string> - <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Mantén pulsado un icono y arrástralo para reubicarlo"</string> + <string name="drag_to_add_tiles" msgid="8933270127508303672">"Pulsa y arrastra para añadir recuadros"</string> + <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Mantén pulsado un recuadro y arrástralo para reubicarlo"</string> <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arrastra aquí para quitar una función"</string> - <string name="drag_to_remove_disabled" msgid="933046987838658850">"Necesitas al menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> iconos"</string> + <string name="drag_to_remove_disabled" msgid="933046987838658850">"Necesitas al menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> recuadros"</string> <string name="qs_edit" msgid="5583565172803472437">"Editar"</string> <string name="tuner_time" msgid="2450785840990529997">"Hora"</string> <string-array name="clock_options"> @@ -910,15 +912,15 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconos de notificaciones con prioridad baja"</string> <string name="other" msgid="429768510980739978">"Otros"</string> - <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"quitar icono"</string> - <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"añadir icono al final"</string> - <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover icono"</string> - <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Añadir icono"</string> + <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"quitar recuadro"</string> + <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"añadir recuadro al final"</string> + <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover recuadro"</string> + <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Añadir recuadro"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Añadir a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string> - <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tarjeta añadida"</string> - <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tarjeta quitada"</string> + <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Recuadro añadido"</string> + <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Recuadro quitado"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de ajustes rápidos."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir ajustes."</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticación obligatoria. Toca el sensor de huellas digitales para autenticarte."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"No hay redes disponibles"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalles de la red"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca una red para conectarte"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloquea para ver redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"No se ha podido conectar a la red"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por ahora no se conectará automáticamente a redes Wi-Fi"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de red, desconecta el cable Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las aplicaciones y los servicios podrán buscar redes Wi-Fi en cualquier momento, aunque la conexión Wi-Fi esté desactivada. Puedes cambiarlo en los ajustes de búsqueda de redes Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 6cd609fa6151..fb2aa1ff5905 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud mikrofoni kasutada."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat kasutada."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat või mikrofoni kasutada."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Seade"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu seade"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laetud"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laadimine"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Toite märguannete juhtnupud"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Sees"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Väljas"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Sees – näopõhine"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Toite märguannete juhtnuppudega saate määrata rakenduse märguannete tähtsuse taseme vahemikus 0–5. \n\n"<b>"5. tase"</b>" \n- Kuva märguannete loendi ülaosas\n- Luba täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"4. tase"</b>" \n- Keela täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"3. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n\n"<b>"2. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n\n"<b>"1. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n- Peida lukustuskuval ja olekuribal \n- Kuva märguannete loendi allosas \n\n"<b>"Tase 0"</b>" \n- Blokeeri kõik rakenduse märguanded"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Märguanded"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Te ei näe enam neid märguandeid"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Kasutage avamiseks sõrmejälge"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vajalik on autentimine. Puudutage autentimiseks sõrmejäljeandurit."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Käimasolev telefonikõne"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilset andmesideühendust ei looda automaatselt"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ühendus puudub"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ühtegi muud võrku pole saadaval"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Ühtegi võrku pole saadaval"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Võrgu üksikasjad"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Puudutage ühendamiseks võrku"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Võrkude vaatamiseks avage"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Võrkude otsimine …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Võrguühenduse loomine ebaõnnestus"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi-ühendust ei looda praegu automaatselt"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Kuva kõik"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Võrkude vahetamiseks katkestage Etherneti-ühendus"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Seadme kasutuskogemuse parandamiseks võivad rakendused ja teenused siiski alati otsida WiFi-võrke isegi siis, kui WiFi on väljas. Seda saab muuta WiFi-skannimise seadetes. "<annotation id="link">"Muuda"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index b6162a830186..27418388ae8b 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> @@ -304,7 +305,7 @@ <string name="data_usage_disabled_dialog_4g_title" msgid="1490779000057752281">"4G datuen erabilera pausatu da"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"Datu-konexioa pausatu egin da"</string> <string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Datuen erabilera pausatu da"</string> - <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Iritsi zara ezarri zenuen datu-mugara. Datu-konexioa erabiltzeari utzi diozu.\n\nDatu-konexioa erabiltzeari berrekiten badiozu, datuen erabileragatiko gastuak izango dituzu."</string> + <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Iritsi zara ezarri zenuen datu-mugara. Datu-konexioa erabiltzeari utzi diozu.\n\nDatu-konexioa erabiltzeari berrekiten badiozu, baliteke zerbait ordaindu behar izatea datuak erabiltzeagatik."</string> <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Jarraitu erabiltzen"</string> <string name="gps_notification_searching_text" msgid="231304732649348313">"GPS seinalearen bila"</string> <string name="gps_notification_found_text" msgid="3145873880174658526">"Kokapena GPS bidez ezarri da"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera edo mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dituzte."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Gailua"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Beste gailu bat"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kargatuta"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kargatzen"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerak"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aktibatuta"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desaktibatuta"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktibatuta: aurpegian oinarrituta"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerekin, 0 eta 5 bitarteko garrantzi-mailetan sailka ditzakezu aplikazioen jakinarazpenak. \n\n"<b>"5. maila"</b>" \n- Erakutsi jakinarazpenen zerrendaren goialdean. \n- Baimendu etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"4. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"3. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n\n"<b>"2. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n\n"<b>"1. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n- Ezkutatu pantaila blokeatutik eta egoera-barratik. \n- Erakutsi jakinarazpenen zerrendaren behealdean. \n\n"<b>"0. maila"</b>" \n- Blokeatu aplikazioaren jakinarazpen guztiak."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Jakinarazpenak"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Aurrerantzean ez duzu ikusiko horrelako jakinarazpenik"</string> @@ -844,7 +846,7 @@ <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Arakatzailea"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktuak"</string> <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Posta"</string> - <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS mezuak"</string> + <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string> <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string> @@ -998,7 +1000,7 @@ <string name="slice_permission_deny" msgid="6870256451658176895">"Ukatu"</string> <string name="auto_saver_title" msgid="6873691178754086596">"Sakatu bateria-aurrezlea noiz aktibatu programatzeko"</string> <string name="auto_saver_text" msgid="3214960308353838764">"Aktibatu aurrezlea bateria agortzeko arriskua dagoenean"</string> - <string name="no_auto_saver_action" msgid="7467924389609773835">"Ez"</string> + <string name="no_auto_saver_action" msgid="7467924389609773835">"Ez, eskerrik asko"</string> <string name="auto_saver_enabled_title" msgid="4294726198280286333">"Bateria-aurrezlea aktibatu da"</string> <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Bateria-aurrezlea automatikoki aktibatuko da bateriaren %% <xliff:g id="PERCENTAGE">%d</xliff:g> gelditzen denean."</string> <string name="open_saver_setting_action" msgid="2111461909782935190">"Ezarpenak"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Erabili hatz-marka irekitzeko"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentifikazioa behar da. Autentifikatzeko, ukitu hatz-marken sentsorea."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefono-dei bat abian da"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> (<xliff:g id="NETWORKMODE">%2$s</xliff:g>)"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Ez da automatikoki aktibatuko datu-konexioa"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Konexiorik gabe"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ez dago beste sare erabilgarririk"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Ez dago sare erabilgarririk"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wifia"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Sarearen xehetasunak"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Sakatu sare bat hartara konektatzeko"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sareak ikusteko, desblokeatu pantaila"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Sareak bilatzen…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ezin izan da konektatu sarera"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Oraingoz ez da automatikoki konektatuko wifira"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ikusi guztiak"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Sarea aldatzeko, deskonektatu Ethernet-a"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Gailuaren funtzionamendua hobetzeko, aplikazioek eta zerbitzuek wifi-sareak bilatzen jarraituko dute, baita wifi-konexioa desaktibatuta dagoenean ere. Aukera hori aldatzeko, joan wifi-sareen bilaketaren ezarpenetara. "<annotation id="link">"Aldatu"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index d1ddd8c042f4..84ab778d15c7 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"با این کار دسترسی برای همه برنامهها و سرویسهایی که مجاز هستند از میکروفونتان استفاده کنند لغو انسداد میشود."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"با این کار دسترسی برای همه برنامهها و سرویسهایی که مجاز هستند از دوربینتان استفاده کنند لغو انسداد میشود."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"با این کار دسترسی برای همه برنامهها و دستگاههایی که مجاز هستند از دوربین یا میکروفونتان استفاده کنند لغو انسداد میشود."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"دستگاه دیگر"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"شارژ کامل شد"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"در حال شارژ شدن"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"کنترلهای قدرتمند اعلان"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"روشن"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"خاموش"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"روشن - براساس چهره"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"با کنترلهای قدرتمند اعلان میتوانید سطح اهمیت اعلانهای هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلانها نشان داده میشود \n- وقفه برای نمایش تمامصفحه مجاز است \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا و لرزش ایجاد نمیکند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا یا لرزش ایجاد نمیکند \n- در صفحه قفل و نوار وضعیت پنهان است \n- در پایین فهرست اعلانها نشان داده میشود \n\n"<b>"سطح ۰"</b>" \n- همه اعلانهای این برنامه مسدود است"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"اعلانها"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"دیگر این اعلانها را نخواهید دید"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"از اثر انگشت برای باز کردن قفل استفاده کنید"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالتسنجی لازم است. برای اصالتسنجی، حسگر اثر انگشت را لمس کنید."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"داده تلفن همراه بهطور خودکار متصل نخواهد شد"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"اتصال برقرار نیست"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"شبکه دیگری وجود ندارد"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"شبکهای در دسترس نیست"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"جزئیات شبکه"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"برای اتصال به شبکه روی آن ضربه بزنید"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"برای مشاهده شبکهها، قفل صفحه را باز کنید"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"درحال جستجوی شبکه…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"اتصال به شبکه برقرار نشد"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"فعلاً Wi-Fi بهطور خودکار متصل نمیشود"</string> + <string name="see_all_networks" msgid="3773666844913168122">"مشاهده همه"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"برای تغییر شبکه، اترنت را قطع کنید"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"برای بهبود تجربه استفاده از دستگاه، برنامهها و سرویسها همچنان میتوانند در هر زمانی شبکههای Wi-Fi را اسکن کنند؛ حتی وقتی که Wi-Fi خاموش باشد. میتوانید این مورد را در تنظیمات اسکن کردن Wi‑Fi تغییر دهید. "<annotation id="link">"تغییر"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 652acf7ddd89..25efe59ef7aa 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää mikrofoniasi."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa eston kaikkien sellaisten sovellusten ja palveluiden osalta, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu laite"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Ladattu"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ladataan"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ilmoitusten tehohallinta"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Päällä"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Pois päältä"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Päällä – kasvojen perusteella"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Ilmoitusten tehohallinnan avulla voit määrittää sovelluksen ilmoituksille tärkeystason väliltä 0–5. \n\n"<b>"Taso 5"</b>" \n– Ilmoitukset näytetään ilmoitusluettelon yläosassa \n– Näkyminen koko näytön tilassa sallitaan \n– Ilmoitukset kurkistavat aina näytölle\n\n"<b>"Taso 4"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ilmoitukset kurkistavat aina näytölle \n\n"<b>"Taso 3"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n\n"<b>"Taso 2"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n\n"<b>"Taso 1"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n– Ilmoitukset piilotetaan lukitusnäytöltä ja tilapalkista \n– Ilmoitukset näytetään ilmoitusluettelon alaosassa \n\n"<b>"Taso 0"</b>" \n– Kaikki sovelluksen ilmoitukset estetään"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Ilmoitukset"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Et näe näitä ilmoituksia enää"</string> @@ -860,7 +862,7 @@ <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Kuulokemikrofoni liitetty"</string> <string name="data_saver" msgid="3484013368530820763">"Data Saver"</string> <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Data Saver on käytössä."</string> - <string name="accessibility_data_saver_off" msgid="58339669022107171">"Data Saver on pois käytöstä."</string> + <string name="accessibility_data_saver_off" msgid="58339669022107171">"Data Saver on pois päältä."</string> <string name="switch_bar_on" msgid="1770868129120096114">"Päällä"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Pois päältä"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ei käytettävissä"</string> @@ -975,9 +977,9 @@ <string name="mobile_data" msgid="4564407557775397216">"Mobiilitiedonsiirto"</string> <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string> - <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois käytöstä"</string> + <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois päältä"</string> <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth ei ole käytössä"</string> - <string name="dnd_is_off" msgid="3185706903793094463">"Älä häiritse ‑tila on pois käytöstä"</string> + <string name="dnd_is_off" msgid="3185706903793094463">"Älä häiritse ‑tila on pois päältä"</string> <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Automaattinen sääntö otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>)."</string> <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"Sovellus otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>)."</string> <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"Automaattinen sääntö tai sovellus otti käyttöön Älä häiritse ‑tilan."</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Avaa sormenjäljellä"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Todennus vaaditaan. Todenna koskettamalla sormenjälkitunnistinta."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Puhelu käynnissä"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilidata ei yhdisty automaattisesti"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ei yhteyttä"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ei muita verkkoja käytettävissä"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Ei verkkoja käytettävissä"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Verkon tiedot"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Muodosta yhteys napauttamalla verkkoa"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Avaa lukitus nähdäksesi verkot"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Etsitään verkkoja…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Yhteyden muodostaminen verkkoon epäonnistui"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ei toistaiseksi yhdistä automaattisesti"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Näytä kaikki"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Irrota Ethernet-johto, jos haluat vaihtaa verkkoa"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Laitteen käyttökokemuksen parantamiseksi sovellukset ja palvelut voivat hakea Wi-Fi-verkkoja myös silloin, kun Wi-Fi on pois päältä. Voit muuttaa asetusta Wi-Fi-haun asetuksissa. "<annotation id="link">"Muuta"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 1ec1f9190a22..b885249a4e91 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/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">"Fonctionnalité Smart Lock désactivée"</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 capture écran…"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser le microphone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès pour toutes les applications et pour tous les services autorisés à utiliser l\'appareil photo."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser l\'appareil photo ou le microphone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargée"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charge en cours..."</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Réglages avancés des notifications"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activé"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Désactivé"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activé : en fonction du visage"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Avec les réglages avancés des notifications, vous pouvez définir un degré d\'importance de 0 à 5 pour les notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher dans le haut de la liste des notifications \n- Autoriser les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 4"</b>" \n- Empêcher les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 3"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n\n"<b>"Niveau 2"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n\n"<b>"Niveau 1"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n- Masquer de l\'écran de verrouillage et de la barre d\'état status bar \n- Afficher dans le bas de la liste des notifications \n\n"<b>"Level 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Vous ne verrez plus ces notifications"</string> @@ -1008,7 +1010,7 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string> - <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En cours d\'utilisation par <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En cours d\'utilisation par : <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Récemment utilisé par <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(travail)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Appel téléphonique"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Servez-vous de votre empreinte digitale pour ouvrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Touchez le capteur d\'empreintes digitales pour vous authentifier."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours…"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Aucune connexion auto. des données cellulaires"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau n\'est accessible"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Aucun réseau n\'est accessible"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Détails du réseau"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Touchez un réseau pour vous y connecter"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Déverrouillez l\'écran pour afficher les réseaux Wi-Fi"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Recherche de réseaux en cours…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Échec de la connexion au réseau"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connexion automatique au Wi-Fi impossible pour le moment"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pour changer de réseau, débranchez le câble Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pour améliorer l\'expérience de l\'appareil, les applications et les services peuvent quand même rechercher des réseaux Wi-Fi en tout temps, même lorsque le Wi-Fi est désactivé. Vous pouvez modifier vos préférences dans les paramètres de recherche de réseaux Wi-Fi. "<annotation id="link">"Modifier"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 6a08d8716677..ce6cd9591e93 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre micro."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'aperçu"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargé"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"En charge"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Commandes de gestion des notifications"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activé"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Désactivé"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Active - En fonction du visage"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Grâce aux commandes de gestion des notifications, vous pouvez définir le niveau d\'importance (compris entre 0 et 5) des notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher en haut de la liste des notifications \n- Autoriser l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 4"</b>" \n- Empêcher l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 3"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n\n"<b>"Niveau 2"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n\n"<b>"Niveau 1"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n- Masquer les notifications dans l\'écran de verrouillage et la barre d\'état \n- Afficher au bas de la liste des notifications \n\n"<b>"Niveau 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifications"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Vous ne recevrez plus ces notifications"</string> @@ -894,7 +896,7 @@ <string name="right_icon" msgid="1103955040645237425">"Icône droite"</string> <string name="drag_to_add_tiles" msgid="8933270127508303672">"Faites glisser les blocs pour les ajouter"</string> <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Faites glisser les blocs pour les réorganiser"</string> - <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Faites glisser les icônes ici pour les supprimer."</string> + <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Faites glisser les blocs ici pour les supprimer"</string> <string name="drag_to_remove_disabled" msgid="933046987838658850">"Au minimum <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tuiles sont nécessaires"</string> <string name="qs_edit" msgid="5583565172803472437">"Modifier"</string> <string name="tuner_time" msgid="2450785840990529997">"Heure"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilisez votre empreinte pour ouvrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Appuyez sur le lecteur d\'empreintes digitales pour vous authentifier."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Pas de connexion automatique des données mobiles"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau disponible"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Aucun réseau disponible"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Détails du réseau"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Appuyez sur un réseau pour vous connecter"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Déverrouiller pour afficher les réseaux"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Recherche de réseaux…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Échec de la connexion au réseau"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connexion automatique au Wi-Fi désactivée pour le moment"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pour changer de réseau, déconnectez l\'Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pour améliorer l\'expérience sur l\'appareil, les applis et les services peuvent continuer de rechercher les réseaux Wi-Fi, même si le Wi-Fi est désactivé. Vous pouvez modifier cela dans les paramètres de recherche Wi-Fi. "<annotation id="link">"Modifier"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 15678e4cc907..9da7d6fbac0a 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Con esta acción desbloquearase o acceso ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalo."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Con esta acción desbloquearase o acceso á cámara para todas as aplicacións e servizos que teñan permiso para utilizala."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Con esta acción desbloquearase o acceso á cámara ou ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalos."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargado"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controis de notificacións mellorados"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activado"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desactivado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activada: baseada na cara"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Cos controis de notificacións mellorados, podes asignarlles un nivel de importancia comprendido entre 0 e 5 ás notificacións dunha aplicación determinada. \n\n"<b>"Nivel 5"</b>" \n- Mostrar na parte superior da lista de notificacións. \n- Permitir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 4"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 3"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n\n"<b>"Nivel 2"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n\n"<b>"Nivel 1"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n- Ocultar na pantalla de bloqueo e na barra de estado. \n- Mostrar na parte inferior da lista de notificacións. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas as notificacións da aplicación."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificacións"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Deixarás de ver estas notificacións"</string> @@ -1008,7 +1010,7 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> - <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Opción en uso por <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En uso por: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Opción usada recentemente por <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(traballo)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada de teléfono"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa a impresión dixital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Requírese autenticación. Para autenticarte, toca o sensor de impresión dixital."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica en curso"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Os datos móbiles non se conectarán automaticamente"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sen conexión"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Non hai outras redes dispoñibles"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Non hai redes dispoñibles"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalles da rede"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca unha rede para conectarte a ela"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloquea a pantalla para ver as redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Produciuse un erro ao conectarse á rede"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"De momento, a wifi non se conectará automaticamente"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de rede, desconecta a Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mellorar a experiencia que ofrece o dispositivo, as aplicacións e os servizos poden seguir buscando redes wifi en calquera momento, aínda que esta conexión estea desactivada. Podes cambiar esta opción na configuración da función Busca de redes wifi. "<annotation id="link">"Cambiar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 9255827aa64e..79bb64f0599b 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/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> @@ -133,7 +134,7 @@ <string name="accessibility_rotate_button" msgid="1238584767612362586">"સ્ક્રીન ફેરવો"</string> <string name="accessibility_recent" msgid="901641734769533575">"ઝલક"</string> <string name="accessibility_search_light" msgid="524741790416076988">"શોધ"</string> - <string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરો"</string> + <string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરા"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"વૉલેટ"</string> @@ -146,7 +147,7 @@ <string name="accessibility_manage_notification" msgid="582215815790143983">"નોટિફિકેશનને મેનેજ કરો"</string> <string name="phone_label" msgid="5715229948920451352">"ફોન ખોલો"</string> <string name="voice_assist_label" msgid="3725967093735929020">"વૉઇસ સહાય ખોલો"</string> - <string name="camera_label" msgid="8253821920931143699">"કૅમેરો ખોલો"</string> + <string name="camera_label" msgid="8253821920931143699">"કૅમેરા ખોલો"</string> <string name="cancel" msgid="1089011503403416730">"રદ કરો"</string> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"કન્ફર્મ કરો"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ફરી પ્રયાસ કરો"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"આ તમારા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"આ તમારા કૅમેરાનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"આ તમારા કૅમેરા અથવા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ડિવાઇસ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"અન્ય ડિવાઇસ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ચાર્જ થઈ ગયું"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ચાર્જ થઈ રહ્યું છે"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"પાવર સૂચના નિયંત્રણો"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ચાલુ"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"બંધ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ચાલુ છે - ચહેરા આધારિત રોટેશન"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"પાવર સૂચના નિયંત્રણો સાથે, તમે ઍપની સૂચનાઓ માટે 0 થી 5 સુધીના મહત્વના સ્તરને સેટ કરી શકો છો. \n\n"<b>"સ્તર 5"</b>" \n- સૂચના સૂચિની ટોચ પર બતાવો \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 4"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 3"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n\n"<b>"સ્તર 2"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n\n"<b>"સ્તર 1"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n- લૉક સ્ક્રીન અને સ્ટેટસ બારથી છુપાવો \n- સૂચના સૂચિના તળિયા પર બતાવો \n\n"<b>"સ્તર 0"</b>" \n- ઍપની તમામ સૂચનાઓને બ્લૉક કરો"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"નોટિફિકેશન"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"તમને હવેથી આ નોટિફિકેશન દેખાશે નહીં"</string> @@ -982,7 +984,7 @@ <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"ખલેલ પાડશો નહીં એક ઍપ્લિકેશન દ્વારા ચાલુ કરાયું હતું (<xliff:g id="ID_1">%s</xliff:g>)."</string> <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"ખલેલ પાડશો નહીં એક સ્વચાલિત નિયમ અથવા ઍપ્લિકેશન દ્વારા ચાલુ કરાયું હતું."</string> <string name="qs_dnd_until" msgid="7844269319043747955">"<xliff:g id="ID_1">%s</xliff:g> સુધી"</string> - <string name="qs_dnd_keep" msgid="3829697305432866434">"Keep"</string> + <string name="qs_dnd_keep" msgid="3829697305432866434">"રાખો"</string> <string name="qs_dnd_replace" msgid="7712119051407052689">"બદલો"</string> <string name="running_foreground_services_title" msgid="5137313173431186685">"પૃષ્ઠભૂમિમાં ચાલી રહેલ ઍપ્લિકેશનો"</string> <string name="running_foreground_services_msg" msgid="3009459259222695385">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ખોલવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"પ્રમાણીકરણ આવશ્યક છે. પ્રમાણિત કરવા માટે ફિંગરપ્રિન્ટ સેન્સરને ટચ કરો."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ફોન કૉલ ચાલુ છે"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"મોબાઇલ ડેટા ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"કોઈ કનેક્શન નથી"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"બીજાં કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"વાઇ-ફાઇ"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"નેટવર્કની વિગતો"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"કનેક્ટ કરવા માટે નેટવર્ક પર ટૅપ કરો"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"વાઇ-ફાઇ નેટવર્ક જોવા માટે અનલૉક કરો"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"નેટવર્ક શોધી રહ્યાં છીએ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"નેટવર્ક સાથે કનેક્ટ કરવામાં નિષ્ફળ થયાં"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"હમણાં પૂરતું વાઇ-ફાઇ ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string> + <string name="see_all_networks" msgid="3773666844913168122">"બધા જુઓ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"બીજા નેટવર્ક પર જવા માટે, ઇથરનેટ ડિસ્કનેક્ટ કરો"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ડિવાઇસના અનુભવને બહેતર બનાવવા માટે, વાઇ-ફાઇ બંધ હોય ત્યારે પણ ઍપ અને સેવાઓ કોઈપણ સમયે વાઇ-ફાઇ નેટવર્ક સ્કૅન કરી શકે છે. તમે વાઇ-ફાઇ સ્કૅનિંગના સેટિંગમાં જઈને આને બદલી શકો છો. "<annotation id="link">"બદલો"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-h800dp/dimens.xml b/packages/SystemUI/res/values-h800dp/dimens.xml index 19ec8cee18a8..f057603e2cd0 100644 --- a/packages/SystemUI/res/values-h800dp/dimens.xml +++ b/packages/SystemUI/res/values-h800dp/dimens.xml @@ -16,7 +16,7 @@ <resources> <!-- Minimum margin between clock and top of screen or ambient indication --> - <dimen name="keyguard_clock_top_margin">76dp</dimen> + <dimen name="keyguard_clock_top_margin">38dp</dimen> <!-- Large clock maximum font size (dp is intentional, to prevent any further scaling) --> <dimen name="large_clock_text_size">200dp</dimen> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 1ebb517dc316..429bbccaf797 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ऐसा करने से, माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें माइक्रोफ़ोन का इस्तेमाल करने की अनुमति दी गई है."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरा या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें ये इस्तेमाल करने की अनुमति है."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"अन्य डिवाइस"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज हो गई है"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हो रही है"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"पावर सूचना नियंत्रण"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"चालू"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"बंद"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"चालू है - चेहरे की गतिविधि के हिसाब से कैमरे को घुमाने की सुविधा"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"सूचनाएं"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"अब आपको ये सूचनाएं दिखाई नहीं देंगी"</string> @@ -847,7 +849,7 @@ <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"मैसेज (एसएमएस) करें"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"संगीत"</string> <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string> - <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"कैलेंडर"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string> <string name="tuner_full_zen_title" msgid="5120366354224404511">"वॉल्यूम नियंत्रणों के साथ दिखाएं"</string> <string name="volume_and_do_not_disturb" msgid="502044092739382832">"परेशान न करें"</string> <string name="volume_dnd_silent" msgid="4154597281458298093">"वॉल्यूम बटन का शॉर्टकट"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"खोलने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि करना ज़रूरी है. पुष्टि करने के लिए, फ़िंगरप्रिंट सेंसर को छुएं."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फ़ोन कॉल चल रहा है"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा अपने-आप कनेक्ट नहीं होगा"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"इंटरनेट कनेक्शन नहीं है"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"कोई दूसरा नेटवर्क उपलब्ध नहीं है"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"कोई नेटवर्क उपलब्ध नहीं है"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"वाई-फ़ाई"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्क की जानकारी"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"इंटरनेट से कनेक्ट करने के लिए, किसी नेटवर्क पर टैप करें"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"वाई-फ़ाई नेटवर्क देखने के लिए, स्क्रीन को अनलॉक करें"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्क खोजे जा रहे हैं…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्क से कनेक्ट नहीं किया जा सका"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"फ़िलहाल, वाई-फ़ाई अपने-आप कनेक्ट नहीं होगा"</string> + <string name="see_all_networks" msgid="3773666844913168122">"सभी देखें"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क बदलने के लिए, पहले ईथरनेट को डिसकनेक्ट करें"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिवाइस इस्तेमाल करने के अनुभव काे बेहतर बनाने के लिए, ऐप्लिकेशन और सेवाओं की मदद से, किसी भी समय वाई-फ़ाई नेटवर्क स्कैन किए जा सकते हैं. ऐसा वाई-फ़ाई बंद होने पर भी किया जा सकता है. वाई-फ़ाई स्कैनिंग की सेटिंग में जाकर, इसे बदला जा सकता है. "<annotation id="link">"बदलें"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 9ec657d8d19d..789bdf6c7a7f 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg mikrofona."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata ili mikrofona."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Ostali uređaji"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Napredne kontrole obavijesti"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Uključeno"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Isključeno"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na temelju lica"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Napredne kontrole obavijesti omogućuju vam da postavite razinu važnosti za obavijesti aplikacije od 0 do 5. \n\n"<b>"Razina 5"</b>" \n– prikaži na vrhu popisa obavijesti \n– dopusti prekide prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 4"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 3"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled\n\n"<b>"Razina 2"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n\n"<b>"Razina 1"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n– ne prikazuj na zaključanom zaslonu i traci statusa \n– prikaži na dnu popisa obavijesti \n\n"<b>"Razina 0"</b>" \n– blokiraj sve obavijesti aplikacije"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Obavijesti"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Te vam se obavijesti više neće prikazivati"</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor otiska prsta da biste se autentificirali."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u tijeku"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna veza neće se automatski uspostaviti"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Pojedinosti o mreži"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da biste se povezali"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte za prikaz mreža"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traženje mreža…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje s mrežom nije uspjelo"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi se zasad neće automatski povezivati"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da biste se prebacili na drugu mrežu, odspojite Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Da bi se poboljšao doživljaj uređaja, aplikacije i usluge i dalje mogu tražiti Wi-Fi mreže u bilo kojem trenutku, čak i kada je Wi-Fi isključen. To možete promijeniti u postavkama traženja Wi-Fija. "<annotation id="link">"Promijeni"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index d9d8148938de..26c34f80117f 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> @@ -353,7 +354,7 @@ <string name="quick_settings_ime_label" msgid="3351174938144332051">"Beviteli módszer"</string> <string name="quick_settings_location_label" msgid="2621868789013389163">"Tartózkodási hely"</string> <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Hely kikapcsolva"</string> - <string name="quick_settings_camera_label" msgid="5612076679385269339">"Kameraelérés"</string> + <string name="quick_settings_camera_label" msgid="5612076679385269339">"Hozzáférés a kamerához"</string> <string name="quick_settings_mic_label" msgid="8392773746295266375">"Mikrofonelérés"</string> <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Rendelkezésre áll"</string> <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Letiltva"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a mikrofon használatát."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera használatát."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera vagy a mikrofon használatát."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Más eszköz"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Feltöltve"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Töltés"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Teljes körű értesítésvezérlők"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Bekapcsolva"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Kikapcsolva"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Be: Arcalapú"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Az értesítési beállítások révén 0-tól 5-ig állíthatja be a fontossági szintet az alkalmazás értesítéseinél. \n\n"<b>"5. szint"</b>" \n– Megjelenítés az értesítési lista tetején \n– Teljes képernyő megszakításának engedélyezése \n– Mindig felugrik \n\n"<b>"4. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Mindig felugrik \n\n"<b>"3. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n\n"<b>"2. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés és rezgés \n\n"<b>"1. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés vagy rezgés \n– Elrejtés a lezárási képernyőről és az állapotsávról \n– Megjelenítés az értesítési lista alján \n\n"<b>"0. szint"</b>" \n– Az alkalmazás összes értesítésének letiltása"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Értesítések"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Többé nem jelennek meg ezek az értesítések"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ujjlenyomat használata a megnyitáshoz"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Hitelesítés szükséges. Érintse meg az ujjlenyomat-érzékelőt a hitelesítéshez."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Folyamatban lévő telefonhívás"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g>/<xliff:g id="STATE">%1$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nincs automatikus mobiladat-kapcsolat"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nincs kapcsolat"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nincs több rendelkezésre álló hálózat"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nincs rendelkezésre álló hálózat"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Hálózati információk"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"A kapcsolódáshoz koppintson a kívánt hálózatra"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Zárolás feloldása a hálózatok megtekintéséhez"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Hálózatok keresése…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nem sikerült hálózathoz csatlakozni."</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A Wi-Fi-re történő csatlakozás jelenleg nem automatikus"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Megtekintés"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Hálózatváltáshoz válassza le az ethernetet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Az eszközhasználati élmény javítása érdekében az alkalmazások és a szolgáltatások továbbra is bármikor kereshetnek Wi-Fi-hálózatokat, még akkor is, ha a Wi-Fi ki van kapcsolva. A funkciót a „Wi-Fi scanning settings” (Wi-Fi-keresési beállítások) részben módosíthatja. "<annotation id="link">"Módosítás"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 1d8094a4f61c..133587000926 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր խոսափողն օգտագործելու թույլտվություն։"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկն օգտագործելու թույլտվություն։"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկը կամ խոսափողն օգտագործելու թույլտվություն։"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Սարք"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Այլ սարք"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Լիցքավորված է"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Լիցքավորվում է"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ծանուցումների ընդլայնված կառավարում"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Միացված է"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Անջատված է"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Միաց․ – Դիմաճանաչման հիման վրա"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Ծանուցումների ընդլայնված կառավարման օգնությամբ կարող եք յուրաքանչյուր հավելվածի ծանուցումների համար նշանակել կարևորության աստիճան՝ 0-5 սահմաններում: \n\n"<b>"5-րդ աստիճան"</b>" \n- Ցուցադրել ծանուցումների ցանկի վերևում \n- Թույլատրել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"4-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"3-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n\n"<b>"2-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n\n"<b>"1-ին աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n- Չցուցադրել կողպէկրանում և կարգավիճակի գոտում \n- Ցուցադրել ծանուցումների ցանկի ներքևում \n\n"<b>"0-րդ աստիճան"</b>\n"- Արգելափակել հավելվածի բոլոր ծանուցումները"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Ծանուցումներ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Այլևս չեք ստանա նման ծանուցումներ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Բացելու համար օգտագործեք մատնահետքը"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Պահանջվում է նույնականացում։ Դրա համար մատը հպեք մատնահետքի սկաներին։"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ընթացիկ հեռախոսազանգ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Բջջային ինտերնետն ավտոմատ չի միանա"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Կապ չկա"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Այլ հասանելի ցանցեր չկան"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Հասանելի ցանցեր չկան"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Ցանցի տվյալներ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Հպեք ցանցին՝ միանալու համար"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ապակողպեք՝ ցանցերը դիտելու համար"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ցանցերի որոնում…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Չհաջողվեց միանալ ցանցին"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi-ն ավտոմատ չի միանա"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Տեսնել բոլորը"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Մի ցանցից մյուսին անցնելու համար անջատեք Ethernet-ը"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Սարքի աշխատանքը բարելավելու համար հավելվածներն ու ծառայությունները կորոնեն Wi‑Fi ցանցեր, նույնիսկ երբ Wi‑Fi-ն անջատված է։ Այս պարամետրը կարող եք փոխել Wi‑Fi ցանցերի որոնման կարգավորումներում։ "<annotation id="link">"Փոխել"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 76ee7224933c..83b6371f4505 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> @@ -190,7 +191,7 @@ <string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikon wajah"</string> <string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Tombol perbesar/perkecil kompatibilitas."</string> <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"Perbesar dari layar kecil ke besar."</string> - <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tersambung."</string> + <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string> <string name="accessibility_bluetooth_disconnected" msgid="7195823280221275929">"Bluetooth terputus."</string> <string name="accessibility_no_battery" msgid="3789287732041910804">"Tidak ada baterai."</string> <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"Baterai satu batang."</string> @@ -215,8 +216,8 @@ <string name="accessibility_signal_full" msgid="5920148525598637311">"Sinyal penuh."</string> <string name="accessibility_desc_on" msgid="2899626845061427845">"Aktif."</string> <string name="accessibility_desc_off" msgid="8055389500285421408">"Nonaktif."</string> - <string name="accessibility_desc_connected" msgid="3082590384032624233">"Tersambung."</string> - <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string> + <string name="accessibility_desc_connected" msgid="3082590384032624233">"Terhubung."</string> + <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menghubungkan."</string> <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string> <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string> <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string> @@ -271,7 +272,7 @@ <string name="accessibility_quick_settings_bluetooth_off" msgid="3795983516942423240">"Bluetooth nonaktif."</string> <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"Bluetooth aktif."</string> <string name="accessibility_quick_settings_bluetooth_connecting" msgid="7362294657419149294">"Bluetooth menyambung."</string> - <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Bluetooth tersambung."</string> + <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Bluetooth terhubung."</string> <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"Bluetooth dinonaktifkan."</string> <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"Bluetooth diaktifkan."</string> <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Pelaporan lokasi nonaktif."</string> @@ -389,9 +390,9 @@ <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Setelan pengguna"</string> <string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string> <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string> - <string name="quick_settings_connected" msgid="3873605509184830379">"Tersambung"</string> + <string name="quick_settings_connected" msgid="3873605509184830379">"Terhubung"</string> <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Terhubung, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> - <string name="quick_settings_connecting" msgid="2381969772953268809">"Menyambung..."</string> + <string name="quick_settings_connecting" msgid="2381969772953268809">"Menghubungkan..."</string> <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Menambatkan"</string> <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Hotspot"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Mengaktifkan…"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan mikrofon."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Langkah ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Perangkat lainnya"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Terisi penuh"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengisi daya"</string> @@ -562,30 +563,30 @@ <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Otoritas sertifikat diinstal di perangkat. Traffic jaringan aman Anda mungkin dipantau atau diubah."</string> <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di profil kerja, tetapi tidak di profil pribadi."</string> - <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> - <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda tersambung ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> - <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Profil pribadi Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> + <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> + <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda terhubung ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> + <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Profil pribadi Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"Perangkat dikelola oleh <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string> <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> untuk mengelola perangkat Anda."</string> <string name="monitoring_description_do_body" msgid="7700878065625769970">"Admin dapat memantau dan mengelola setelan, akses perusahaan, aplikasi, data terkait perangkat, dan informasi lokasi perangkat."</string> <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string> <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"Pelajari lebih lanjut"</string> - <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> + <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Buka setelan VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Buka kredensial terpercaya"</string> <string name="monitoring_description_network_logging" msgid="577305979174002252">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat.\n\nUntuk informasi selengkapnya, hubungi admin."</string> <string name="monitoring_description_vpn" msgid="1685428000684586870">"Anda memberikan izin kepada aplikasi untuk menyiapkan sambungan VPN.\n\nAplikasi ini ini dapat memantau aktivitas perangkat dan jaringan, termasuk email, aplikasi, dan situs web."</string> - <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga tersambung ke VPN, yang dapat memantau aktivitas jaringan."</string> + <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga terhubung ke VPN, yang dapat memantau aktivitas jaringan."</string> <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Perangkat ini dikelola oleh orang tuamu. Orang tuamu bisa melihat dan mengelola berbagai informasi, seperti aplikasi yang kamu gunakan, lokasimu, dan lama pemakaian perangkat."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> - <string name="monitoring_description_app" msgid="376868879287922929">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> - <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string> - <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string> - <string name="monitoring_description_app_work" msgid="3713084153786663662">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs.\n\nHubungi admin untuk mendapatkan informasi lebih lanjut."</string> - <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs.\n\nAnda juga tersambung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string> + <string name="monitoring_description_app" msgid="376868879287922929">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string> + <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string> + <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string> + <string name="monitoring_description_app_work" msgid="3713084153786663662">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil terhubung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs.\n\nHubungi admin untuk mendapatkan informasi lebih lanjut."</string> + <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil terhubung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs.\n\nAnda juga terhubung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Tetap terbuka kuncinya oleh TrustAgent"</string> <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"Perangkat akan tetap terkunci hingga Anda membukanya secara manual"</string> <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrol notifikasi daya"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aktif"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Nonaktif"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktif - Berbasis deteksi wajah"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Dengan kontrol notifikasi daya, Anda dapt menyetel level kepentingan notifikasi aplikasi dari 0 sampai 5. \n\n"<b>"Level 5"</b>" \n- Muncul di atas daftar notifikasi \n- Izinkan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 4"</b>" \n- Jangan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 3"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n\n"<b>"Level 2"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara dan getaran \n\n"<b>"Level 1"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara atau getaran \n- Sembunyikan dari layar kunci dan bilah status \n- Muncul di bawah daftar notifikasi \n\n"<b>"Level 0"</b>" \n- Blokir semua notifikasi dari aplikasi"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifikasi"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Anda tidak akan melihat notifikasi ini lagi"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan sidik jari untuk membuka"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Perlu autentikasi. Sentuh sensor sidik jari untuk melakukan autentikasi."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telepon sedang berlangsung"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data seluler tidak akan terhubung otomatis"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tidak ada koneksi"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Jaringan lain tidak tersedia"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Jaringan tidak tersedia"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detail jaringan"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ketuk jaringan untuk menghubungkan"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Buka kunci untuk melihat jaringan"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Mencari jaringan …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Gagal menghubungkan ke jaringan"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tidak akan otomatis terhubung untuk saat ini"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Untuk beralih jaringan, lepaskan kabel ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Agar pengalaman perangkat menjadi lebih baik, aplikasi dan layanan tetap dapat memindai jaringan Wi-Fi kapan saja, bahkan saat Wi-Fi nonaktif. Anda dapat mengubahnya di setelan pemindaian Wi-Fi. "<annotation id="link">"Ubah"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml index d58cdc89832e..110eb0945975 100644 --- a/packages/SystemUI/res/values-in/strings_tv.xml +++ b/packages/SystemUI/res/values-in/strings_tv.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string> <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mengakses mikrofon"</string> - <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN tersambung"</string> + <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN terhubung"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 01905542684d..af97d98d9f14 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Þetta veitir öllum forritum og þjónustum aðgang að hljóðnemanum þínum."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni þinni."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni og hljóðnemanum þínum."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Tæki"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Annað tæki"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Fullhlaðin"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Í hleðslu"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Orkustillingar tilkynninga"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Kveikt"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Slökkt"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Kveikt – út frá andliti"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Með orkutilkynningastýringum geturðu stillt mikilvægi frá 0 upp í 5 fyrir tilkynningar forrita. \n\n"<b>"Stig 5"</b>" \n- Sýna efst á tilkynningalista \n- Leyfa truflun þegar birt er á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 4"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 3"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n\n"<b>"Stig 2"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n\n"<b>"Stig 1"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n- Fela á lásskjá og stöðustiku \n- Sýna neðst á tilkynningalista \n\n"<b>"Stig 0"</b>" \n- Setja allar tilkynningar frá forriti á bannlista"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Tilkynningar"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Þú munt ekki sjá þessar tilkynningar aftur"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Opna með fingrafari"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Auðkenningar krafist. Auðkenndu með því að snerta fingrafaralesarann."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Símtal í gangi"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Farsímagögn tengjast ekki sjálfkrafa"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Engin tenging"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Engin önnur net í boði"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Ekkert net í boði"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Upplýsingar um net"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ýttu á net til að tengjast"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Taktu úr lás til að skoða netkerfi"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Leitar að netum…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ekki tókst að tengjast neti"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tengist ekki sjálfkrafa eins og er"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Sjá allt"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Aftengdu ethernet til að skipta um net"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Til að bæta tækjaupplifun geta forrit og þjónustur áfram leitað að WiFi-netum hvenær sem er, jafnvel þótt slökkt sé á WiFi. Hægt er að breyta þessu í stillingum WiFi-leitar. "<annotation id="link">"Breyta"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 0efab5ceb84e..1ea1097dfc79 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare il microfono."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera o il microfono."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Altro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carica"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"In carica"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controlli di gestione delle notifiche"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Rotazione basata sul viso"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notifiche"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Non vedrai più queste notifiche"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa l\'impronta per aprire"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessione attiva"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nessuna connessione dati mobili automatica"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nessuna connessione"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nessun\'altra rete disponibile"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nessuna rete disponibile"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Dettagli rete"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tocca una rete per connetterti"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sblocca per visualizzare le reti"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ricerca di reti in corso…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Connessione alla rete non riuscita"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connessione automatica rete Wi-Fi non attiva al momento"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Mostra tutte"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per cambiare rete, scollega il cavo Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per migliorare l\'esperienza con il dispositivo, le app e i servizi possono continuare a cercare reti Wi-Fi in qualsiasi momento, anche quando la connessione Wi-Fi non è attiva. Puoi modificare questa preferenza nelle impostazioni relative alla ricerca di reti Wi-Fi. "<annotation id="link">"Cambia"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 1e4c9d66ed9c..2978a6a346f7 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במיקרופון."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה או במיקרופון."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"מכשיר"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"מכשיר אחר"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"הסוללה טעונה"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"בטעינה"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"פקדים של הודעות הפעלה"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"פועל"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"כבוי"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"פועל – מבוסס על זיהוי פנים"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"בעזרת פקדים של התראות הפעלה, אפשר להגדיר רמת חשיבות מ-0 עד 5 להתראות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצגה בראש רשימת ההתראות \n- לאפשר הפרעה במסך מלא \n- תמיד לאפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מניעת הפרעה במסך מלא \n- תמיד לאפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n- אף פעם לא לאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n- אף פעם לא לאפשר קול ורטט \n- הסתרה ממסך הנעילה ומשורת הסטטוס \n- הצגה בתחתית רשימת ההתראות \n\n"<b>"רמה 0"</b>" \n- חסימת כל ההתראות מהאפליקציה"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"התראות"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ההתראות האלה לא יוצגו לך יותר"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"שימוש בטביעת אצבע כדי לפתוח"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"החיבור לנתונים סלולריים לא מתבצע באופן אוטומטי"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"אין חיבור"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"אין רשתות זמינות אחרות"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"אין רשתות זמינות"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"פרטי הרשת"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"צריך להקיש על רשת כדי להתחבר"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"צריך לבטל את הנעילה כדי להציג את הרשתות"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"בתהליך חיפוש רשתות…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"נכשל הניסיון להתחבר לרשת"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ה-Wi-Fi לא יתחבר באופן אוטומטי בינתיים"</string> + <string name="see_all_networks" msgid="3773666844913168122">"הצגת הכול"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"כדי לעבור בין רשתות, צריך לנתק את האתרנט"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"כדי לשפר את חוויית השימוש במכשיר, אפליקציות ושירותים יוכלו לחפש רשתות Wi-Fi בכל שלב, גם כאשר ה-Wi-Fi כבוי. אפשר לשנות זאת בהגדרות של חיפוש נקודות Wi-Fi. "<annotation id="link">"שינוי"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 27259791f664..ba3d2241152b 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"マイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"カメラの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"カメラやマイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"デバイス"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"その他のデバイス"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"充電が完了しました"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電しています"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"電源通知管理"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ON"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"OFF"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ON - 顔ベース"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"電源通知管理では、アプリの通知の重要度をレベル 0~5 で設定できます。\n\n"<b>"レベル 5"</b>" \n- 通知リストの一番上に表示する \n- 全画面表示を許可する \n- 常にポップアップする \n\n"<b>"レベル 4"</b>" \n- 全画面表示しない \n- 常にポップアップする \n\n"<b>"レベル 3"</b>" \n- 全画面表示しない \n- ポップアップしない \n\n"<b>"レベル 2"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n\n"<b>"レベル 1"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n- ロック画面やステータスバーに表示しない \n- 通知リストの一番下に表示する \n\n"<b>"レベル 0"</b>" \n- アプリからのすべての通知をブロックする"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"通知"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"今後、この通知は表示されません"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"指紋を使って開いてください"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"認証が必要です。指紋認証センサーをタッチして認証してください。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"モバイルデータには自動接続しません"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"接続なし"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"利用できるネットワークはありません"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ネットワークを利用できません"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ネットワークの詳細"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ネットワークをタップして接続"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ネットワークを表示するにはロック解除してください"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ネットワークを検索しています…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ネットワークに接続できませんでした"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi に自動接続しません"</string> + <string name="see_all_networks" msgid="3773666844913168122">"すべて表示"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ネットワークを変更するにはイーサネット接続を解除してください"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"デバイスの機能向上のため、アプリやサービスは、Wi-Fi が OFF の場合でも、いつでも Wi-Fi ネットワークをスキャンできます。この設定は Wi-Fi スキャンの設定で変更できます。"<annotation id="link">"変更"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 21e1c52ae136..19dee6855adc 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი მიკროფონის გამოყენების უფლება."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის გამოყენების უფლება."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის ან მიკროფონის გამოყენების უფლება."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"მოწყობილობა"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"სხვა მოწყობილობა"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"დატენილია"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"მიმდინარეობს დატენვა"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"შეტყობინებების მართვის საშუალებები"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ჩართული"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"გამორთული"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ჩართული — სახის მიხედვით"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"შეტყობინებების მართვის საშუალებების მეშვეობით, შეგიძლიათ განსაზღვროთ აპის შეტყობინებების მნიშვნელობის დონე 0-დან 5-მდე დიაპაზონში. \n\n"<b>"დონე 5"</b>" \n— შეტყობინებათა სიის თავში ჩვენება \n— სრულეკრანიანი რეჟიმის შეფერხების დაშვება \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 4"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 3"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n\n"<b>"დონე 2"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n\n"<b>"დონე 1"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n— ჩაკეტილი ეკრანიდან და სტატუსის ზოლიდან დამალვა \n— შეტყობინებათა სიის ბოლოში ჩვენება \n\n"<b>"დონე 0"</b>" \n— აპის ყველა შეტყობინების დაბლოკვა"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"შეტყობინებები"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ამ შეტყობინებებს აღარ დაინახავთ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"გასახსნელად გამოიყენეთ თითის ანაბეჭდი"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"მობილურ ინტერნეტს ავტომატურად არ დაუკავშირდება"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"კავშირი არ არის"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"სხვა ქსელები მიუწვდომელია"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ქსელები მიუწვდომელია"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ქსელის დეტალები"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"დასაკავშირებლად შეეხეთ ქსელს"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"განბლოკვა ქსელების სანახავად"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"მიმდინარეობს ქსელების ძიება…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ქსელთან დაკავშირება ვერ ხერხდება"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ინტერნეტს დროებით ავტომატურად არ დაუკავშირდება"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ყველას ნახვა"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ქსელების გადასართავად, გაწყვიტეთ Ethernet-თან კავშირი"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"მოწყობილობისგან მიღებული გამოცდილების გასაუმჯობესებლად, აპებსა და სერვისებს მაინც შეუძლია სკანირება Wi‑Fi ქსელების აღმოსაჩენად, ნებისმიერ დროს, მაშინაც კი, როცა Wi‑Fi გამორთულია. ამის შეცვლა Wi-Fi სკანირების პარამეტრებში შეგიძლიათ. "<annotation id="link">"შეცვლა"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 6a9a9b5d8d11..5e3dbdc218d6 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды немесе микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Құрылғы"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Басқа құрылғы"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зарядталды"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядталуда"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Қуат хабарландыруының басқару элементтері"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Қосулы"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Өшірулі"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Қосулы – бет негізінде"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Қуат хабарландыруының басқару элементтерімен қолданбаның хабарландырулары үшін 0-ден бастап 5-ке дейін маңыздылық деңгейін орнатуға болады. \n\n"<b>"5-деңгей"</b>" \n- Хабарландыру тізімінің ең басында көрсету \n- Толық экранға ашылуын рұқсат ету \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"4-деңгей"</b>" \n- Толық экранға шығармау \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"3-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n\n"<b>"2-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс және діріл шығармау \n\n"<b>"1-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс немесе діріл шығармау \n- Құлыпталған экраннан және күйін көрсету жолағынан жасыру \n- Хабарландыру тізімінің ең астында көрсету \n\n"<b>"0-деңгей"</b>" \n- Қолданбадағы барлық хабарландыруларға тыйым салу"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Хабарландырулар"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Хабарландырулар бұдан былай көрсетілмейді"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ашу үшін саусақ ізін пайдаланыңыз."</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аутентификациядан өту қажет. Ол үшін саусақ ізін оқу сканерін түртіңіз."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Телефон қоңырауы бар"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобильдік интернет автоматты түрде қосылмайды."</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыс жоқ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Басқа қолжетімді желі жоқ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Қолжетімді желілер жоқ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Желі деректері"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Желіге қосылу үшін оны түртіңіз."</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Желілерді көру үшін құлыпты ашыңыз."</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Маңайдағы желілер ізделуде…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Желіге қосылмады."</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Әзірше Wi-Fi автоматты түрде қосылмайды."</string> + <string name="see_all_networks" msgid="3773666844913168122">"Барлығын көру"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Желілерді ауыстыру үшін ethernet кабелін ажыратыңыз."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Құрылғы жұмысын жақсарту үшін қолданбалар мен қызметтер Wi-Fi байланысы өшірулі кезде де Wi-Fi желілерін іздейді. Оны Wi-Fi іздеу параметрлерінен өзгерте аласыз. "<annotation id="link">"Өзгерту"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 080ba1958e24..7aee43f0018a 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើមីក្រូហ្វូនរបស់អ្នក។"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ារបស់អ្នក។"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ា ឬមីក្រូហ្វូនរបស់អ្នក។"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ឧបករណ៍"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ឧបករណ៍ផ្សេងទៀត"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើកទិដ្ឋភាពរួម"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"បានសាកថ្មពេញ"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"កំពុងសាកថ្ម"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"អង្គគ្រប់គ្រងការជូនដំណឹងថាមពល"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"បើក"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"បិទ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"បើក - ផ្អែកលើមុខ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ជាមួយអង្គគ្រប់គ្រងការជូនដំណឹងថាមពល អ្នកអាចកំណត់កម្រិតសំខាន់ពី 0 ទៅ 5 សម្រាប់ការជូនដំណឹងរបស់កម្មវិធី។ \n\n"<b>"កម្រិត 5"</b>" \n- បង្ហាញនៅផ្នែកខាងលើបញ្ជីជូនដំណឹង \n- អនុញ្ញាតការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 4"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 3"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 2"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n\n"<b>"កម្រិត 1"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n- លាក់ពីអេក្រង់ចាក់សោ និងរបារស្ថានភាព \n- បង្ហាញនៅផ្នែកខាងក្រោមបញ្ជីជូនដំណឹង \n\n"<b>"កម្រិត 0"</b>" \n- រារាំងការជូនដំណឹងទាំងអស់ពីកម្មវិធី"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ការជូនដំណឹង"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"អ្នកនឹងមិនឃើញការជូនដំណឹងទាំងនេះទៀតទេ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ប្រើស្នាមម្រាមដៃ ដើម្បីបើក"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"តម្រូវឱ្យមានការផ្ទៀងផ្ទាត់។ សូមចុចឧបករណ៍ចាប់ស្នាមម្រាមដៃ ដើម្បីផ្ទៀងផ្ទាត់។"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យទូរសព្ទចល័ត"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ទិន្នន័យទូរសព្ទចល័តនឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"មិនមានការតភ្ជាប់ទេ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"មិនមានបណ្ដាញផ្សេងទៀតដែលអាចប្រើបានទេ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"មិនមានបណ្ដាញដែលអាចប្រើបានទេ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ព័ត៌មានលម្អិតអំពីបណ្ដាញ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ចុចលើបណ្ដាញណាមួយ ដើម្បីភ្ជាប់"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ដោះសោដើម្បីមើលបណ្ដាញ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"កំពុងស្វែងរកបណ្ដាញ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"មិនអាចភ្ជាប់បណ្ដាញបានទេ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិក្នុងពេលនេះទេ"</string> + <string name="see_all_networks" msgid="3773666844913168122">"មើលទាំងអស់"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ដើម្បីប្ដូរបណ្ដាញ សូមផ្ដាច់អ៊ីសឺរណិត"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ដើម្បីធ្វើឱ្យបទពិសោធន៍ប្រើប្រាស់ឧបករណ៍ប្រសើរឡើង កម្មវិធី និងសេវាកម្មនៅតែអាចស្កេនរកបណ្ដាញ Wi‑Fi បានគ្រប់ពេល ទោះបីជានៅពេលដែលបិទ Wi‑Fi ក៏ដោយ។ អ្នកអាចប្ដូរវាបាននៅក្នុងការកំណត់ការស្កេន Wi‑Fi។ "<annotation id="link">"ប្ដូរ"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f63d02f6682a..8aa8febf4690 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/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> @@ -132,7 +133,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"ಪರದೆಯನ್ನು ತಿರುಗಿಸಿ"</string> <string name="accessibility_recent" msgid="901641734769533575">"ಸಮಗ್ರ ನೋಟ"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"ಹುಡುಕಿ"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string> @@ -434,14 +435,14 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಅಥವಾ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ಸಾಧನ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ಅನ್ಯ ಸಾಧನ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"ನೆಟ್ವರ್ಕ್\n ವೀಕ್ಷಿಸಬಹುದಾಗಿರುತ್ತದೆ"</string> - <string name="description_target_search" msgid="3875069993128855865">"Search"</string> + <string name="description_target_search" msgid="3875069993128855865">"ಹುಡುಕಿ"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ಗಾಗಿ ಮೇಲಕ್ಕೆ ಸ್ಲೈಡ್ ಮಾಡಿ."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ಗಾಗಿ ಎಡಕ್ಕೆ ಸ್ಲೈಡ್ ಮಾಡಿ."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ಅಲಾರಾಂಗಳು, ಜ್ಞಾಪನೆಗಳು, ಈವೆಂಟ್ಗಳು ಹಾಗೂ ನೀವು ಸೂಚಿಸಿರುವ ಕರೆದಾರರನ್ನು ಹೊರತುಪಡಿಸಿ ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ನೀವು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ಆನ್"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ಆಫ್"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ಆನ್ ಆಗಿದೆ - ಮುಖ-ಆಧಾರಿತ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಅಪ್ಲಿಕೇಶನ್ಗಳ ಅಧಿಸೂಚನೆಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ಅಧಿಸೂಚನೆಗಳು"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನೋಡುವುದಿಲ್ಲ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ತೆರೆಯುವುದಕ್ಕಾಗಿ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ. ದೃಢೀಕರಿಸಲು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಫೋನ್ ಕರೆ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ಯಾವುದೇ ಕನೆಕ್ಷನ್ ಇಲ್ಲ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ಇತರ ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"ವೈ‑ಫೈ"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ನೆಟ್ವರ್ಕ್ ವಿವರಗಳು"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ಕನೆಕ್ಟ್ ಮಾಡಲು ಒಂದು ನೆಟ್ವರ್ಕ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ಸದ್ಯದ ಮಟ್ಟಿಗೆ ವೈ-ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಬದಲಿಸಲು, ಇಥರ್ನೆಟ್ ಅನ್ನು ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ವೈ-ಫೈ ಆಫ್ ಇದ್ದಾಗಲೂ ಸಹ, ಸಾಧನದ ಅನುಭವವನ್ನು ಸುಧಾರಿಸಲು, ಆ್ಯಪ್ಗಳು ಮತ್ತು ಸೇವೆಗಳು ಯಾವಾಗ ಬೇಕಾದರೂ ಸಹ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಬಹುದು. ನೀವು ಇದನ್ನು ವೈ-ಫೈ ಸ್ಕ್ಯಾನಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು. "<annotation id="link">"ಬದಲಿಸಿ"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 371b7de67806..0346c45af6ea 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"카메라를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"카메라 또는 마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"기기"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"기타 기기"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"충전됨"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"충전 중"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"전원 알림 컨트롤"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"사용"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"사용 안함"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"켜짐 - 얼굴 기준"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"전원 알림 컨트롤을 사용하면 앱 알림 관련 중요도를 0부터 5까지로 설정할 수 있습니다. \n\n"<b>"레벨 5"</b>" \n- 알림 목록 상단에 표시 \n- 전체 화면일 경우 알림 표시 허용 \n- 항상 엿보기 표시 \n\n"<b>"레벨 4"</b>" \n- 전체 화면에 알림 표시 금지 \n- 항상 엿보기 표시 \n\n"<b>"레벨 3"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n\n"<b>"레벨 2"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n\n"<b>"레벨 1"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n- 잠금 화면 및 상태 표시줄에서 숨김 \n- 알림 목록 하단에 표시 \n\n"<b>"레벨 0"</b>" \n- 앱의 모든 알림 차단"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"알림"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"더 이상 다음의 알림을 받지 않습니다"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"지문으로 열기"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"인증이 필요합니다. 지문 센서를 터치하여 인증하세요."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"진행 중인 전화 통화"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"모바일 데이터가 자동으로 연결되지 않음"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"연결되지 않음"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"사용 가능한 다른 네트워크가 없음"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"사용 가능한 네트워크가 없음"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"네트워크 세부정보"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"연결하려면 네트워크를 탭하세요"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"네트워크를 보려면 잠금 해제하세요"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"네트워크 검색 중…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"네트워크에 연결하지 못했습니다."</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"지금은 Wi-Fi가 자동으로 연결되지 않습니다."</string> + <string name="see_all_networks" msgid="3773666844913168122">"모두 보기"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"네트워크를 전환하려면 이더넷을 연결 해제하세요."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"기기 환경을 개선하기 위해 Wi‑Fi가 꺼져 있을 때도 앱과 서비스에서 Wi‑Fi 네트워크를 검색할 수 있습니다. 이 설정은 Wi‑Fi 검색 설정에서 변경할 수 있습니다. "<annotation id="link">"변경"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 404b9ac45179..c86f2f93da52 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераны колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды же микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Башка түзмөк"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Кубатталууда"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Эскертмелерди башкаруу каражаттары"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Күйүк"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Өчүк"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Күйүк – Жүздүн негизинде"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Бул функциянын жардамы менен, ар бир колдонмо үчүн билдирменин маанилүүлүгүн 0дон 5ке чейин бааласаңыз болот. \n\n"<b>"5-деңгээл"</b>" \n- Билдирмелер тизмесинин өйдө жагында көрүнөт \n- Билдирмелер толук экранда көрүнөт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"4-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"3-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n\n"<b>"2-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n\n"<b>"1-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n- Кулпуланган экрандан жана абал тилкесинен жашырылат \n- Билдирмелер тизмесинин ылдый жагында көрүнөт \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык билдирмелер бөгөттөлөт"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Билдирмелер"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Мындан ары бул билдирмелер сизге көрүнбөйт"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Манжаңыздын изи менен ачыңыз"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аныктыкты текшерүү талап кылынат. Аныктыгын текшерүү үчүн манжа изинин сенсоруна тийип коюңуз."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Учурдагы телефон чалуу"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилдик трафик автоматтык түрдө туташтырылбайт"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыш жок"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Башка тармактар жеткиликсиз"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Тармактар жеткиликтүү эмес"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Тармактын чоо-жайы"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Кайсы тармакка туташасыз?"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Тармактарды көрүү үчүн кулпусун ачыңыз"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Тармактар изделүүдө…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Тармакка туташпай калды"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi азырынча автоматтык түрдө туташпайт"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Баарын көрүү"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Башка тармактарга которулуу үчүн Ethernet кабелин ажыратыңыз"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Түзмөктүн колдонулушун жакшыртуу үчүн колдонмолор менен кызматтар Wi‑Fi өчүп турса да зымсыз тармактарды издей беришет. Аны Wi-Fi тармактарын издөө жөндөөлөрүнөн өзгөртө аласыз. "<annotation id="link">"Өзгөртүү"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 33fddef3efb3..969818e28d26 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ໄມໂຄຣໂຟນຂອງທ່ານ."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຂອງທ່ານ."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະປົດບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ອຸປະກອນອື່ນໆ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ສາກເຕັມແລ້ວ."</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ກຳລັງສາກໄຟ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ເປີດ"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ປິດ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ເປີດ - ອ້າງອີງໃບໜ້າ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ດ້ວຍການຄວບຄຸມການແຈ້ງເຕືອນ, ທ່ານສາມາດຕັ້ງລະດັບຄວາມສຳຄັນຈາກ 0 ຮອດ 5 ໃຫ້ກັບການແຈ້ງເຕືອນແອັບໃດໜຶ່ງໄດ້. \n\n"<b>"ລະດັບ 5"</b>" \n- ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ \n- ອະນຸຍາດໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 4"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 3"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n\n"<b>"ລະດັບ 2"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n\n"<b>"ລະດັບ 1"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n- ເຊື່ອງຈາກໜ້າຈໍລັອກ ແລະ ແຖບສະຖານະ \n- ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນ \n\n"<b>"ລະດັບ 0"</b>" \n- ປິດກັ້ນການແຈ້ງເຕືອນທັງໝົດຈາກແອັບ"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ການແຈ້ງເຕືອນ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ໃຊ້ລາຍນິ້ວມືເພື່ອເປີດ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ຕ້ອງພິສູດຢືນຢັນ. ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມືເພື່ອພິສູດຢືນຢັນ."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ສາຍໂທອອກ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ຈະບໍ່ເຊື່ອມຕໍ່ອິນເຕີເນັດມືຖືອັດຕະໂນມັດ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ບໍ່ມີການເຊື່ອມຕໍ່"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ບໍ່ມີເຄືອຂ່າຍອື່ນທີ່ສາມາດໃຊ້ໄດ້"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ບໍ່ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ລາຍລະອຽດເຄືອຂ່າຍ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ແຕະເຄືອຂ່າຍໃດໜຶ່ງເພື່ອເຊື່ອມຕໍ່"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ປົດລັອກເພື່ອເບິ່ງເຄືອຂ່າຍ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ກຳລັງຊອກຫາເຄືອຂ່າຍ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ເຊື່ອມຕໍ່ເຄືອຂ່າຍບໍ່ສຳເລັດ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ຈະບໍ່ເຊື່ອມຕໍ່ອັດຕະໂນມັດສຳລັບຕອນນີ້"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ເບິ່ງທັງໝົດ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ເພື່ອສະຫຼັບເຄືອຂ່າຍ, ໃຫ້ຕັດການເຊື່ອມຕໍ່ອີເທີເນັດກ່ອນ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ເພື່ອປັບປຸງປະສົບການອຸປະກອນ, ແອັບ ແລະ ບໍລິການຍັງຄົງສາມາດສະແກນຫາເຄືອຂ່າຍ Wi‑Fi ຕອນໃດກໍໄດ້, ເຖິງແມ່ນວ່າຈະປິດ Wi‑Fi ໄວ້ກໍຕາມ. ທ່ານສາມາດປ່ຽນສິ່ງນີ້ໄດ້ໃນການຕັ້ງຄ່າການສະແກນ Wi‑Fi. "<annotation id="link">"ປ່ຽນ"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 94faaf42d1b9..be976160951f 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti mikrofoną."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą ar mikrofoną."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Įrenginys"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Kitas įrenginys"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Įkrautas"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kraunamas"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Galingi pranešimų valdikliai"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Įjungta"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Išjungta"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Įjungta – pagal veidą"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Naudodami pranešimų valdiklius galite nustatyti programos pranešimų svarbos lygį nuo 0 iki 5. \n\n"<b>"5 lygis"</b>" \n– Rodyti pranešimų sąrašo viršuje \n– Leisti pertraukti, kai veikia viso ekrano režimas \n– Visada rodyti pranešimus \n\n"<b>"4 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Visada rodyti pranešimus \n\n"<b>"3 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n\n"<b>"2 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n\n"<b>"1 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n– Slėpti užrakinimo ekrane ir būsenos juostoje \n– Rodyti pranešimų sąrašo apačioje \n\n"<b>"0 lygis"</b>" \n– Blokuoti visus programos pranešimus"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Pranešimai"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Nebematysite šių pranešimų"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Naudokite kontrolinį kodą, kad atidarytumėte"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Reikia nustatyti tapatybę. Nustatykite tapatybę palietę kontrolinio kodo jutiklį."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Vykstantis telefono skambutis"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Naud. mob. r. duomenis nebus autom. prisijungiama"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nėra ryšio"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nėra kitų pasiekiamų tinklų"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nėra pasiekiamų tinklų"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Išsami tinklo informacija"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Palieskite tinklą, kad prisijungtumėte"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Atrakinkite, kad peržiūrėtumėte visus tinklus"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ieškoma tinklų…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Jungiantis prie tinklo įvyko klaida"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"„Wi-Fi“ šiuo metu nebus prijungtas automatiškai"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Žiūrėti viską"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Norėdami perjungti tinklus, atjunkite eternetą"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Kad pagerintų įrenginio funkcijas, programos ir paslaugos vis tiek gali bet kada nuskaityti ieškodamos „Wi‑Fi“ tinklų, net jei „Wi‑Fi“ išjungtas. Tai galite pakeisti „Wi-Fi“ nuskaitymo nustatymuose. "<annotation id="link">"Pakeisti"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 0d14405ea4fb..e4ba5df7631f 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Visas lietotnes un pakalpojumi, kurām ir atļauts izmantot mikrofonu, varēs tam piekļūt."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru, varēs tai piekļūt."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Cita ierīce"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Akumulators uzlādēts"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Notiek uzlāde"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Barošanas paziņojumu vadīklas"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ieslēgts"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Izslēgts"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ieslēgta — ar sejas noteikšanu"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Izmantojot barošanas paziņojumu vadīklas, varat lietotnes paziņojumiem iestatīt svarīguma līmeni (no 0 līdz 5). \n\n"<b>"5. līmenis"</b>" \n- Tiek rādīts paziņojumu saraksta augšdaļā \n- Tiek atļauta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"4. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"3. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n\n"<b>"2. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n\n"<b>"1. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n- Paziņojumi tiek paslēpti bloķēšanas ekrānā un statusa joslā \n- Paziņojumi tiek rādīti paziņojumu saraksta apakšdaļā \n\n"<b>"0. līmenis"</b>" \n- Visi lietotnes paziņojumi tiek bloķēti"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Paziņojumi"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Jūs vairs neredzēsiet šos paziņojumus."</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Atvēršanai izmantojiet pirksta nospiedumu"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Nepieciešama autentifikācija. Pieskarieties pirksta nospieduma sensoram, lai veiktu autentificēšanu."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Notiekošs tālruņa zvans"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilo datu savienojums netiks veidots automātiski"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nav savienojuma"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nav pieejams neviens cits tīkls"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nav pieejams neviens tīkls"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Dati par tīklu"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Pieskarieties tīklam, lai izveidotu savienojumu"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lai skatītu tīklus, atbloķējiet"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Notiek tīklu meklēšana…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Neizdevās izveidot savienojumu ar tīklu"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi savienojums īslaicīgi netiks izveidots automātiski."</string> + <string name="see_all_networks" msgid="3773666844913168122">"Visu tīklu skatīšana"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Lai pārslēgtu tīklus, atvienojiet tīkla Ethernet vadu."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Lai uzlabotu ierīces lietošanas iespējas, lietotnes un pakalpojumi joprojām varēs meklēt Wi‑Fi tīklus jebkurā laikā, pat ja Wi‑Fi būs izslēgts. Varat to mainīt Wi‑Fi meklēšanas iestatījumos. "<annotation id="link">"Mainīt"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 5fda8b211ab1..721bd2b9fdbf 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на микрофонот."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата или микрофонот."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Уред"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Друг уред"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Наполнета"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Се полни"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Контроли за известувањата за напојување"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Вклучено"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Исклучено"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Вклучено - според лице"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Со контролите за известувањата за напојување, може да поставите ниво на важност од 0 до 5 за известувањата на која било апликација. \n\n"<b>"Ниво 5"</b>" \n- Прикажувај на врвот на списокот со известувања \n- Дозволи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 4"</b>" \n- Спречи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 3"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n\n"<b>"Ниво 2"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n\n"<b>"Ниво 1"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n- Сокриј од заклучен екран и статусна лента \n- Прикажувај на дното на списокот со известувања \n\n"<b>"Ниво 0"</b>" \n- Блокирај ги сите известувања од апликацијата"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Известувања"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Веќе нема да ги гледате овие известувања"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Користете отпечаток за да се отвори"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна е проверка. Допрете го сензорот за отпечаток за да автентицирате."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Тековен телефонски повик"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилниот интернет не може автоматски да се поврзе"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нема интернет-врска"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нема други достапни мрежи"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Нема достапни мрежи"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Детали за мрежата"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Допрете на мрежа за да се поврзете"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Отклучете за да се прикажат мрежите"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Се пребаруваат мрежи…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не успеа да се поврзе на мрежата"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi нема да се поврзува автоматски засега"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Прикажи ги сите"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"За промена на мрежата, прекинете ја врската со етернетот"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"За да се подобри доживувањето на уредот, апликациите и услугите може сѐ уште да скенираат за Wi‑Fi мрежи во секое време, дури и кога Wi‑Fi е исклучено. Може да го промените ова во поставките за „Скенирање за Wi-Fi“. "<annotation id="link">"Промени"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 6956934d7af7..e432a1dc9ee5 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> @@ -132,7 +133,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ഉപയോഗസഹായി"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"സ്ക്രീൻ തിരിക്കുക"</string> <string name="accessibility_recent" msgid="901641734769533575">"അവലോകനം"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"തിരയൽ"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"ക്യാമറ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്സ് സഹായം"</string> @@ -434,14 +435,14 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"നിങ്ങളുടെ മൈക്രോഫോൺ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"നിങ്ങളുടെ ക്യാമറ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"നിങ്ങളുടെ ക്യാമറയോ മൈക്രോഫോണോ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ഉപകരണം"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"മറ്റ് ഉപകരണം"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ചാർജായി"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ചാർജ് ചെയ്യുന്നു"</string> <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"ഫുൾ ചാർജാകാൻ, <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"നെറ്റ്വർക്ക്\nനിരീക്ഷിക്കപ്പെടാം"</string> - <string name="description_target_search" msgid="3875069993128855865">"Search"</string> + <string name="description_target_search" msgid="3875069993128855865">"തിരയൽ"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> എന്നതിനായി മുകളിലേയ്ക്ക് സ്ലൈഡുചെയ്യുക."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> എന്നതിനായി ഇടത്തേയ്ക്ക് സ്ലൈഡുചെയ്യുക."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"നിങ്ങൾ സജ്ജീകരിച്ച അലാറങ്ങൾ, റിമൈൻഡറുകൾ, ഇവന്റുകൾ, കോളർമാർ എന്നിവയിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"പവർ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ഓൺ"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ഓഫ്"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ഓണാണ് - ഫേസ് ബേസ്ഡ്"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"പവർ അറിയിപ്പ് നിയന്ത്രണം ഉപയോഗിച്ച്, ഒരു ആപ്പിനായുള്ള അറിയിപ്പുകൾക്ക് 0 മുതൽ 5 വരെയുള്ള പ്രാധാന്യ ലെവലുകളിലൊന്ന് നിങ്ങൾക്ക് സജ്ജമാക്കാവുന്നതാണ്. \n\n"<b>"ലെവൽ 5"</b>" \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ മുകളിൽ കാണിക്കുക \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം അനുവദിക്കുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 4"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 3"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും സൃശ്യമാക്കരുത് \n\n"<b>"ലെവൽ 2"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n\n"<b>"ലെവൽ 1"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n- ലോക്ക് സ്ക്രീനിൽ നിന്നും സ്റ്റാറ്റസ് ബാറിൽ നിന്നും മറയ്ക്കുക \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ അടിയിൽ കാണിക്കുക \n\n"<b>"ലെവൽ 0"</b>" \n- ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"അറിയിപ്പുകൾ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"നിങ്ങൾ ഇനി ഈ അറിയിപ്പുകൾ കാണില്ല"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"തുറക്കുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. പരിശോധിച്ചുറപ്പിക്കാൻ, വിരലടയാള സെൻസറിൽ സ്പർശിക്കുക."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"സജീവമായ ഫോൺ കോൾ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"മൊബൈൽ ഡാറ്റ സ്വയമേവ കണക്റ്റ് ചെയ്യില്ല"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"കണക്ഷനില്ല"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"മറ്റ് നെറ്റ്വർക്കുകളൊന്നും ലഭ്യമല്ല"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"നെറ്റ്വർക്കുകളൊന്നും ലഭ്യമല്ല"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"വൈഫൈ"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"നെറ്റ്വർക്ക് വിശദാംശങ്ങൾ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"കണക്റ്റ് ചെയ്യാൻ ഒരു നെറ്റ്വർക്കിൽ ടാപ്പ് ചെയ്യുക"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"നെറ്റ്വർക്കുകൾ കാണാൻ അൺലോക്ക് ചെയ്യുക"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"നെറ്റ്വർക്കുകൾ തിരയുന്നു…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"നെറ്റ്വർക്കിൽ കണക്റ്റ് ചെയ്യാനായില്ല"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"വൈഫൈ ഇപ്പോൾ സ്വയമേവ കണക്റ്റ് ചെയ്യില്ല"</string> + <string name="see_all_networks" msgid="3773666844913168122">"എല്ലാം കാണുക"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"മറ്റ് നെറ്റ്വർക്കുകളിലേക്ക് മാറാൻ, ഇതർനെറ്റ് വിച്ഛേദിക്കുക"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ഉപകരണ അനുഭവം മെച്ചപ്പെടുത്താൻ, വൈഫൈ ഓഫാക്കിയിരിക്കുമ്പോൾ പോലും ആപ്പുകൾക്കും സേവനങ്ങൾക്കും വൈഫൈ നെറ്റ്വർക്കുകൾ കണ്ടെത്താൻ ഏത് സമയത്തും സ്കാൻ ചെയ്യാനാകും. നിങ്ങൾക്ക് ഇത് വൈഫൈ സ്കാനിംഗ് ക്രമീകരണത്തിൽ മാറ്റാം. "<annotation id="link">"മാറ്റുക"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 0d1ad4bebce6..cbab4da4909f 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Энэ нь таны микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Энэ нь таны камерыг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Энэ нь таны камер эсвэл микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Бусад төхөөрөмж"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Цэнэглэгдсэн"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Цэнэглэж байна"</string> @@ -658,7 +659,7 @@ <string name="system_ui_tuner" msgid="1471348823289954729">"Системийн UI Тохируулагч"</string> <string name="show_battery_percentage" msgid="6235377891802910455">"Залгаатай тэжээлийн хувийг харуулах"</string> <string name="show_battery_percentage_summary" msgid="9053024758304102915">"Тэжээлийн хувийг цэнэглээгүй байх үед статусын хэсэгт харуулна уу"</string> - <string name="quick_settings" msgid="6211774484997470203">"Түргэвчилсэн Tохиргоо"</string> + <string name="quick_settings" msgid="6211774484997470203">"Шуурхай тохиргоо"</string> <string name="status_bar" msgid="4357390266055077437">"Статус самбар"</string> <string name="overview" msgid="3522318590458536816">"Тойм"</string> <string name="demo_mode" msgid="263484519766901593">"Системийн UI демо горим"</string> @@ -683,7 +684,7 @@ <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string> <string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> цагт"</string> <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-т"</string> - <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Түргэн Тохиргоо, <xliff:g id="TITLE">%s</xliff:g>."</string> + <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Шуурхай тохиргоо, <xliff:g id="TITLE">%s</xliff:g>."</string> <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Сүлжээний цэг"</string> <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string> <string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string> @@ -696,8 +697,8 @@ <string name="activity_not_found" msgid="8711661533828200293">"Аппыг таны төхөөрөмжид суулгаагүй байна"</string> <string name="clock_seconds" msgid="8709189470828542071">"Цагийн секундыг харуулах"</string> <string name="clock_seconds_desc" msgid="2415312788902144817">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string> - <string name="qs_rearrange" msgid="484816665478662911">"Түргэн тохиргоог дахин засварлах"</string> - <string name="show_brightness" msgid="6700267491672470007">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string> + <string name="qs_rearrange" msgid="484816665478662911">"Шуурхай тохиргоог дахин засварлах"</string> + <string name="show_brightness" msgid="6700267491672470007">"Шуурхай тохиргоонд гэрэлтүүлэг харах"</string> <string name="experimental" msgid="3549865454812314826">"Туршилтын"</string> <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth-г асаах уу?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Тэжээлийн мэдэгдлийн удирдлага"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Идэвхтэй"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Идэвхгүй"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Асаалттай - Царайнд суурилсан"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Тэжээлийн мэдэгдлийн удирдлагын тусламжтайгаар та апп-н мэдэгдэлд 0-5 хүртэлх ач холбогдлын түвшин тогтоох боломжтой. \n\n"<b>"5-р түвшин"</b>" \n- Мэдэгдлийн жагсаалтын хамгийн дээр харуулна \n- Бүтэн дэлгэцэд саад болно \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"4-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"3-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n\n"<b>"2-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n\n"<b>"1-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n- Түгжигдсэн дэлгэц болон статусын самбараас нууна \n- Мэдэгдлийн жагсаалтын доор харуулна \n\n"<b>"0-р түвшин"</b>" \n- Энэ апп-н бүх мэдэгдлийг блоклоно"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Мэдэгдэл"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Та эдгээр мэдэгдлийг цаашид харахгүй"</string> @@ -919,11 +921,11 @@ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> байрлал"</string> <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Хавтан нэмсэн"</string> <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Хавтанг хассан"</string> - <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Түргэн тохиргоо засварлагч."</string> + <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Шуурхай тохиргоо засварлагч."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Тохиргоог нээнэ үү."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Шуурхай тохиргоог нээнэ үү."</string> - <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Хурдан тохиргоог хаана уу."</string> + <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Шуурхай тохиргоог хаана уу."</string> <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"Сэрүүлэг тавьсан."</string> <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g>-р нэвтэрсэн"</string> <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"хэрэглэгчийг сонгох"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Нээхийн тулд хурууны хээг ашиглана уу"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Баталгаажуулалт шаардлагатай. Баталгаажуулахын тулд хурууны хээ мэдрэгчид хүрнэ үү."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Үргэлжилж буй утасны дуудлага"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобайл дата автоматаар холбогдохгүй"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Холболт алга"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Өөр боломжтой сүлжээ байхгүй байна"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Боломжтой сүлжээ байхгүй байна"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Сүлжээний дэлгэрэнгүй мэдээлэл"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Холбогдохын тулд сүлжээг товшино уу"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Сүлжээг харахын тулд түгжээг тайлах"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Сүлжээ хайж байна…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Сүлжээнд холбогдож чадсангүй"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi-г одоогоор автоматаар холбохгүй"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Бүгдийг харах"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Сүлжээг сэлгэхийн тулд этернэтийг салгана уу"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Төхөөрөмжийн туршлагыг сайжруулахын тулд аппууд болон үйлчилгээнүүд нь Wi-Fi сүлжээг хүссэн үедээ буюу Wi-Fi-г унтраалттай байсан ч скан хийх боломжтой хэвээр байна. Та үүнийг Wi-Fi скан хийх тохиргоонд өөрчлөх боломжтой. "<annotation id="link">"Өөрчлөх"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 1202a7467a2c..2e632806668f 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/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> @@ -132,7 +133,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"अॅक्सेसिबिलिटी"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"स्क्रीन फिरवा"</string> <string name="accessibility_recent" msgid="901641734769533575">"अवलोकन"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"शोधा"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"कॅमेरा"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string> @@ -247,7 +248,7 @@ <skip /> <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"सूचना डिसमिस केल्या."</string> <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string> - <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिंग्ज."</string> + <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string> <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string> <string name="accessibility_desc_settings" msgid="6728577365389151969">"सेटिंग्ज"</string> <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"अवलोकन."</string> @@ -434,14 +435,14 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"हे तुमचा मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अॅक्सेस अनब्लॉक करते."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"हे तुमचा कॅमेरा वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अॅक्सेस अनब्लॉक करते."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"हे तुमचा कॅमेरा आणि मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स व सेवांसाठी अॅक्सेस अनब्लॉक करते."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"डिव्हाइस"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"इतर डिव्हाइस"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज झाली"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज होत आहे"</string> <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण होईपर्यंत"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"चार्ज होत नाही"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"नेटवर्कचे परीक्षण\nकेले जाऊ शकते"</string> - <string name="description_target_search" msgid="3875069993128855865">"Search"</string> + <string name="description_target_search" msgid="3875069993128855865">"शोध"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> साठी वर स्लाइड करा."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> साठी डावीकडे स्लाइड करा."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"अलार्म, रिमाइंडर, इव्हेंट आणि तुम्ही निश्चित केलेल्या कॉलर व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> @@ -553,7 +554,7 @@ <string name="disable_vpn" msgid="482685974985502922">"VPN अक्षम करा"</string> <string name="disconnect_vpn" msgid="26286850045344557">"VPN डिस्कनेक्ट करा"</string> <string name="monitoring_button_view_policies" msgid="3869724835853502410">"धोरणे पहा"</string> - <string name="monitoring_button_view_controls" msgid="8316440345340701117">"नियंत्रणे पाहा"</string> + <string name="monitoring_button_view_controls" msgid="8316440345340701117">"नियंत्रणे पहा"</string> <string name="monitoring_description_named_management" msgid="505833016545056036">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> चे आहे.\n\nतुमचा आयटी ॲडमिन सेटिंग्ज, कॉर्पोरेट अॅक्सेस, ॲप्स, तुमच्या डिव्हाइसशी संबंधित डेटा आणि तुमच्या डिव्हाइसच्या स्थानाची माहिती यांचे परीक्षण व व्यवस्थापन करू शकतो.\n\nअधिक माहितीसाठी तुमच्या आयटी ॲडमिनशी संपर्क साधा."</string> <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> कदाचित या डिव्हाइसशी संलग्न असलेला डेटा अॅक्सेस करू शकते, ॲप्सचे व्यवस्थापन करू शकते आणि ही डिव्हाइस सेटिंग्ज बदलू शकते.\n\nतुम्हाला प्रश्न असल्यास, <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> शी संपर्क साधा."</string> <string name="monitoring_description_management" msgid="4308879039175729014">"हे डिव्हाइस तुमच्या संस्थेचे आहे.\n\nतुमचा आयटी ॲडमिन सेटिंग्ज, कॉर्पोरेट अॅक्सेस, ॲप्स, तुमच्या डिव्हाइसशी संबंधित डेटा आणि तुमच्या डिव्हाइसच्या स्थानाची माहिती यांचे परीक्षण व व्यवस्थापन करू शकतो.\n\nअधिक माहितीसाठी तुमच्या आयटी ॲडमिनशी संपर्क साधा."</string> @@ -651,14 +652,14 @@ <string name="output_title" msgid="3938776561655668350">"मीडिया आउटपुट"</string> <string name="output_calls_title" msgid="7085583034267889109">"फोन कॉल आउटपुट"</string> <string name="output_none_found" msgid="5488087293120982770">"कोणतीही डिव्हाइस सापडली नाहीत"</string> - <string name="output_none_found_service_off" msgid="935667567681386368">"कोणतीही डिव्हाइस सापडली नाहीत. <xliff:g id="SERVICE">%1$s</xliff:g> सुरू करून पाहा"</string> + <string name="output_none_found_service_off" msgid="935667567681386368">"कोणतीही डिव्हाइस सापडली नाहीत. <xliff:g id="SERVICE">%1$s</xliff:g> सुरू करून पहा"</string> <string name="output_service_bt" msgid="4315362133973911687">"ब्लूटूथ"</string> <string name="output_service_wifi" msgid="9003667810868222134">"वाय-फाय"</string> <string name="output_service_bt_wifi" msgid="7186882540475524124">"ब्लूटूथ आणि वाय-फाय"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string> <string name="show_battery_percentage" msgid="6235377891802910455">"एम्बेडेड बॅटरी टक्केवारी दर्शवा"</string> <string name="show_battery_percentage_summary" msgid="9053024758304102915">"चार्ज होत नसताना स्टेटस बार चिन्हामध्ये बॅटरी पातळी टक्केवारी दर्शवा"</string> - <string name="quick_settings" msgid="6211774484997470203">"द्रुत सेटिंग्ज"</string> + <string name="quick_settings" msgid="6211774484997470203">"क्विक सेटिंग्ज"</string> <string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string> <string name="overview" msgid="3522318590458536816">"अवलोकन"</string> <string name="demo_mode" msgid="263484519766901593">"सिस्टम UI डेमो मोड"</string> @@ -687,7 +688,7 @@ <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"हॉटस्पॉट"</string> <string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string> <string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string> - <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्याला Android वापरकर्ता इंटरफेस ट्विक आणि कस्टमाइझ करण्याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string> + <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string> <string name="tuner_persistent_warning" msgid="230466285569307806">"ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत."</string> <string name="got_it" msgid="477119182261892069">"समजले"</string> <string name="tuner_toast" msgid="3812684836514766951">"अभिनंदन! सिस्टम UI ट्युनर सेटिंग्जमध्ये जोडले गेले आहे"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"पॉवर सूचना नियंत्रणे"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"सुरू"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"बंद"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"सुरू - चेहऱ्यावर आधारित"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"पॉवर सूचना नियंत्रणांच्या साहाय्याने तुम्ही अॅप सूचनांसाठी 0 ते 5 असे महत्त्व स्तर सेट करू शकता. \n\n"<b>"स्तर 5"</b>" \n- सूचना सूचीच्या शीर्षस्थानी दाखवा \n- फुल स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 4"</b>\n" - फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 3"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n"<b>"स्तर 2"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n\n"<b>"स्तर 1"</b>\n"- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n"<b>"स्तर 0"</b>" \n- अॅपमधील सर्व सूचना ब्लॉक करा"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"सूचना"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"आता तुम्हाला या सूचना दिसणार नाहीत"</string> @@ -754,7 +756,7 @@ <string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉंफिगर केला जाऊ शकत नाही"</string> <string name="notification_delegate_header" msgid="1264510071031479920">"प्रॉक्सी केलेल्या सूचना"</string> <string name="notification_channel_dialog_title" msgid="6856514143093200019">"सर्व <xliff:g id="APP_NAME">%1$s</xliff:g> वरील सूचना"</string> - <string name="see_more_title" msgid="7409317011708185729">"आणखी पाहा"</string> + <string name="see_more_title" msgid="7409317011708185729">"आणखी पहा"</string> <string name="appops_camera" msgid="5215967620896725715">"हे अॅप कॅमेरा वापरत आहे."</string> <string name="appops_microphone" msgid="8805468338613070149">"हे अॅप मायक्रोफोन वापरत आहे."</string> <string name="appops_overlay" msgid="4822261562576558490">"हे अॅप स्क्रीनवरील इतर अॅप्स वर प्रदर्शित होत आहे."</string> @@ -847,7 +849,7 @@ <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"संगीत"</string> <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string> - <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"कॅलेंडर"</string> <string name="tuner_full_zen_title" msgid="5120366354224404511">"आवाज नियंत्रणांसह दर्शवा"</string> <string name="volume_and_do_not_disturb" msgid="502044092739382832">"व्यत्यय आणू नका"</string> <string name="volume_dnd_silent" msgid="4154597281458298093">"आवाजाच्या बटणांचा शार्टकट"</string> @@ -938,14 +940,14 @@ <string name="thermal_shutdown_title" msgid="2702966892682930264">"तापल्यामुळे फोन बंद झाला"</string> <string name="thermal_shutdown_message" msgid="6142269839066172984">"तुमचा फोन आता नेहमीप्रमाणे काम करत आहे.\nअधिक माहितीसाठी टॅप करा"</string> <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"तुमचा फोन खूप तापलाय, म्हणून तो थंड होण्यासाठी बंद झाला आहे. तुमचा फोन आता व्यवस्थित सुरू आहे.\n\nतुम्ही असे केल्यास तुमचा फोन खूप तापेल:\n •संसाधन केंद्रित अॅप वापरणे (गेमिंग, व्हिडिओ किंवा नेव्हिगेशन अॅप यासारखे)\n •मोठ्या फाइल डाउनलोड किंवा अपलोड करणे\n •उच्च तापमानामध्ये तुमचा फोन वापरणे"</string> - <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"काय काळजी घ्यावी ते पाहा"</string> + <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"काय काळजी घ्यावी ते पहा"</string> <string name="high_temp_title" msgid="2218333576838496100">"फोन ऊष्ण होत आहे"</string> <string name="high_temp_notif_message" msgid="1277346543068257549">"फोन थंड होईपर्यंत काही वैशिष्ट्ये मर्यादित केली.\nअधिक माहितीसाठी टॅप करा"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"तुमचा फोन स्वयंचलितपणे थंड होईल. तुम्ही अद्यापही तुमचा फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nतुमचा फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string> - <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"काय काळजी घ्यावी ते पाहा"</string> + <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"काय काळजी घ्यावी ते पहा"</string> <string name="high_temp_alarm_title" msgid="2359958549570161495">"चार्जर अनप्लग करा"</string> <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"हे डिव्हाइस चार्ज करताना समस्या आहे. पॉवर अडॅप्टर अनप्लग करा आणि शक्य तेवढी काळजी घ्या कदाचित केबल गरम असू शकते."</string> - <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"काय काळजी घ्यावी ते पाहा"</string> + <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"काय काळजी घ्यावी ते पहा"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"डावा शॉर्टकट"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"उजवा शॉर्टकट"</string> <string name="lockscreen_unlock_left" msgid="1417801334370269374">"डावा शॉर्टकट देखील अनलॉक करतो"</string> @@ -1013,7 +1015,7 @@ <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(ऑफिस)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"फोन कॉल"</string> <string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(<xliff:g id="APPLICATION_NAME_S_">%s</xliff:g> द्वारे)"</string> - <string name="privacy_type_camera" msgid="7974051382167078332">"कॅमेरा"</string> + <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"मायक्रोफोन"</string> <string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सर बंद आहेत"</string> @@ -1035,7 +1037,7 @@ <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फुल स्क्रीन मॅग्निफाय करा"</string> <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string> <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच करा"</string> - <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"अॅक्सेसिबिलिटी जेश्चर हे आता अॅक्सेसिबिलिटी बटण आहे \n\n"<annotation id="link">"सेटिंग्ज पाहा"</annotation></string> + <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"अॅक्सेसिबिलिटी जेश्चर हे आता अॅक्सेसिबिलिटी बटण आहे \n\n"<annotation id="link">"सेटिंग्ज पहा"</annotation></string> <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"तुम्ही अॅक्सेसिबिलिटी जेश्चरवरून बटणवर स्विच करू शकता \n\n"<annotation id="link">"सेटिंग्ज"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्यामध्ये हलवा"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"वर डावीकडे हलवा"</string> @@ -1144,7 +1146,7 @@ <string name="status_before_loading" msgid="1500477307859631381">"आशय लवकरच दाखवला जाईल"</string> <string name="missed_call" msgid="4228016077700161689">"मिस्ड कॉल"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> - <string name="people_tile_description" msgid="8154966188085545556">"अलीकडील मेसेज, मिस्ड कॉल आणि स्टेटस अपडेट पाहा"</string> + <string name="people_tile_description" msgid="8154966188085545556">"अलीकडील मेसेज, मिस्ड कॉल आणि स्टेटस अपडेट पहा"</string> <string name="people_tile_title" msgid="6589377493334871272">"संभाषण"</string> <string name="paused_by_dnd" msgid="7856941866433556428">"व्यत्यय आणू नका द्वारे थांबवले गेले"</string> <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> यांनी मेसेज पाठवला: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"उघडण्यासाठी फिंगरप्रिंट वापरा"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ऑथेंटिकेशन आवश्यक आहे. ऑथेंटिकेट करण्यासाठी फिंगरप्रिंट सेन्सरला स्पर्श करा."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फोन कॉल सुरू आहे"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा ऑटो-कनेक्ट होणार नाही"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"कोणतेही कनेक्शन नाही"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"इतर कोणतेही नेटवर्क उपलब्ध नाहीत"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"कोणतेही नेटवर्क उपलब्ध नाही"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"वाय-फाय"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्कचे तपशील"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"कनेक्ट करण्यासाठी नेटवर्कवर टॅप करा"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"नेटवर्क पाहण्यासाठी स्क्रीन अनलॉक करा"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्क शोधत आहे…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्कशी कनेक्ट करता आले नाही"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"सध्या वाय-फाय ऑटो-कनेक्ट होणार नाही"</string> + <string name="see_all_networks" msgid="3773666844913168122">"सर्व पहा"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क स्विच करण्यासाठी, इथरनेट केबल डिस्कनेक्ट करा"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिव्हाइसच्या अनुभवामध्ये सुधारणा करण्यासाठी, वाय-फाय बंद असले तरीही ॲप्स आणि सेवा या कधीही वाय-फाय नेटवर्क स्कॅन करू शकतात. तुम्ही हे वाय-फाय स्कॅनिंग सेटिंग्जमध्ये बदलू शकता. "<annotation id="link">"बदला"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index b7d0246c4095..7bc56237d5eb 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan mikrofon anda."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera anda."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera atau mikrofon anda."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Peranti"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Peranti lain"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Sudah dicas"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengecas"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kawalan pemberitahuan berkuasa"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Hidup"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Mati"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Hidup - Berasaskan wajah"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Dengan kawalan pemberitahuan berkuasa, anda boleh menetapkan tahap kepentingan dari 0 hingga 5 untuk pemberitahuan apl. \n\n"<b>"Tahap 5"</b>" \n- Tunjukkan pada bahagian atas senarai pemberitahuan \n- Benarkan gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 4"</b>" \n- Halang gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 3"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n\n"<b>"Tahap 2"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi dan bergetar \n\n"<b>"Tahap 1"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi atau bergetar \n- Sembunyikan daripada skrin kunci dan bar status \n- Tunjukkan di bahagian bawah senarai pemberitahuan \n\n"<b>"Tahap 0"</b>" \n- Sekat semua pemberitahuan daripada apl"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Pemberitahuan"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Anda tidak akan melihat pemberitahuan ini lagi"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan cap jari untuk membuka"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Pengesahan diperlukan. Sentuh penderia cap jari untuk pengesahan."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telefon yang sedang berjalan"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data mudah alih tidak akan autosambung"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tiada sambungan"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Tiada rangkaian lain yang tersedia"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Tiada rangkaian tersedia"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Butiran rangkaian"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ketik rangkaian untuk membuat sambungan"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Buka kunci untuk melihat rangkaian"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Mencari rangkaian…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Gagal menyambung kepada rangkaian"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tidak akan disambungkan secara automatik buat masa ini"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Untuk menukar rangkaian, putuskan sambungan ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Untuk meningkatkan pengalaman peranti, apl dan perkhidmatan masih dapat melakukan imbasan untuk mengesan rangkaian Wi-Fi pada bila-bila masa, meskipun apabila Wi-Fi dimatikan. Anda boleh menukar tetapan ini dalam tetapan pengimbasan Wi-Fi. "<annotation id="link">"Tukar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 81d168b79065..c864587f7016 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"၎င်းက သင့်မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"၎င်းက သင့်ကင်မရာသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"၎င်းက သင့်ကင်မရာ (သို့) မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"စက်"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"အခြားစက်ပစ္စည်း"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"အားသွင်းပြီး"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"အားသွင်းနေ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ဖွင့်"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ပိတ်"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ဖွင့် - မျက်နှာအခြေခံ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများကိုအသုံးပြုပြီး အက်ပ်တစ်ခု၏ အကြောင်းကြားချက် အရေးပါမှု ၀ မှ ၅ အထိသတ်မှတ်ပေးနိုင်သည်။ \n\n"<b>"အဆင့် ၅"</b>" \n- အကြောင်းကြားချက်စာရင်း၏ ထိပ်ဆုံးတွင် ပြသည် \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်းကို ခွင့်ပြုသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၄"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၃"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n\n"<b>"အဆင့် ၂"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n\n"<b>"အဆင့် ၁"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n- လော့ခ်ချထားသည့် မျက်နှာပြင်နှင့် အခြေအနေဘားတန်းတို့တွင် မပြပါ \n- အကြောင်းကြားချက်စာရင်း အောက်ဆုံးတွင်ပြသည် \n\n"<b>"အဆင့် ၀"</b>" \n- အက်ပ်မှ အကြောင်းကြားချက်များ အားလုံးကို ပိတ်ဆို့သည်"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"အကြောင်းကြားချက်များ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ဤအကြောင်းကြားချက်များကို မြင်ရတော့မည် မဟုတ်ပါ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ဖွင့်ရန် လက်ဗွေကို သုံးပါ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"အထောက်အထားစိစစ်ခြင်း လိုအပ်သည်။ အထောက်အထားစိစစ်ရန် လက်ဗွေ အာရုံခံကိရိယာကို ထိပါ။"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"လက်ရှိ ဖုန်းခေါ်ဆိုမှု"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"မိုဘိုင်းဒေတာက အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ချိတ်ဆက်မှုမရှိပါ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"အခြားကွန်ရက်များ မရှိပါ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ကွန်ရက်များ မရှိပါ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ကွန်ရက် အသေးစိတ်များ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ချိတ်ဆက်ရန် ကွန်ရက်ကို တို့ပါ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ကွန်ရက်များကြည့်ရန် ဖွင့်ပါ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ကွန်ရက်များကို ရှာဖွေနေသည်…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ကွန်ရက်သို့ ချိတ်ဆက်၍မရပါ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi က လောလောဆယ် အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string> + <string name="see_all_networks" msgid="3773666844913168122">"အားလုံးကြည့်ရန်"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ကွန်ရက်ပြောင်းရန် အီသာနက်ကို ချိတ်ဆက်မှုဖြုတ်ပါ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"စက်ပစ္စည်းကို ပိုမိုကောင်းမွန်စွာ အသုံးပြုနိုင်ရန် Wi-Fi ပိတ်ထားသည့်တိုင် အက်ပ်နှင့် ဝန်ဆောင်မှုများက Wi-Fi ကွန်ရက်များကို အချိန်မရွေး စကင်ဖတ်နိုင်သည်။ ၎င်းကို Wi-Fi ရှာဖွေခြင်း ဆက်တင်များတွင် ပြောင်းနိုင်သည်။ "<annotation id="link">"ပြောင်းရန်"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 360c58b9e2dc..628b6a99883d 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke mikrofonen."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet eller mikrofonen."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Annen enhet"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Oppladet"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Lader"</string> @@ -601,8 +602,8 @@ <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatisk medieteksting"</string> <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Verktøytips for teksting"</string> <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlegg med teksting"</string> - <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"slå på"</string> - <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"slå av"</string> + <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivér"</string> + <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string> <string name="accessibility_output_chooser" msgid="7807898688967194183">"Bytt enhet for lydutgang"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Appen er festet"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den."</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Effektive varselinnstillinger"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"På"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Av"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"På – ansiktsbasert"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Varsler"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Du ser ikke disse varslene lenger"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Bruk fingeravtrykk for å åpne"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobildata kobler ikke til automatisk"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen tilkobling"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ingen andre nettverk er tilgjengelige"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Ingen nettverk er tilgjengelige"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Nettverksdetaljer"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Trykk på et nettverk for å koble til"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås opp for å se nettverk"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søker etter nettverk …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kunne ikke koble til nettverket"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi kobles ikke til automatisk inntil videre"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"For å bytte nettverk, koble fra Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"For å forbedre brukeropplevelsen på enheten kan apper og tjenester søke etter Wi-Fi-nettverk når som helst – også når Wi-Fi er slått av. Du kan endre dette i innstillingene for Wi-Fi-skanning. "<annotation id="link">"Bytt"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index e5787b578430..c6dfb37ce848 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"यसो गर्नुभयो भने माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"यसो गर्नुभयो भने क्यामेरा प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"यसो गर्नुभयो भने क्यामेरा वा माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"यन्त्र"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"अर्को डिभाइड"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज भयो"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हुँदै छ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"सशक्त सूचना नियन्त्रण"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"अन छ"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"अफ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"अन छ - अनुहारमा आधारित"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- एपका सबै सूचनाहरूलाई रोक्ने"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"सूचनाहरू"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"तपाईं अब उप्रान्त यी सूचनाहरू देख्नु हुने छैन"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"फिंगरप्रिन्ट प्रयोग गरी खोल्नुहोस्"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि गर्नु पर्ने हुन्छ। पुष्टि गर्न फिंगरप्रिन्ट सेन्सर छुनुहोस्।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"जारी फोन कल"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा स्वतः कनेक्ट हुँदैन"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"इन्टरनेट छैन"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"अन्य नेटवर्क उपलब्ध छैनन्"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"कुनै पनि नेटवर्क उपलब्ध छैन"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्कसम्बन्धी विवरण"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"इन्टरनेट कनेक्ट गर्न कुनै नेटवर्कमा ट्याप गर्नुहोस्"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"नेटवर्कहरू हेर्न आफ्नो स्क्रिन अनलक गर्नुहोस्"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्कहरू खोजिँदै छन्…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्कमा कनेक्ट गर्न सकिएन"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"केही समयका लागि Wi-Fi स्वतः कनेक्ट हुँदैन"</string> + <string name="see_all_networks" msgid="3773666844913168122">"सबै नेटवर्क हेर्नुहोस्"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क बदल्न इथरनेट डिस्कनेक्ट गर्नुहोस्"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिभाइस प्रयोगको अनुभवमा गुणस्तर सुधार गर्न, एप तथा सेवाहरूले अझै पनि जुनसुकै बेला (Wi‑Fi अफ भएका बेलामा पनि) Wi‑Fi नेटवर्क खोज्न सक्छन्। तपाईं यसलाई Wi‑Fi स्क्यानिङका सेटिङमा गई परिवर्तन गर्न सक्नुहुन्छ। "<annotation id="link">"बदल्नुहोस्"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml index 461505f12ce6..ffcc3a821d36 100644 --- a/packages/SystemUI/res/values-night/styles.xml +++ b/packages/SystemUI/res/values-night/styles.xml @@ -48,4 +48,16 @@ <item name="android:windowLightStatusBar">false</item> </style> + <style name="TextAppearance.InternetDialog.Active"> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + <item name="android:textSize">16sp</item> + <item name="android:textColor">@color/connected_network_primary_color</item> + <item name="android:textDirection">locale</item> + </style> + + <style name="TextAppearance.InternetDialog.Secondary.Active"> + <item name="android:textSize">14sp</item> + <item name="android:textColor">@color/connected_network_secondary_color</item> + </style> + </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 7d75b6e20a1e..00debe8d4112 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je microfoon te gebruiken."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera te gebruiken."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera of microfoon te gebruiken."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander apparaat"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opgeladen"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Opladen"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Beheeropties voor meldingen met betrekking tot stroomverbruik"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aan"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Uit"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aan: op basis van gezicht"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Met beheeropties voor meldingen met betrekking tot stroomverbruik kun je een belangrijkheidsniveau van 0 tot 5 instellen voor de meldingen van een app. \n\n"<b>"Niveau 5"</b>" \n- Bovenaan de lijst met meldingen tonen \n- Onderbreking op volledig scherm toestaan \n- Altijd korte weergave \n\n"<b>"Niveau 4"</b>" \n- Geen onderbreking op volledig scherm \n- Altijd korte weergave \n\n"<b>"Niveau 3"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n\n"<b>"Niveau 2"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n\n"<b>"Niveau 1"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n- Verbergen op vergrendelscherm en statusbalk \n- Onderaan de lijst met meldingen tonen \n\n"<b>"Niveau 0"</b>" \n- Alle meldingen van de app blokkeren"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Meldingen"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Je ziet deze meldingen niet meer"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om te openen"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Verificatie vereist. Raak de vingerafdruksensor aan om de verificatie uit te voeren."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Actief telefoongesprek"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data maakt niet automatisch verbinding"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen andere netwerken beschikbaar"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Geen netwerken beschikbaar"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Netwerkgegevens"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tik op een netwerk om verbinding te maken"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ontgrendel het scherm om netwerken te bekijken"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Netwerken zoeken…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kan geen verbinding maken met het netwerk"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wifi maakt momenteel niet automatisch verbinding"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Alles tonen"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Verbreek de ethernetverbinding om van netwerk te wisselen"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Apps en services kunnen nog steeds op elk moment scannen op wifi-netwerken, zelfs als wifi uitstaat, om de apparaatfunctionaliteit te verbeteren. Je kunt dit aanpassen in de instellingen voor wifi-scannen. "<annotation id="link">"Wijzigen"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index ee524bf2e3c8..a1e7013fec73 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/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> @@ -132,7 +133,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ଆକ୍ସେସିବିଲିଟୀ"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"ସ୍କ୍ରୀନ୍କୁ ଘୁରାନ୍ତୁ"</string> <string name="accessibility_recent" msgid="901641734769533575">"ଓଭରଭିଉ"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"ସନ୍ଧାନ କରନ୍ତୁ"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"କ୍ୟାମେରା"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍ ସହାୟକ"</string> @@ -247,7 +248,7 @@ <skip /> <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"ବିଜ୍ଞପ୍ତି ଖାରଜ କରାଗଲା।"</string> <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍।"</string> - <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ଦ୍ରୁତ ସେଟିଂସ୍।"</string> + <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string> <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍ ସ୍କ୍ରୀନ୍।"</string> <string name="accessibility_desc_settings" msgid="6728577365389151969">"ସେଟିଂସ୍"</string> <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀ"</string> @@ -434,14 +435,14 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ଆପଣଙ୍କ ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ଆପଣଙ୍କ କ୍ୟାମେରା କିମ୍ବା ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ଡିଭାଇସ୍"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ଅନ୍ୟ ଡିଭାଇସ୍"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ଚାର୍ଜ ହୋଇଗଲା"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ଚାର୍ଜ କରାଯାଉଛି"</string> <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବାକୁ ଆଉ <xliff:g id="CHARGING_TIME">%s</xliff:g> ଅଛି"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ଚାର୍ଜ ହେଉନାହିଁ"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"ନେଟ୍ୱର୍କ\nମନିଟର୍ କରାଯାଇପାରେ"</string> - <string name="description_target_search" msgid="3875069993128855865">"Search"</string> + <string name="description_target_search" msgid="3875069993128855865">"ସନ୍ଧାନ କରନ୍ତୁ"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ପାଇଁ ଉପରକୁ ସ୍ଲାଇଡ୍ କରନ୍ତୁ।"</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ପାଇଁ ବାମକୁ ସ୍ଲାଇଡ୍ କରନ୍ତୁ"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ଆଲାର୍ମ, ରିମାଇଣ୍ଡର୍, ଇଭେଣ୍ଟ ଏବଂ ଆପଣ ନିର୍ଦ୍ଦିଷ୍ଟ କରିଥିବା କଲର୍ଙ୍କ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> @@ -658,7 +659,7 @@ <string name="system_ui_tuner" msgid="1471348823289954729">"ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍"</string> <string name="show_battery_percentage" msgid="6235377891802910455">"ଏମ୍ବେଡ୍ ହୋଇଥିବା ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଦେଖାନ୍ତୁ"</string> <string name="show_battery_percentage_summary" msgid="9053024758304102915">"ଚାର୍ଜ ହେଉନଥିବାବେଳେ ଷ୍ଟାଟସ୍ ବାର୍ ଆଇକନ୍ ଭିତରେ ବ୍ୟାଟେରୀ ସ୍ତର ଶତକଡ଼ା ଦେଖାନ୍ତୁ"</string> - <string name="quick_settings" msgid="6211774484997470203">"ଦ୍ରୁତ ସେଟିଂସ୍"</string> + <string name="quick_settings" msgid="6211774484997470203">"କ୍ୱିକ୍ ସେଟିଂସ୍"</string> <string name="status_bar" msgid="4357390266055077437">"ଷ୍ଟାଟସ୍ ବାର୍"</string> <string name="overview" msgid="3522318590458536816">"ଅବଲୋକନ"</string> <string name="demo_mode" msgid="263484519766901593">"ସିଷ୍ଟମ୍ UI ଡେମୋ ମୋଡ୍"</string> @@ -683,7 +684,7 @@ <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string> <string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ହେଲେ"</string> <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ବେଳେ"</string> - <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"ଦ୍ରୁତ ସେଟିଙ୍ଗ, <xliff:g id="TITLE">%s</xliff:g>।"</string> + <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"କ୍ୱିକ୍ ସେଟିଂସ୍, <xliff:g id="TITLE">%s</xliff:g>।"</string> <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"ହଟସ୍ପଟ୍"</string> <string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string> <string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ଚାଲୁ ଅଛି"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ବନ୍ଦ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ଚାଲୁ ଅଛି - ଫେସ-ଆଧାରିତ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍ରେ, ଆପଣ ଏକ ଆପ୍ ବିଜ୍ଞପ୍ତି ପାଇଁ 0 ରୁ 5 ଗୁରୁତ୍ୱ ସ୍ତର ସେଟ୍ କରିହେବେ। \n\n"<b>"ସ୍ତର 5"</b>" \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ଶୀର୍ଷରେ ଦେଖାନ୍ତୁ \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 4"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 3"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 2"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 1"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n- ଲକ୍ ସ୍କ୍ରୀନ୍ ଓ ଷ୍ଟାଟସ୍ ବାର୍ରୁ ଲୁଚାନ୍ତୁ \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ନିମ୍ନରେ ଦେଖାନ୍ତୁ \n\n"<b>"ସ୍ତର 0"</b>" \n- ଆପରୁ ସମସ୍ତ ବିଜ୍ଞପ୍ତି ବ୍ଲକ୍ କରନ୍ତୁ"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ବିଜ୍ଞପ୍ତି"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଆପଣ ଆଉ ଦେଖିବାକୁ ପାଇବେନାହିଁ।"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ଖୋଲିବାକୁ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ପ୍ରମାଣୀକରଣ ଆବଶ୍ୟକ। ପ୍ରମାଣୀକରଣ କରିବାକୁ ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ଚାଲୁଥିବା ଫୋନ୍ କଲ୍"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ମୋବାଇଲ ଡାଟା ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ସଂଯୋଗ ନାହିଁ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ଅନ୍ୟ କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"ୱାଇ-ଫାଇ"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ନେଟୱାର୍କ ବିବରଣୀ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ସଂଯୋଗ କରିବାକୁ ଏକ ନେଟୱାର୍କରେ ଟାପ୍ କରନ୍ତୁ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ନେଟୱାର୍କଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ଅନଲକ୍ କରନ୍ତୁ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ନେଟୱାର୍କଗୁଡ଼ିକ ସନ୍ଧାନ କରାଯାଉଛି…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ନେଟୱାର୍କକୁ ସଂଯୋଗ କରିବାରେ ବିଫଳ ହୋଇଛି"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ବର୍ତ୍ତମାନ ପାଇଁ ୱାଇ-ଫାଇ ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ସବୁ ଦେଖନ୍ତୁ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ନେଟୱାର୍କ ସ୍ୱିଚ୍ କରିବାକୁ, ଇଥରନେଟ୍ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ଡିଭାଇସ ଅନୁଭୂତିକୁ ଉନ୍ନତ କରିବା ପାଇଁ, ୱାଇ-ଫାଇ ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପ ଓ ସେବାଗୁଡ଼ିକ ଏବେ ବି ଯେ କୌଣସି ସମୟରେ ୱାଇ-ଫାଇ ନେଟୱାର୍କ ପାଇଁ ସ୍କାନ କରିପାରିବ। ଆପଣ ଏହାକୁ ୱାଇ-ଫାଇ ସ୍କାନିଂ ସେଟିଂସରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ। "<annotation id="link">"ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index d68ab4fe347a..0c9dd95ec219 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ਹੋਰ ਡੀਵਾਈਸ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ਚਾਰਜ ਹੋਇਆ"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ਚਾਰਜ ਕਰ ਰਿਹਾ ਹੈ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲ"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ਚਾਲੂ"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ਬੰਦ"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ਚਾਲੂ ਹੈ - ਚਿਹਰਾ-ਆਧਾਰਿਤ"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲਾਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"ਸੂਚਨਾਵਾਂ"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਦਿਖਾਈ ਨਹੀਂ ਦੇਣਗੀਆਂ"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ਖੋਲ੍ਹਣ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ। ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪਰਸ਼ ਕਰੋ।"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ਜਾਰੀ ਫ਼ੋਨ ਕਾਲ"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ਮੋਬਾਈਲ ਡਾਟਾ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ਕੋਈ ਹੋਰ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ਕੋਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"ਵਾਈ-ਫਾਈ"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ਨੈੱਟਵਰਕ ਵੇਰਵੇ"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"ਕਨੈਕਟ ਕਰਨ ਲਈ ਕਿਸੇ ਨੈੱਟਵਰਕ \'ਤੇ ਟੈਪ ਕਰੋ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ਨੈੱਟਵਰਕ ਖੋਜੇ ਜਾ ਰਹੇ ਹਨ…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ਫ਼ਿਲਹਾਲ ਵਾਈ-ਫਾਈ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ਸਭ ਦੇਖੋ"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਬਦਲਣ ਲਈ, ਈਥਰਨੈੱਟ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ਡੀਵਾਈਸ ਦੇ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਕਿਸੇ ਵੀ ਸਮੇਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਭਾਵੇਂ ਵਾਈ-ਫਾਈ ਬੰਦ ਹੀ ਕਿਉਂ ਨਾ ਹੋਵੇ। ਤੁਸੀਂ ਇਸ ਨੂੰ ਵਾਈ‑ਫਾਈ ਸਕੈਨਿੰਗ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਬਦਲ ਸਕਦੇ ਹੋ। "<annotation id="link">"ਬਦਲੋ"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 9aade18169ad..9d7936887c6b 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z mikrofonu."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu lub mikrofonu."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Urządzenie"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Inne urządzenie"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Naładowana"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ładowanie"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Zaawansowane ustawienia powiadomień"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Wł."</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Wył."</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Włączono – na podstawie twarzy"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Dzięki zaawansowanym ustawieniom możesz określić poziom ważności powiadomień z aplikacji w skali od 0 do 5. \n\n"<b>"Poziom 5"</b>" \n– Pokazuj u góry listy powiadomień \n– Zezwalaj na powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 4"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 3"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n\n"<b>"Poziom 2"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n\n"<b>"Poziom 1"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n– Ukrywaj na ekranie blokady i pasku stanu \n– Pokazuj u dołu listy powiadomień \n\n"<b>"Poziom 0"</b>" \n– Blokuj wszystkie powiadomienia aplikacji"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Powiadomienia"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Te powiadomienia nie będą już wyświetlane"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"By otworzyć, użyj odcisku palca"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Wymagane uwierzytelnienie. Dotknij czytnika liniii papilarnych, by uwierzytelnić."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktywne połączenie"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna transmisja danych nie połączy się automatycznie"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Brak połączenia"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Brak innych dostępnych sieci"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Brak dostępnych sieci"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Szczegóły sieci"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Kliknij sieć, aby połączyć"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odblokuj, by wyświetlić sieci"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Szukam sieci…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nie udało się połączyć z siecią"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi nie będzie na razie włączać się automatycznie"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Pokaż wszystko"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Aby przełączać sieci, odłącz Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Aby zapewnić Ci większy komfort korzystania z urządzenia, aplikacje i usługi mogą nadal wyszukiwać sieci Wi-Fi w pobliżu nawet wtedy, gdy Wi-Fi jest wyłączone. Możesz to zmienić w ustawieniach skanowania Wi-Fi. "<annotation id="link">"Zmień"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index cab482ae56fd..ac1bd1164481 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar seu microfone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string> @@ -591,12 +592,12 @@ <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string> <string name="hidden_notifications_title" msgid="1782412844777612795">"Receba notificações mais rápido"</string> <string name="hidden_notifications_text" msgid="5899627470450792578">"Veja-as antes de desbloquear"</string> - <string name="hidden_notifications_cancel" msgid="4805370226181001278">"Não, obrigado"</string> + <string name="hidden_notifications_cancel" msgid="4805370226181001278">"Agora não"</string> <string name="hidden_notifications_setup" msgid="2064795578526982467">"Configurar"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="volume_zen_end_now" msgid="5901885672973736563">"Desativar agora"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string> - <string name="accessibility_volume_expand" msgid="7653070939304433603">"Expandir"</string> + <string name="accessibility_volume_expand" msgid="7653070939304433603">"Abrir"</string> <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Recolher"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string> <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Dica de legenda"</string> @@ -616,7 +617,7 @@ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Para liberar o app, toque nos botões \"Voltar\" e home e os mantenha pressionados"</string> <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Para liberar o app, deslize para cima e mantenha a tela pressionada"</string> <string name="screen_pinning_positive" msgid="3285785989665266984">"Entendi"</string> - <string name="screen_pinning_negative" msgid="6882816864569211666">"Não, obrigado"</string> + <string name="screen_pinning_negative" msgid="6882816864569211666">"Agora não"</string> <string name="screen_pinning_start" msgid="7483998671383371313">"App fixado"</string> <string name="screen_pinning_exit" msgid="4553787518387346893">"App liberado"</string> <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de ativação/desativação de notificações"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ativada"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desativado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada (reconhecimento facial)"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificações"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Você deixará de ver essas notificações"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nenhuma rede disponível"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque em uma rede para se conectar"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Procurando redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Falha ao conectar à rede"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A conexão automática ao Wi-Fi ficará indisponível"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desconecte o cabo Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência no dispositivo, os apps e serviços ainda podem procurar redes Wi-Fi a qualquer momento, mesmo quando o Wi-Fi estiver desativado. Você pode mudar essa opção nas configurações de busca por Wi-Fi. "<annotation id="link">"Mudar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index eec34684ff4a..469170e1d363 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar o seu microfone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara ou microfone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"A carregar"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controlos de notificações do consumo de energia"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ativado"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desativado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada – Com base no rosto"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Com os controlos de notificações do consumo de energia, pode definir um nível de importância de 0 a 5 para as notificações de aplicações. \n\n"<b>"Nível 5"</b>" \n- Mostrar no início da lista de notificações \n- Permitir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre \n\n"<b>"Nível 4"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre\n\n"<b>"Nível 3"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n\n"<b>"Nível 2"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n- Ocultar do ecrã de bloqueio e da barra de estado \n- Mostrar no fim da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações da app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificações"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Nunca mais verá estas notificações."</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilize a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação necessária. Toque no sensor de impressões digitais para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica em curso"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Não é efetuada ligação de dados móveis automática"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem ligação"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Sem redes disponíveis"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque numa rede para estabelecer ligação"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"A procurar redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Não foi possível estabelecer ligação à rede"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por agora, o Wi-Fi não irá estabelecer lig. automaticamente"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Veja tudo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desligue a Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência do dispositivo, as apps e os serviços podem continuar a procurar redes Wi-Fi em qualquer altura, mesmo quando o Wi-Fi está desativado. Pode alterar esta opção nas definições de procura de Wi-Fi. "<annotation id="link">"Alterar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index cab482ae56fd..ac1bd1164481 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar seu microfone."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string> @@ -591,12 +592,12 @@ <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string> <string name="hidden_notifications_title" msgid="1782412844777612795">"Receba notificações mais rápido"</string> <string name="hidden_notifications_text" msgid="5899627470450792578">"Veja-as antes de desbloquear"</string> - <string name="hidden_notifications_cancel" msgid="4805370226181001278">"Não, obrigado"</string> + <string name="hidden_notifications_cancel" msgid="4805370226181001278">"Agora não"</string> <string name="hidden_notifications_setup" msgid="2064795578526982467">"Configurar"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="volume_zen_end_now" msgid="5901885672973736563">"Desativar agora"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string> - <string name="accessibility_volume_expand" msgid="7653070939304433603">"Expandir"</string> + <string name="accessibility_volume_expand" msgid="7653070939304433603">"Abrir"</string> <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Recolher"</string> <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string> <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Dica de legenda"</string> @@ -616,7 +617,7 @@ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Para liberar o app, toque nos botões \"Voltar\" e home e os mantenha pressionados"</string> <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Para liberar o app, deslize para cima e mantenha a tela pressionada"</string> <string name="screen_pinning_positive" msgid="3285785989665266984">"Entendi"</string> - <string name="screen_pinning_negative" msgid="6882816864569211666">"Não, obrigado"</string> + <string name="screen_pinning_negative" msgid="6882816864569211666">"Agora não"</string> <string name="screen_pinning_start" msgid="7483998671383371313">"App fixado"</string> <string name="screen_pinning_exit" msgid="4553787518387346893">"App liberado"</string> <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de ativação/desativação de notificações"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ativada"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Desativado"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada (reconhecimento facial)"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificações"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Você deixará de ver essas notificações"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nenhuma rede disponível"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque em uma rede para se conectar"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Procurando redes…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Falha ao conectar à rede"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A conexão automática ao Wi-Fi ficará indisponível"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desconecte o cabo Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência no dispositivo, os apps e serviços ainda podem procurar redes Wi-Fi a qualquer momento, mesmo quando o Wi-Fi estiver desativado. Você pode mudar essa opção nas configurações de busca por Wi-Fi. "<annotation id="link">"Mudar"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 1e30ea713210..aa174d41dc00 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi microfonul."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera sau microfonul."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispozitiv"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Alt dispozitiv"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comutați secțiunea Recente"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Încărcată"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Se încarcă"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Comenzi de gestionare a notificărilor"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Activate"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Dezactivate"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activată – În funcție de chip"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Folosind comenzile de gestionare a notificărilor, puteți să setați un nivel de importanță de la 0 la 5 pentru notificările unei aplicații. \n\n"<b>"Nivelul 5"</b>" \n– Se afișează la începutul listei de notificări \n– Se permite întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 4"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 3"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n\n"<b>"Nivelul 2"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n\n"<b>"Nivelul 1"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n– Se ascunde în ecranul de blocare și în bara de stare \n– Se afișează la finalul listei de notificări \n\n"<b>"Nivelul 0"</b>" \n– Se blochează toate notificările din aplicație"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Notificări"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Nu veți mai vedea aceste notificări"</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Folosiți amprenta ca să deschideți"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentificare obligatorie. Atingeți senzorul de amprentă pentru a vă autentifica."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Apel telefonic în desfășurare"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nu se conectează automat la date mobile"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nicio conexiune"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nu sunt disponibile alte rețele"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nicio rețea disponibilă"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detalii despre rețea"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Atingeți o rețea pentru a vă conecta"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Deblocați pentru a vedea rețelele"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Se caută rețele…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nu s-a realizat conexiunea la rețea"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Deocamdată, Wi-Fi nu se poate conecta automat"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Afișează-le pe toate"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pentru a schimba rețeaua, deconectați ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pentru a îmbunătăți experiența cu dispozitivul, aplicațiile și serviciile pot să caute în continuare rețele Wi‑Fi chiar și atunci când conexiunea Wi-Fi este dezactivată. Puteți să schimbați acest aspect din setările pentru căutarea de rețele Wi-Fi. "<annotation id="link">"Schimbați"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 99465d54e124..69f8c97f2fe9 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование микрофона."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры или микрофона."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Другое устройство"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Батарея заряжена"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядка батареи"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Расширенное управление уведомлениями"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Включено"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Отключено"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Включить (на основе распознавания лиц)"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n"<b>"Уровень 5"</b>\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"<b></b>\n"‒ Блокировать все уведомления приложения."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Уведомления"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Эти уведомления отключены."</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Используйте отпечаток пальца для входа."</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Требуется аутентификация. Приложите палец к сканеру отпечатков."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущий вызов"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Без автоподключения к мобильному интернету"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нет подключения к интернету"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нет других доступных сетей"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Нет доступных сетей"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Сведения о сети"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Выберите сеть, чтобы подключиться"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Разблокируйте, чтобы посмотреть сети Wi-Fi."</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Поиск сетей…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не удалось подключиться к сети"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Подключение по Wi-Fi не установится автоматически."</string> + <string name="see_all_networks" msgid="3773666844913168122">"Показать все"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Чтобы переключиться между сетями, отключите кабель Ethernet."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Чтобы улучшать работу устройства, приложения и сервисы могут искать беспроводные сети в любое время, даже если вы отключили Wi‑Fi. Чтобы запретить это, отключите поиск сетей Wi‑Fi. "<annotation id="link">"Открыть настройки"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 6ea2a0dd5d7a..f6fd853170f6 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"මෙය ඔබගේ මයික්රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"මෙය ඔබගේ කැමරාව භාවිතා කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"මෙය ඔබගේ කැමරාව හෝ මයික්රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"උපාංගය"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"වෙනත් උපාංගය"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"අරෝපිතයි"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ආරෝපණය වෙමින්"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"බල දැනුම්දීම් පාලන"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ක්රියාත්මකයි"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ක්රියාවිරහිතයි"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ක්රියාත්මකයි - මුහුණ-පදනම්ව"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"බල දැනුම්දීම් පාලන සමගින්, ඔබට යෙදුමක දැනුම්දීම් සඳහා වැදගත්කම 0 සිට 5 දක්වා සැකසිය හැකිය. \n\n"<b>"5 මට්ටම"</b>" \n- දැනුම්දීම් ලැයිස්තුවේ ඉහළින්ම පෙන්වන්න \n- පූර්ණ තිර බාධාවට ඉඩ දෙන්න \n- සැම විට එබී බලන්න \n\n"<b>"4 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- සැම විට එබී බලන්න \n\n"<b>"3 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n\n"<b>"2 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n\n"<b>"1 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n- අගුලු තිරය සහ තත්ත්ව තීරුව වෙතින් සඟවන්න \n- දැනුම්දීම් ලැයිස්තුවේ පහළින්ම පෙන්වන්න \n\n"<b>"0 මට්ටම"</b>" \n- යෙදුම වෙතින් වන සියලු දැනුම් දීම් සඟවන්න."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"දැනුම් දීම්"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ඔබට තවදුරටත් මෙම දැනුම්දීම් නොදකිනු ඇත"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"විවෘත කිරීමට ඇඟිලි සලකුණ භාවිත කරන්න"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්යාපනය අවශ්යයි. සත්යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්රියාත්මක වන දුරකථන ඇමතුම"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"ජංගම දත්ත ස්වංක්රියව සම්බන්ධ නොවනු ඇත"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"සම්බන්ධතාවයක් නැත"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ලබා ගත හැකි වෙනත් ජාල නැත"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ජාලය නොතිබේ"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"ජාල විස්තර"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"සම්බන්ධ වීමට ජාලයක් තට්ටු කරන්න"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ජාල බැලීමට අගුලු හරින්න"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ජාල සඳහා සොයමින්…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ජාලය වෙත සම්බන්ධ වීම අසාර්ථක විය"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi දැනට ස්වයං-සබැඳි නොවනු ඇත"</string> + <string name="see_all_networks" msgid="3773666844913168122">"සියල්ල බලන්න"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ජාල මාරු කිරීමට, ඊතර්නෙට් විසන්ධි කරන්න"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"උපාංග අත්දැකීම වැඩි දියුණු කිරිමට, Wi‑Fi ක්රියාවිරහිත විට පවා, ඕනෑම අවස්ථාවක Wi‑Fi ජාල සඳහා ස්කෑන් කිරීමට යෙදුම් සහ සේවාවලට හැකිය. ඔබට මෙය Wi‑Fi ස්කෑන් කිරීමේ සැකසීම් තුළ වෙනස් කළ හැකිය. "<annotation id="link">"වෙනස් කරන්න"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 399b9797d21f..c296666b6249 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať mikrofón."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát alebo mikrofón."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Zariadenie"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Iné zariadenie"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabitá"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíja sa"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ovládacie prvky zobrazovania upozornení"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Zapnuté"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Vypnuté"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Zapnuté – podľa tváre"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Pomocou ovládacích prvkov zobrazovania upozornení môžete nastaviť pre upozornenia aplikácie úroveň dôležitosti od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazovať v hornej časti zoznamu upozornení. \n– Povoliť prerušenia na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 4"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 3"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n\n"<b>"Úroveň 2"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n\n"<b>"Úroveň 1"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n– Skryť na uzamknutej obrazovke a v stavovom riadku. \n– Zobraziť v dolnej časti zoznamu upozornení. \n\n"<b>"Úroveň 0"</b>" \n– Blokovať všetky upozornenia z aplikácie."</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Upozornenia"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Tieto upozornenia sa už nebudú zobrazovať"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorte odtlačkom prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vyžaduje sa overenie. Dotknite sa senzora odtlačkov prstov."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Prebiehajúci telefonický hovor"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Automatické pripojenie cez mobilné dáta nefunguje"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bez pripojenia"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nie sú k dispozícii žiadne ďalšie siete"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nie sú k dispozícii žiadne siete"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Podrobnosti siete"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ak sa chcete pripojiť, klepnite na sieť"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odomknutím si zobrazte siete"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Vyhľadávajú sa siete…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nepodarilo sa pripojiť k sieti"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi sa teraz automaticky nepripojí"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Zobraziť všetko"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ak chcete prepnúť siete, odpojte ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Aplikácie a služby môžu kedykoľvek vyhľadávať siete Wi‑Fi (a to aj vtedy, keď je pripojenie Wi‑Fi vypnuté), čím zlepšujú prostredie v zariadení. Môžete to zmeniť v nastaveniach vyhľadávania sietí Wi‑Fi. "<annotation id="link">"Zmeniť"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 0c93bced9f41..c2598211981e 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo mikrofona."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata ali mikrofona."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Naprava"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Druga naprava"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Baterija napolnjena"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Polnjenje"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrolniki za pomembnost obvestil"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Vklopljeno"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Izklopljeno"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Vklopljeno – na podlagi obraza"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"S kontrolniki za pomebnost obvestila je mogoče za obvestila aplikacije nastaviti stopnjo pomembnosti od 0 do 5. \n\n"<b>"Stopnja 5"</b>" \n– Prikaz na vrhu seznama obvestil \n– Omogočanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 4"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 3"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n\n"<b>"Stopnja 2"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n\n"<b>"Stopnja 1"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n– Skrivanje na zaklenjenem zaslonu in v vrstici stanja \n– Prikaz na dnu seznama obvestil \n\n"<b>"Stopnja 0"</b>" \n– Blokiranje vseh obvestil aplikacije"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Obvestila"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Ta obvestila ne bodo več prikazana"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Odprite s prstnim odtisom"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Zahtevano je preverjanje pristnosti. Za preverjanje pristnosti se dotaknite tipala prstnih odtisov."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Poteka klic"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna podatkovna povezava ne bo samodejna."</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ni povezave"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nobeno drugo omrežje ni na voljo"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Na voljo ni nobeno omrežje"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Podatki o omrežju"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Za vzpostavitev povezave se dotaknite omrežja."</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odklenite za ogled omrežij"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Iskanje omrežij …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Vzpostavljanje povezave z omrežjem ni uspelo."</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Vmesnik Wi-Fi trenutno ne bo samodejno vzpostavil povezave."</string> + <string name="see_all_networks" msgid="3773666844913168122">"Prikaz vseh omrežij"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Če želite preklopiti omrežje, prekinite ethernetno povezavo."</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Za izboljšano izkušnjo pri uporabi naprave lahko aplikacije in storitve kadar koli iščejo omrežja Wi‑Fi, tudi ko je Wi‑Fi izklopljen. To lahko spremenite v nastavitvah iskanja omrežij Wi-Fi. "<annotation id="link">"Spremeni"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 7f101dbd3f57..cfd5573e8fd3 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -77,6 +77,7 @@ <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> + <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock është çaktivizuar"</string> <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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin mikrofonin tënd."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën tënde."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën ose mikrofonin tënd."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Pajisja"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Pajisje tjetër"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"I karikuar"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Po karikohet"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrollet e njoftimit të energjisë"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Aktiv"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Joaktiv"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktiv - Në bazë të fytyrës"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Me kontrollet e njoftimit të energjisë, mund të caktosh një nivel rëndësie nga 0 në 5 për njoftimet e një aplikacioni. \n\n"<b>"Niveli 5"</b>" \n- Shfaq në krye të listës së njoftimeve \n- Lejo ndërprerjen e ekranit të plotë \n- Gjithmonë shfaq shpejt \n\n"<b>"Niveli 4"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Gijthmonë shfaq shpejt \n\n"<b>"Niveli 3"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n\n"<b>"Niveli 2"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull dhe dridhje \n\n"<b>"Niveli 1"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull ose dridhje \n- Fshih nga ekrani i kyçjes dhe shiriti i statusit \n- Shfaq në fund të listës së njoftimeve \n\n"<b>"Niveli 0"</b>" \n- Blloko të gjitha njoftimet nga aplikacioni"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Njoftime"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Nuk do t\'i shikosh më këto njoftime"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Përdor gjurmën e gishtit për ta hapur"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kërkohet vërtetimi. Prek sensorin e gjurmës së gishtit për t\'u vërtetuar."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonatë në vazhdim"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Të dhënat celulare nuk do të lidhen automatikisht"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nuk ka lidhje"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nuk ofrohet asnjë rrjet tjetër"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Nuk ofrohet asnjë rrjet"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Detajet e rrjetit"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Trokit te një rrjet për t\'u lidhur"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Shkyçe për të parë rrjetet"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Po kërkon për rrjete…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Lidhja me rrjetin dështoi"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi nuk do të lidhet automatikisht për momentin"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Shiko të gjitha"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Për të ndërruar rrjetet, shkëput Ethernet-in"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Për të përmirësuar përvojën e pajisjes, aplikacionet dhe shërbimet mund të vazhdojnë të skanojnë për rrjete Wi-Fi në çdo kohë, edhe kur Wi-Fi është joaktiv. Mund ta ndryshosh këtë te cilësimet e skanimit të Wi-Fi. "<annotation id="link">"Ndrysho"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 1da42cfb2d3d..ea67c9e49437 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> @@ -436,7 +437,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење микрофона."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере или микрофона."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Уређај"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Други уређај"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Напуњена је"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Пуни се"</string> @@ -712,6 +713,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Напредне контроле за обавештења"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Укључено"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Искључено"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Укључено – на основу лица"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Помоћу напредних контрола за обавештења можете да подесите ниво важности од 0. до 5. за обавештења апликације. \n\n"<b>"5. ниво"</b>" \n– Приказују се у врху листе обавештења \n- Дозволи прекид режима целог екрана \n– Увек завируј \n\n"<b>"4. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Увек завируј \n\n"<b>"3. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n\n"<b>"2. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n\n"<b>"1. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n– Сакриј на закључаном екрану и статусној траци \n– Приказују се у дну листе обавештења \n\n"<b>"0. ниво"</b>" \n– Блокирај сва обавештења из апликације"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Обавештења"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Више нећете видети ова обавештења"</string> @@ -1013,7 +1015,7 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string> - <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Користи <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Користи: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно користио/ла <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(посао)"</string> <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонски позив"</string> @@ -1167,4 +1169,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Отворите помоћу отиска прста"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна је потврда идентитета. Додирните сензор за отисак прста да бисте потврдили идентитет."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Актуелни телефонски позив"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Није успело аутом. повезивање преко моб. података"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Веза није успостављена"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Није доступна ниједна друга мрежа"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Нема доступних мрежа"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Детаљи о мрежи"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Додирните мрежу да бисте се повезали"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Откључајте да бисте видели мреже"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Траже се мреже…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Повезивање са мрежом није успело"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi тренутно не може да се аутоматски повеже"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Погледајте све"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Да бисте променили мрежу, прекините етернет везу"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ради бољег доживљаја уређаја, апликације и услуге и даље могу да траже WiFi мреже у било ком тренутку, чак и када је WiFi искључен. То можете да промените у подешавањима WiFi скенирања. "<annotation id="link">"Промените"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 05aeffbc300d..a671d4c554cc 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda mikrofonen."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran eller mikrofonen."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Annan enhet"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laddat"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laddar"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Prioritetsinställningar för aviseringar"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Av"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"På"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"På – ansiktsbaserad"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Med aviseringsinställningarna kan du ange prioritetsnivå från 0 till 5 för aviseringar från en app. \n\n"<b>"Nivå 5"</b>" \n– Visa högst upp i aviseringslistan\n– Tillåt avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 4"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 3"</b>" \n- Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n\n"<b>"Nivå 2"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n\n"<b>"Nivå 1"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n– Visa inte på låsskärmen och i statusfältet \n– Visa längst ned i aviseringslistan \n\n"<b>"Nivå 0"</b>" \n– Blockera alla aviseringar från appen"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Aviseringar"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"De här aviseringarna visas inte längre"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Öppna med fingeravtryck"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering krävs. Identifiera dig genom att trycka på fingeravtryckssensorn."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående samtal"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Du ansluts inte till mobildata automatiskt"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen anslutning"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Inga andra nätverk är tillgängliga"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Det finns inga tillgängliga nätverk"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Nätverksinformation"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tryck på ett nätverk för att ansluta"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås upp för att visa nätverk"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Söker efter nätverk …"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Det gick inte att ansluta till nätverket"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Du ansluts inte till wifi automatiskt för närvarande"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Visa alla"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Koppla bort Ethernet för att växla nätverk"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"I syfte att förbättra upplevelsen med enheten kan appar och tjänster fortfarande söka efter wifi-nätverk när som helst, även om wifi har inaktiverats. "<annotation id="link">"Ändra"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 7f51e82683b7..6d503e249a6a 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -77,11 +77,12 @@ <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> <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string> - <string name="screenshot_saved_text" msgid="7778833104901642442">"Gusa ili utazame picha ya skrini uliyohifadhi"</string> + <string name="screenshot_saved_text" msgid="7778833104901642442">"Gusa ili uone picha ya skrini uliyohifadhi"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Imeshindwa kuhifadhi picha ya skrini"</string> <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ni sharti ufungue kifaa kabla ya kuhifadhi picha ya skrini"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie maikrofoni yako."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera yako."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera au maikrofoni yako."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Kifaa"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Kifaa kingine"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Betri imejaa"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Inachaji"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Udhibiti wa arifa"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Imewashwa"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Imezimwa"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Imewashwa - Inayolenga nyuso"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n"<b>"Kiwango cha 5"</b>" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n"<b>"Kiwango cha 4"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n"<b>"Kiwango cha 3"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n"<b>"Kiwango cha 2"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n"<b>"Kiwango cha 1"</b>" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n"<b>"Kiwango cha 0"</b>" \n- Zuia arifa zote kutoka programu"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Arifa"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Hutaona tena arifa hizi"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Tumia alama ya kidole kufungua"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data ya mtandao wa simu haitaunganishwa kiotomatiki"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Hakuna muunganisho"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Hakuna mitandao mingine inayopatikana"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Hakuna mitandao inayopatikana"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Maelezo ya mtandao"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Gusa mtandao ili uunganishe"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Fungua ili uangalie mitandao"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Inatafuta mitandao…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Imeshindwa kuunganisha kwenye mtandao"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi haitaunganishwa kiotomatiki kwa sasa"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Angalia yote"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ili kubadili mitandao, tenganisha ethaneti"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ili kuboresha hali ya matumizi ya kifaa, programu na huduma bado zinaweza kutafuta mitandao ya Wi‑Fi wakati wowote, hata wakati umezima Wi‑Fi. Unaweza kubadilisha mipangilio hii katika mipangilio ya kutafuta Wi-Fi. "<annotation id="link">"Badilisha"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index da80b85b38bf..0a34dfd71c7e 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -95,4 +95,7 @@ <dimen name="controls_top_margin">24dp</dimen> <dimen name="global_actions_grid_item_layout_height">80dp</dimen> + + <!-- Internet panel related dimensions --> + <dimen name="internet_dialog_list_max_width">624dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index b51fb9efbbee..845a36148ef4 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> @@ -122,10 +123,10 @@ <string name="screenrecord_delete_error" msgid="2870506119743013588">"திரை ரெக்கார்டிங்கை நீக்குவதில் பிழை"</string> <string name="screenrecord_permission_error" msgid="7856841237023137686">"அனுமதிகளைப் பெற இயலவில்லை"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"ஸ்கிரீன் ரெக்கார்டிங்கைத் தொடங்குவதில் பிழை"</string> - <string name="usb_preference_title" msgid="1439924437558480718">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string> + <string name="usb_preference_title" msgid="1439924437558480718">"USB ஃபைல் இடமாற்ற விருப்பங்கள்"</string> <string name="use_mtp_button_title" msgid="5036082897886518086">"(MTP) மீடியா பிளேயராக ஏற்று"</string> <string name="use_ptp_button_title" msgid="7676427598943446826">"(PTP) கேமராவாக ஏற்று"</string> - <string name="installer_cd_button_title" msgid="5499998592841984743">"Mac க்கான Android கோப்பு இடமாற்ற ஆப்ஸை நிறுவு"</string> + <string name="installer_cd_button_title" msgid="5499998592841984743">"Mac க்கான Android ஃபைல் இடமாற்ற ஆப்ஸை நிறுவு"</string> <string name="accessibility_back" msgid="6530104400086152611">"பின்செல்"</string> <string name="accessibility_home" msgid="5430449841237966217">"முகப்பு"</string> <string name="accessibility_menu" msgid="2701163794470513040">"மெனு"</string> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"உங்கள் மைக்ரோஃபோனைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"உங்கள் கேமராவைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"உங்கள் கேமராவையோ மைக்ரோஃபோனையோ பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"சாதனம்"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"பிற சாதனம்"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"சார்ஜ் செய்யப்பட்டது"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"சார்ஜ் ஆகிறது"</string> @@ -451,7 +452,7 @@ <string name="zen_silence_introduction" msgid="6117517737057344014">"இது அலாரங்கள், இசை, வீடியோக்கள் மற்றும் கேம்ஸ் உட்பட எல்லா ஒலிகளையும் அதிர்வுகளையும் தடுக்கும்."</string> <string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="7248696377626341060">"அவசர நிலைக் குறைவான அறிவிப்புகள் கீழே உள்ளன"</string> - <string name="notification_tap_again" msgid="4477318164947497249">"திறக்க, மீண்டும் தட்டவும்"</string> + <string name="notification_tap_again" msgid="4477318164947497249">"அன்லாக் செய்ய, மீண்டும் தட்டவும்"</string> <string name="tap_again" msgid="1315420114387908655">"மீண்டும் தட்டவும்"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="keyguard_unlock_press" msgid="8488350566398524740">"திறப்பதற்கு அழுத்தவும்"</string> @@ -512,7 +513,7 @@ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> மூலம் ரெக்கார்டிங் செய்யவோ அனுப்புவதற்கோ தொடங்கிவீட்டீர்களா?"</string> <string name="media_projection_remember_text" msgid="6896767327140422951">"மீண்டும் காட்டாதே"</string> <string name="clear_all_notifications_text" msgid="348312370303046130">"எல்லாவற்றையும் அழி"</string> - <string name="manage_notifications_text" msgid="6885645344647733116">"அறிவிப்புகளை நிர்வகி"</string> + <string name="manage_notifications_text" msgid="6885645344647733116">"நிர்வகி"</string> <string name="manage_notifications_history_text" msgid="57055985396576230">"இதுவரை வந்த அறிவிப்புகள்"</string> <string name="notification_section_header_incoming" msgid="850925217908095197">"புதிது"</string> <string name="notification_section_header_gentle" msgid="6804099527336337197">"சைலன்ட்"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள்"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ஆன்"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ஆஃப்"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ஆன் - முகம் அடிப்படையிலானது"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள் மூலம், ஆப்ஸின் அறிவிப்புகளுக்கு முக்கியத்துவ நிலையை (0-5) அமைக்கலாம். \n\n"<b>"நிலை 5"</b>" \n- அறிவிப்புப் பட்டியலின் மேலே காட்டும் \n- முழுத் திரைக் குறுக்கீட்டை அனுமதிக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 4"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 3"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n\n"<b>"நிலை 2"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது, அதிர்வுறாது \n\n"<b>"நிலை 1"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது அல்லது அதிர்வுறாது \n- லாக் ஸ்கிரீன் மற்றும் நிலைப்பட்டியிலிருந்து மறைக்கும் \n- அறிவிப்புகள் பட்டியலின் கீழே காட்டும் \n\n"<b>"நிலை 0"</b>" \n- ஆப்ஸின் எல்லா அறிவிப்புகளையும் தடுக்கும்"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"அறிவிப்புகள்"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"இந்த அறிவிப்புகளை இனி பார்க்கமாட்டீர்கள்"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"கைரேகையைப் பயன்படுத்தி திறந்திடுங்கள்"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"அங்கீகாரம் தேவை. கைரேகை சென்சாரைத் தொட்டு அங்கீகரியுங்கள்."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"செயலில் உள்ள மொபைல் அழைப்பு"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"மொபைல் டேட்டாவுடன் தானாக இணைக்காது"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"இணைப்பு இல்லை"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"வேறு நெட்வொர்க்குகள் எதுவும் கிடைக்கவில்லை"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"நெட்வொர்க்குகள் எதுவும் கிடைக்கவில்லை"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"வைஃபை"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"நெட்வொர்க் விவரங்கள்"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"இணையத்துடன் இணைய நெட்வொர்க்கைத் தட்டுங்கள்"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"நெட்வொர்க்குகளைப் பார்க்க அன்லாக் செய்யுங்கள்"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"நெட்வொர்க்குகளைத் தேடுகிறது…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"நெட்வொர்க்குடன் இணைக்க முடியவில்லை"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"தற்போதைக்கு வைஃபை தானாக இணைக்கப்படாது"</string> + <string name="see_all_networks" msgid="3773666844913168122">"அனைத்தையும் காட்டு"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"நெட்வொர்க்குகளை மாற்ற ஈதர்நெட் இணைப்பைத் துண்டிக்கவும்"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"சாதன அனுபவத்தை மேம்படுத்த, வைஃபை ஆஃப் செய்யப்பட்டிருந்தாலும்கூட எந்த நேரத்திலும் ஆப்ஸும் சேவைகளும் வைஃபை நெட்வொர்க்குகளைத் தேடலாம். வைஃபை ஸ்கேனிங் அமைப்புகளில் இதை மாற்றிக் கொள்ளலாம். "<annotation id="link">"மாற்று"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index e285796f6037..605c2eca5124 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/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> @@ -100,7 +101,7 @@ <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string> <string name="screenrecord_start_label" msgid="1750350278888217473">"రికార్డింగ్ను ప్రారంభించాలా?"</string> - <string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నైనా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, ఆడియో ఉంటాయి."</string> + <string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నయినా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, ఆడియో కూడా ఉంటాయి."</string> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ఆడియోను రికార్డ్ చేయి"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"పరికరం ఆడియో"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే సంగీతం, కాల్స్, రింగ్టోన్ల వంటి ధ్వనులు"</string> @@ -113,7 +114,7 @@ <string name="screenrecord_stop_text" msgid="6549288689506057686">"ఆపడానికి ట్యాప్ చేయండి"</string> <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string> <string name="screenrecord_pause_label" msgid="6004054907104549857">"పాజ్ చేయి"</string> - <string name="screenrecord_resume_label" msgid="4972223043729555575">"కొనసాగించు"</string> + <string name="screenrecord_resume_label" msgid="4972223043729555575">"కొనసాగించండి"</string> <string name="screenrecord_cancel_label" msgid="7850926573274483294">"రద్దు చేయి"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయి"</string> <string name="screenrecord_cancel_success" msgid="1775448688137393901">"స్క్రీన్ రికార్డ్ రద్దు చేయబడింది"</string> @@ -124,7 +125,7 @@ <string name="screenrecord_start_error" msgid="2200660692479682368">"స్క్రీన్ రికార్డింగ్ ప్రారంభించడంలో ఎర్రర్ ఏర్పడింది"</string> <string name="usb_preference_title" msgid="1439924437558480718">"USB ఫైల్ బదిలీ ఎంపికలు"</string> <string name="use_mtp_button_title" msgid="5036082897886518086">"మీడియా ప్లేయర్గా (MTP) మౌంట్ చేయి"</string> - <string name="use_ptp_button_title" msgid="7676427598943446826">"కెమెరాగా (PTP) మౌంట్ చేయి"</string> + <string name="use_ptp_button_title" msgid="7676427598943446826">"ఒక కెమెరాగా (PTP) మౌంట్ చేయండి"</string> <string name="installer_cd_button_title" msgid="5499998592841984743">"Macకు Android ఫైల్ బదిలీ యాప్ ఇన్స్టాల్ చేయండి"</string> <string name="accessibility_back" msgid="6530104400086152611">"వెనుకకు"</string> <string name="accessibility_home" msgid="5430449841237966217">"హోమ్"</string> @@ -146,7 +147,7 @@ <string name="accessibility_manage_notification" msgid="582215815790143983">"నోటిఫికేషన్లను నిర్వహించండి"</string> <string name="phone_label" msgid="5715229948920451352">"ఫోన్ను తెరువు"</string> <string name="voice_assist_label" msgid="3725967093735929020">"వాయిస్ అసిస్టెంట్ను తెరువు"</string> - <string name="camera_label" msgid="8253821920931143699">"కెమెరాను తెరువు"</string> + <string name="camera_label" msgid="8253821920931143699">"కెమెరాను తెరవండి"</string> <string name="cancel" msgid="1089011503403416730">"రద్దు చేయి"</string> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"నిర్ధారించు"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"మళ్లీ ప్రయత్నించు"</string> @@ -274,10 +275,10 @@ <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string> <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"బ్లూటూత్ ఆఫ్ చేయబడింది."</string> <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"బ్లూటూత్ ఆన్ చేయబడింది."</string> - <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"స్థాన నివేదన ఆఫ్లో ఉంది."</string> - <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"స్థాన నివేదన ఆన్లో ఉంది."</string> - <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"స్థాన నివేదన ఆఫ్ చేయబడింది."</string> - <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"స్థాన నివేదన ఆన్ చేయబడింది."</string> + <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"లొకేషన్ రిపోర్టింగ్ ఆఫ్లో ఉంది."</string> + <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"లొకేషన్ రిపోర్టింగ్ ఆన్లో ఉంది."</string> + <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"లొకేషన్ రిపోర్టింగ్ ఆఫ్ చేయబడింది."</string> + <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"లొకేషన్ రిపోర్టింగ్ ఆన్ చేయబడింది."</string> <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g>కి అలారం సెట్ చేయబడింది."</string> <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"ప్యానెల్ను మూసివేయి."</string> <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"ఎక్కువ సమయం."</string> @@ -307,8 +308,8 @@ <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"మీరు సెట్ చేసిన డేటా పరిమితిని చేరుకున్నారు. మీరు ఇప్పుడు మొబైల్ డేటాను ఉపయోగించడం లేదు.\n\nమీరు పునఃప్రారంభిస్తే, డేటా వినియోగానికి ఛార్జీలు చెల్లించాల్సి రావచ్చు."</string> <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"పునఃప్రారంభించు"</string> <string name="gps_notification_searching_text" msgid="231304732649348313">"GPS కోసం శోధిస్తోంది"</string> - <string name="gps_notification_found_text" msgid="3145873880174658526">"స్థానం GPS ద్వారా సెట్ చేయబడింది"</string> - <string name="accessibility_location_active" msgid="2845747916764660369">"స్థాన అభ్యర్థనలు సక్రియంగా ఉన్నాయి"</string> + <string name="gps_notification_found_text" msgid="3145873880174658526">"లొకేషన్ GPS ద్వారా సెట్ చేయబడింది"</string> + <string name="accessibility_location_active" msgid="2845747916764660369">"లొకేషన్ రిక్వెస్ట్లు యాక్టివ్గా ఉన్నాయి"</string> <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"సెన్సార్లు ఆఫ్ యాక్టివ్లో ఉంది"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"అన్ని నోటిఫికేషన్లను క్లియర్ చేయండి."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> @@ -429,12 +430,12 @@ <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించు"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string> - <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరం కెమెరాను అన్బ్లాక్ చేయమంటారా?"</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"పరికరం కెమెరా, మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string> + <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరంలోని కెమెరాను అన్బ్లాక్ చేయమంటారా?"</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"పరికరంలోని కెమెరా, మైక్రోఫోన్లను అన్బ్లాక్ చేయమంటారా?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"మీ మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string> - <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"మీ కెమెరాను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string> - <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"మీ కెమెరాను లేదా మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"పరికరం"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ఇది, మీ కెమెరాను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లకు, సర్వీస్లకు యాక్సెస్ను అన్బ్లాక్ చేస్తుంది."</string> + <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ఇది, మీ కెమెరాను లేదా మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లకు, సర్వీస్లకు యాక్సెస్ను అన్బ్లాక్ చేస్తుంది."</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"ఇతర పరికరం"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ఛార్జ్ చేయబడింది"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"ఛార్జ్ అవుతోంది"</string> @@ -461,7 +462,7 @@ <string name="do_disclosure_with_name" msgid="2091641464065004091">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>కు చెందినది"</string> <string name="do_financed_disclosure_with_name" msgid="6723004643314467864">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ద్వారా అందించబడింది"</string> <string name="phone_hint" msgid="6682125338461375925">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string> - <string name="voice_hint" msgid="7476017460191291417">"వాయిస్ అసిస్టెంట్ చిహ్నం నుండి స్వైప్"</string> + <string name="voice_hint" msgid="7476017460191291417">"వాయిస్ అసిస్టెంట్ కోసం చిహ్నం నుండి స్వైప్ చేయండి"</string> <string name="camera_hint" msgid="4519495795000658637">"కెమెరా కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string> <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"మొత్తం నిశ్శబ్దం. దీని వలన స్క్రీన్ రీడర్లు కూడా నిశ్శబ్దమవుతాయి."</string> <string name="interruption_level_none" msgid="219484038314193379">"మొత్తం నిశ్శబ్దం"</string> @@ -506,7 +507,7 @@ <string name="battery_saver_notification_title" msgid="8419266546034372562">"బ్యాటరీ సేవర్ ఆన్లో ఉంది"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string> <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"బ్యాటరీ సేవర్ను ఆఫ్ చేయండి"</string> - <string name="media_projection_dialog_text" msgid="1755705274910034772">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్వర్డ్లు, చెల్లింపు వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> + <string name="media_projection_dialog_text" msgid="1755705274910034772">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్ను అందిస్తున్న సర్వీస్ యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> @@ -562,30 +563,30 @@ <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ఈ పరికరంలో ప్రమాణపత్ర అధికారం ఇన్స్టాల్ చేయబడింది. మీ సురక్షిత నెట్వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string> <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్ని పర్యవేక్షించగల నెట్వర్క్ లాగింగ్ని ఆన్ చేశారు."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"మీ అడ్మిన్ నెట్వర్క్ లాగింగ్ను ఆన్ చేశారు, ఇది మీ వర్క్ ప్రొఫైల్లోని ట్రాఫిక్ను పర్యవేక్షిస్తుంది కానీ మీ వ్యక్తిగత ప్రొఫైల్లో కాదు."</string> - <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> - <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"మీరు ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP_0">%1$s</xliff:g> మరియు <xliff:g id="VPN_APP_1">%2$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"మీ కార్యాలయ ప్రొఫైల్ ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> - <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"మీ వ్యక్తిగత ప్రొఫైల్ ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> + <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> + <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"మీరు ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP_0">%1$s</xliff:g> మరియు <xliff:g id="VPN_APP_1">%2$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"మీ కార్యాలయ ప్రొఫైల్ ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> + <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"మీ వ్యక్తిగత ప్రొఫైల్ ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"మీ పరికరం <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ద్వారా నిర్వహించబడుతోంది."</string> <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> మీ పరికరాన్ని నిర్వహించడానికి <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>ని ఉపయోగిస్తుంది."</string> - <string name="monitoring_description_do_body" msgid="7700878065625769970">"మీ పరికరంతో అనుబంధించబడిన సెట్టింగ్లు, కార్పొరేట్ యాక్సెస్, యాప్లు, డేటా మరియు మీ పరికరం యొక్క స్థాన సమాచారాన్ని మీ నిర్వాహకులు పర్యవేక్షించగలరు మరియు నిర్వహించగలరు."</string> + <string name="monitoring_description_do_body" msgid="7700878065625769970">"మీ పరికరంతో అనుబంధించబడిన సెట్టింగ్లు, కార్పొరేట్ యాక్సెస్, యాప్లు, డేటా మరియు మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు."</string> <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string> <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"మరింత తెలుసుకోండి"</string> - <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> + <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN సెట్టింగ్లను తెరవండి"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"విశ్వసనీయ ఆధారాలను తెరువు"</string> <string name="monitoring_description_network_logging" msgid="577305979174002252">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్ని పర్యవేక్షించగల నెట్వర్క్ లాగింగ్ని ఆన్ చేశారు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string> - <string name="monitoring_description_vpn" msgid="1685428000684586870">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక యాప్నకు అనుమతి ఇచ్చారు.\n\nఈ యాప్ ఇమెయిల్లు,యాప్లు మరియు వెబ్సైట్లతో సహా మీ డివైజ్ మరియు నెట్వర్క్ కార్యకలాపాన్ని పర్యవేక్షించగలదు."</string> - <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది.\n\nఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల సామర్థ్యం మీ నిర్వాహకులకు ఉంది.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి.\n\nమీరు VPNకి కూడా కనెక్ట్ అయ్యారు, ఇది మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> + <string name="monitoring_description_vpn" msgid="1685428000684586870">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక యాప్నకు అనుమతి ఇచ్చారు.\n\nఈ యాప్ ఈమెయిళ్లు,యాప్లు మరియు వెబ్సైట్లతో సహా మీ డివైజ్ మరియు నెట్వర్క్ యాక్టివిటీని పర్యవేక్షించగలదు."</string> + <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది.\n\nఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల సామర్థ్యం మీ నిర్వాహకులకు ఉంది.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి.\n\nమీరు VPNకి కూడా కనెక్ట్ అయ్యారు, ఇది మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు. మీ తల్లి/తండ్రి, మీరు ఉపయోగించే యాప్లు, మీ లొకేషన్, అలాగే మీ పరికర వినియోగ వ్యవధి వంటి సమాచారాన్ని చూడగలరు, మేనేజ్ చేయగలరు."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> - <string name="monitoring_description_app" msgid="376868879287922929">"మీరు ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string> - <string name="monitoring_description_app_personal" msgid="1970094872688265987">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> - <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> - <string name="monitoring_description_app_work" msgid="3713084153786663662">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ కార్యాలయ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> - <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఇమెయిల్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ కార్యాలయ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>కి కూడా మీరు కనెక్ట్ చేయబడ్డారు."</string> + <string name="monitoring_description_app" msgid="376868879287922929">"మీరు ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string> + <string name="monitoring_description_app_personal" msgid="1970094872688265987">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> + <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> + <string name="monitoring_description_app_work" msgid="3713084153786663662">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ కార్యాలయ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> + <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఈమెయిళ్లు, యాప్లు మరియు వెబ్సైట్లతో సహా మీ కార్యాలయ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>కి కూడా మీరు కనెక్ట్ చేయబడ్డారు."</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ద్వారా అన్లాక్ చేయబడింది"</string> <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"మీరు మాన్యువల్గా అన్లాక్ చేస్తే మినహా పరికరం లాక్ చేయబడి ఉంటుంది"</string> <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string> @@ -610,7 +611,7 @@ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి, పైకి స్వైప్ చేసి & పట్టుకోండి."</string> <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి స్థూలదృష్టిని తాకి & అలాగే పట్టుకోండి."</string> <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి హోమ్ని తాకి & అలాగే పట్టుకోండి."</string> - <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"వ్యక్తిగత డేటా (కాంటాక్ట్లు, ఇంకా ఇమెయిల్ కంటెంట్ లాంటివి) యాక్సెస్ చేయబడవచ్చు."</string> + <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"వ్యక్తిగత డేటా (కాంటాక్ట్లు, ఇంకా ఈమెయిల్ కంటెంట్ లాంటివి) యాక్సెస్ చేయబడవచ్చు."</string> <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"పిన్ చేయబడిన యాప్ ఇతర యాప్లను తెరవవచ్చు."</string> <string name="screen_pinning_toast" msgid="8177286912533744328">"ఈ యాప్ను అన్పిన్ చేయడానికి, \'వెనుకకు\', \'ఓవర్వ్యూ\' బటన్లను తాకి & అలాగే పట్టుకోండి"</string> <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"ఈ యాప్ను అన్పిన్ చేయడానికి, వెనుకకు, హోమ్ బటన్లను తాకి & అలాగే పట్టుకోండి"</string> @@ -658,7 +659,7 @@ <string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string> <string name="show_battery_percentage" msgid="6235377891802910455">"పొందుపరిచిన బ్యాటరీ శాతం చూపు"</string> <string name="show_battery_percentage_summary" msgid="9053024758304102915">"ఛార్జింగ్లో లేనప్పుడు స్థితి పట్టీ చిహ్నం లోపల బ్యాటరీ స్థాయి శాతం చూపుతుంది"</string> - <string name="quick_settings" msgid="6211774484997470203">"శీఘ్ర సెట్టింగ్లు"</string> + <string name="quick_settings" msgid="6211774484997470203">"క్విక్ సెట్టింగ్లు"</string> <string name="status_bar" msgid="4357390266055077437">"స్థితి పట్టీ"</string> <string name="overview" msgid="3522318590458536816">"ఓవర్వ్యూ"</string> <string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string> @@ -709,7 +710,8 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"పవర్ నోటిఫికేషన్ నియంత్రణలు"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"ఆన్లో ఉన్నాయి"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ఆఫ్లో ఉన్నాయి"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ జాబితా పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ జాబితా దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"\'ముఖం ఆధారం\'ను - ఆన్ చేయండి"</string> + <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్ పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"నోటిఫికేషన్లు"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"ఇకపై మీకు ఈ నోటిఫికేషన్లు కనిపించవు"</string> <string name="notification_channel_minimized" msgid="6892672757877552959">"ఈ నోటిఫికేషన్లు కుదించబడ్డాయి"</string> @@ -755,13 +757,13 @@ <string name="notification_delegate_header" msgid="1264510071031479920">"ప్రాక్సీ చేయబడిన నోటిఫికేషన్"</string> <string name="notification_channel_dialog_title" msgid="6856514143093200019">"అన్ని <xliff:g id="APP_NAME">%1$s</xliff:g> నోటిఫికేషన్లు"</string> <string name="see_more_title" msgid="7409317011708185729">"మరిన్ని చూడండి"</string> - <string name="appops_camera" msgid="5215967620896725715">"ఈ యాప్ ఈ కెమెరాను ఉపయోగిస్తోంది."</string> + <string name="appops_camera" msgid="5215967620896725715">"ఈ యాప్, కెమెరాను ఉపయోగిస్తోంది."</string> <string name="appops_microphone" msgid="8805468338613070149">"ఈ యాప్ మైక్రోఫోన్ను ఉపయోగిస్తుంది."</string> <string name="appops_overlay" msgid="4822261562576558490">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది."</string> - <string name="appops_camera_mic" msgid="7032239823944420431">"ఈ యాప్ మైక్రోఫోన్ మరియు కెమెరాను ఉపయోగిస్తుంది."</string> - <string name="appops_camera_overlay" msgid="6466845606058816484">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది మరియు కెమెరాను ఉపయోగిస్తుంది."</string> + <string name="appops_camera_mic" msgid="7032239823944420431">"ఈ యాప్ మైక్రోఫోన్ను, కెమెరాను ఉపయోగిస్తోంది."</string> + <string name="appops_camera_overlay" msgid="6466845606058816484">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది, కెమెరాను ఉపయోగిస్తోంది."</string> <string name="appops_mic_overlay" msgid="4609326508944233061">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది మరియు మైక్రోఫోన్ను ఉపయోగిస్తుంది."</string> - <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది మరియు మైక్రోఫోన్, కెమెరాను ఉపయోగిస్తుంది."</string> + <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది, మైక్రోఫోన్, కెమెరాను ఉపయోగిస్తోంది."</string> <string name="notification_appops_settings" msgid="5208974858340445174">"సెట్టింగ్లు"</string> <string name="notification_appops_ok" msgid="2177609375872784124">"సరే"</string> <string name="feedback_alerted" msgid="5192459808484271208">"ఈ నోటిఫికేషన్, సిస్టమ్ ద్వారా దానంతట అదే <b>ఆటోమేటిక్గా ప్రమోట్ చేయబడింది</b>."</string> @@ -843,7 +845,7 @@ <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"సహాయకం"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"బ్రౌజర్"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"కాంటాక్ట్లు"</string> - <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ఇమెయిల్"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ఈమెయిల్"</string> <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"మ్యూజిక్"</string> <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string> @@ -869,7 +871,7 @@ <string name="nav_bar_layout" msgid="4716392484772899544">"లేఅవుట్"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"అత్యంత ఎడమ వైపు ఉన్న బటన్ రకం"</string> <string name="right_nav_bar_button_type" msgid="4472566498647364715">"అత్యంత కుడివైపు ఉన్న బటన్ రకం"</string> - <string name="nav_bar_default" msgid="8386559913240761526">"(డిఫాల్ట్)"</string> + <string name="nav_bar_default" msgid="8386559913240761526">"(ఆటోమేటిక్)"</string> <string-array name="nav_bar_buttons"> <item msgid="2681220472659720036">"క్లిప్బోర్డ్"</item> <item msgid="4795049793625565683">"కీకోడ్"</item> @@ -900,12 +902,12 @@ <string name="tuner_time" msgid="2450785840990529997">"సమయం"</string> <string-array name="clock_options"> <item msgid="3986445361435142273">"గంటలు, నిమిషాలు మరియు సెకన్లను చూపు"</item> - <item msgid="1271006222031257266">"గంటలు మరియు నిమిషాలను చూపు (డిఫాల్ట్)"</item> + <item msgid="1271006222031257266">"గంటలు, నిమిషాలను చూపు (ఆటోమేటిక్)"</item> <item msgid="6135970080453877218">"ఈ చిహ్నాన్ని చూపవద్దు"</item> </string-array> <string-array name="battery_options"> <item msgid="7714004721411852551">"ఎల్లప్పుడూ శాతాన్ని చూపు"</item> - <item msgid="3805744470661798712">"ఛార్జ్ అవుతున్నప్పుడు శాతాన్ని చూపు (డిఫాల్ట్)"</item> + <item msgid="3805744470661798712">"ఛార్జ్ అవుతున్నప్పుడు శాతాన్ని చూపు (ఆటోమేటిక్)"</item> <item msgid="8619482474544321778">"ఈ చిహ్నాన్ని చూపవద్దు"</item> </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"తక్కువ ప్రాధాన్యత నోటిఫికేషన్ చిహ్నాలను చూపించు"</string> @@ -931,7 +933,7 @@ <string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"వివరాలను తెరవండి."</string> <string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"<xliff:g id="REASON">%s</xliff:g> కారణంగా అందుబాటులో లేదు"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> సెట్టింగ్లను తెరవండి."</string> - <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"సెట్టింగ్ల క్రమాన్ని సవరించండి."</string> + <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"సెట్టింగ్ల క్రమాన్ని ఎడిట్ చేయండి."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"పవర్ మెనూ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"లాక్ స్క్రీన్"</string> @@ -978,9 +980,9 @@ <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi ఆఫ్లో ఉంది"</string> <string name="bt_is_off" msgid="7436344904889461591">"బ్లూటూత్ ఆఫ్లో ఉంది"</string> <string name="dnd_is_off" msgid="3185706903793094463">"అంతరాయం కలిగించవద్దు ఆఫ్లో ఉంది"</string> - <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"స్వయంచాలక నియమం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string> + <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"ఆటోమేటిక్ నియమం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string> <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"యాప్ (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string> - <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"స్వయంచాలక నియమం లేదా యాప్ ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string> + <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"ఆటోమేటిక్ నియమం లేదా యాప్ ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string> <string name="qs_dnd_until" msgid="7844269319043747955">"<xliff:g id="ID_1">%s</xliff:g> వరకు"</string> <string name="qs_dnd_keep" msgid="3829697305432866434">"Keep"</string> <string name="qs_dnd_replace" msgid="7712119051407052689">"భర్తీ చేయి"</string> @@ -989,7 +991,7 @@ <string name="mobile_data_disable_title" msgid="5366476131671617790">"మొబైల్ డేటాను ఆఫ్ చేయాలా?"</string> <string name="mobile_data_disable_message" msgid="8604966027899770415">"\"<xliff:g id="CARRIER">%s</xliff:g>\" ద్వారా మీకు డేటా లేదా ఇంటర్నెట్కు యాక్సెస్ ఉండదు. Wi-Fi ద్వారా మాత్రమే ఇంటర్నెట్ అందుబాటులో ఉంటుంది."</string> <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"మీ క్యారియర్"</string> - <string name="touch_filtered_warning" msgid="8119511393338714836">"అనుమతి అభ్యర్థనకు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string> + <string name="touch_filtered_warning" msgid="8119511393338714836">"అనుమతి రిక్వెస్ట్కు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string> <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> స్లైస్లను చూపించడానికి <xliff:g id="APP_0">%1$s</xliff:g>ని అనుమతించండి?"</string> <string name="slice_permission_text_1" msgid="6675965177075443714">"- ఇది <xliff:g id="APP">%1$s</xliff:g> నుండి సమాచారాన్ని చదువుతుంది"</string> <string name="slice_permission_text_2" msgid="6758906940360746983">"- ఇది <xliff:g id="APP">%1$s</xliff:g> లోపల చర్యలు తీసుకుంటుంది"</string> @@ -1144,7 +1146,7 @@ <string name="status_before_loading" msgid="1500477307859631381">"కంటెంట్ త్వరలో కనిపిస్తుంది"</string> <string name="missed_call" msgid="4228016077700161689">"మిస్డ్ కాల్"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> - <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్లు, మిస్డ్ కాల్స్, అలాగే స్టేటస్ అప్డేట్లను చూడండి"</string> + <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్లు, మిస్స్డ్ కాల్స్, అలాగే స్టేటస్ అప్డేట్లను చూడండి"</string> <string name="people_tile_title" msgid="6589377493334871272">"సంభాషణ"</string> <string name="paused_by_dnd" msgid="7856941866433556428">"అంతరాయం కలిగించవద్దు ద్వారా పాజ్ చేయబడింది"</string> <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> మెసేజ్ను పంపారు: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"తెరవడానికి వేలిముద్రను ఉపయోగించండి"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ప్రామాణీకరణ అవసరం. ప్రామాణీకరించడానికి వేలిముద్ర సెన్సార్ను తాకండి."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ఫోన్ కాల్ జరుగుతోంది"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"మొబైల్ డేటా ఆటోమెటిక్గా కనెక్ట్ అవ్వదు"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"కనెక్షన్ లేదు"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ఇతర నెట్వర్క్లేవీ అందుబాటులో లేవు"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"నెట్వర్క్లు అందుబాటులో లేవు"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"నెట్వర్క్ వివరాలు"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"కనెక్ట్ చేయడానికి నెట్వర్క్ను ట్యాప్ చేయండి"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"నెట్వర్క్లను చూడటానికి అన్లాక్ చేయండి"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"నెట్వర్క్ల కోసం సెర్చ్ చేస్తోంది…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"నెట్వర్క్కు కనెక్ట్ చేయడం విఫలమైంది"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ప్రస్తుతానికి Wi-Fi ఆటోమేటిక్గా కనెక్ట్ అవ్వదు"</string> + <string name="see_all_networks" msgid="3773666844913168122">"అన్నీ చూడండి"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"నెట్వర్క్లను మార్చడానికి, ఈథర్నెట్ను డిస్కనెక్ట్ చేయండి"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"పరికర అనుభవాన్ని మెరుగుపరచడానికి, Wi‑Fi ఆఫ్లో ఉన్నప్పుడు కూడా, ఏ సమయంలో అయినా ఇప్పటికీ Wi‑Fi నెట్వర్క్ల కోసం యాప్లు, సర్వీస్లు స్కాన్ చేయగలవు. మీరు దీనిని Wi‑Fi స్కానింగ్ సెట్టింగ్లలో మార్చవచ్చు. "<annotation id="link">"మార్చండి"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml index 7eded1eaaa65..592f8ce71c1e 100644 --- a/packages/SystemUI/res/values-te/strings_tv.xml +++ b/packages/SystemUI/res/values-te/strings_tv.xml @@ -28,8 +28,8 @@ <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్లు లేవు"</string> <string name="mic_recording_announcement" msgid="7587123608060316575">"మైక్రోఫోన్ రికార్డింగ్ చేస్తోంది"</string> <string name="camera_recording_announcement" msgid="7240177719403759112">"కెమెరా రికార్డింగ్ చేస్తోంది"</string> - <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"కెమెరా, మైక్రోఫోన్ రికార్డింగ్ చేస్తున్నాయి"</string> + <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"కెమెరా, మైక్రోఫోన్లు రికార్డింగ్ చేస్తున్నాయి"</string> <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"మైక్రోఫోన్ రికార్డింగ్ చేయడం ఆపివేసింది"</string> - <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"కెమెరా రికార్డింగ్ చేయడం ఆపివేసింది"</string> - <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"కెమెరా, మైక్రోఫోన్ రికార్డింగ్ చేయడం ఆపివేశాయి"</string> + <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"రికార్డింగ్ చేయడాన్ని కెమెరా ఆపివేసింది"</string> + <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"కెమెరా, మైక్రోఫోన్లు రికార్డింగ్ చేయడం ఆపివేశాయి"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 1fd1313719dc..dd315a24d4c6 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้ไมโครโฟนของคุณ"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องของคุณ"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องหรือไมโครโฟนของคุณ"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"อุปกรณ์"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"อุปกรณ์อื่น"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"ชาร์จแล้ว"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"กำลังชาร์จ"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิด"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"เปิด"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"ปิด"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"เปิด - ตามใบหน้า"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิดช่วยให้คุณตั้งค่าระดับความสำคัญสำหรับการแจ้งเตือนของแอปได้ตั้งแต่ระดับ 0-5 \n\n"<b>"ระดับ 5"</b>" \n- แสดงที่ด้านบนของรายการแจ้งเตือน \n- อนุญาตให้รบกวนแบบเต็มหน้าจอ \n- อนุญาตให้แสดงชั่วครู่ \n\n"<b>"ระดับ 4"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- แสดงชั่วครู่เสมอ \n\n"<b>"ระดับ 3"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n\n"<b>"ระดับ 2"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n\n"<b>"ระดับ 1"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n- ซ่อนจากหน้าจอล็อกและแถบสถานะ \n- แสดงที่ด้านล่างของรายการแจ้งเตือน \n\n"<b>"ระดับ 0"</b>" \n- บล็อกการแจ้งเตือนทั้งหมดจากแอป"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"การแจ้งเตือน"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"คุณจะไม่เห็นการแจ้งเตือนเหล่านี้อีก"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ใช้ลายนิ้วมือเพื่อเปิด"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ต้องมีการตรวจสอบสิทธิ์ แตะเซ็นเซอร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"กำลังโทรอยู่"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"อินเทอร์เน็ตมือถือจะไม่เชื่อมต่ออัตโนมัติ"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"ไม่มีการเชื่อมต่อ"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ไม่มีเครือข่ายอื่นๆ ที่พร้อมใช้งาน"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"ไม่มีเครือข่ายที่พร้อมใช้งาน"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"รายละเอียดเครือข่าย"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"แตะเครือข่ายเพื่อเชื่อมต่อ"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"ปลดล็อกเพื่อดูเครือข่าย"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"กำลังค้นหาเครือข่าย…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"เชื่อมต่อเครือข่ายไม่สำเร็จ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi จะไม่เชื่อมต่ออัตโนมัติในตอนนี้"</string> + <string name="see_all_networks" msgid="3773666844913168122">"ดูทั้งหมด"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ตัดการเชื่อมต่ออีเทอร์เน็ตเพื่อสลับเครือข่าย"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"เพื่อปรับปรุงประสบการณ์การใช้อุปกรณ์ แอปและบริการต่างๆ จะยังคงสแกนหาเครือข่าย Wi‑Fi ได้ทุกเมื่อแม้ว่า Wi‑Fi จะปิดอยู่ คุณเปลี่ยนตัวเลือกนี้ได้ในการตั้งค่าการสแกนหา Wi-Fi "<annotation id="link">"เปลี่ยน"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 3837364887cf..ee569df1bf65 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong mikropono."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera o mikropono."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Iba pang device"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Tapos nang mag-charge"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nagcha-charge"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Mga kontrol sa notification ng power"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Naka-on"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Naka-off"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Naka-on - Batay sa mukha"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Sa pamamagitan ng mga kontrol sa notification ng power, magagawa mong itakda ang antas ng kahalagahan ng mga notification ng isang app mula 0 hanggang 5. \n\n"<b>"Antas 5"</b>" \n- Ipakita sa itaas ng listahan ng notification \n- Payagan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 4"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 3"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n\n"<b>"Antas 2"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n\n"<b>"Antas 1"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n- Itago sa lock screen at status bar \n- Ipakita sa ibaba ng listahan ng notification \n\n"<b>"Antas 0"</b>" \n- I-block ang lahat ng notification mula sa app"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Mga Notification"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Hindi mo na makikita ang mga notification na ito"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gamitin ang fingerprint para buksan"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kailangan ng pag-authenticate. Pindutin ang sensor para sa fingerprint para mag-authenticate."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Kasalukuyang may tawag sa telepono"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Hindi awtomatikong kokonekta ang mobile data"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Walang koneksyon"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Walang available na iba pang network"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Walang available na network"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Mga detalye ng network"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Mag-tap ng network para kumonekta"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"I-unlock para tingnan ang mga network"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Naghahanap ng mga network…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Hind nakakonekta sa network"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Hindi awtomatikong kokonekta ang Wi-Fi sa ngayon"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Tingnan lahat"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para lumipat ng network, idiskonekta ang ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para pahusayin ang karanasan sa device, puwede pa ring mag-scan ng mga Wi-Fi network ang mga app at serbisyo anumang oras, kahit habang naka-off ang Wi‑Fi. Mababago mo ito sa mga setting ng pag-scan ng Wi-Fi. "<annotation id="link">"Baguhin"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 1cd547ca7793..4838b9ea5f24 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Bu işlem, mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Bu işlem, kameranızı kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Bu işlem, kamera veya mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Diğer cihaz"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Şarj oldu"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Şarj oluyor"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Güç bildirim kontrolleri"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Açık"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Kapalı"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Açık - Yüze göre"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n"<b>"5. Düzey"</b>" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"4. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"3. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n"<b>"2. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n"<b>"1. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n"<b>"0. Düzey"</b>" \n- Uygulamadan gelen tüm bildirimler engellensin"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Bildirimler"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Bu bildirimleri artık görmeyeceksiniz"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmak için parmak izi kullanın"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil veri otomatik olarak bağlanmıyor"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yok"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Kullanılabilir başka ağ yok"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Kullanılabilir ağ yok"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Kablosuz"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Ağ bilgileri"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Bağlanmak için bir ağa dokunun"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ağları görmek için kilidi açın"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ağlar aranıyor…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ağa bağlanılamadı"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Şu anda kablosuz ağa otomatik olarak bağlanılamıyor"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Tümünü göster"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ağ değiştirmek için ethernet bağlantısını kesin"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Uygulamalar ve hizmetler, cihaz deneyimini iyileştirmek için Kablosuz özelliği kapalı bile olsa kablosuz ağlar herhangi bir zamanda tarayabilir. Bunu kablosuz ağ taraması ayarlarından değiştirebilirsiniz. "<annotation id="link">"Değiştir"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 70922aa77db3..62b85c45bf38 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> @@ -438,7 +439,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Усі додатки та сервіси, яким дозволено користуватися вашим мікрофоном, отримають доступ."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою, отримають доступ."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою чи мікрофоном, отримають доступ."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Інший пристрій"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заряджено"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Заряджається"</string> @@ -715,6 +716,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Елементи керування сповіщеннями"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Увімк."</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Вимк."</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Увімкнути (за обличчям)"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"За допомогою елементів керування сповіщеннями ви можете налаштувати пріоритет сповіщень додатка – від 0 до 5 рівня. \n\n"<b>"Рівень 5"</b>\n"- Показувати сповіщення вгорі списку \n- Виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 4"</b>\n"- Не виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 3"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n\n"<b>"Рівень 2"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n\n"<b>"Рівень 1"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n- Не показувати на заблокованому екрані та в рядку стану \n- Показувати сповіщення внизу списку \n\n"<b>"Рівень 0"</b>\n"- Блокувати всі сповіщення з додатка"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Сповіщення"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Ви більше не бачитимете цих сповіщень"</string> @@ -1173,4 +1175,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Щоб відкрити, використайте відбиток пальця"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Пройдіть автентифікацію. Для цього торкніться сканера відбитків пальців."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Активний телефонний виклик"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобільний Інтернет не підключатиметься автоматично"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Немає з\'єднання"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Інші мережі недоступні"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Немає доступних мереж"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Деталі мережі"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Натисніть мережу, до якої потрібно підключитися"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Розблокувати, щоб переглянути мережі"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Пошук мереж…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не вдалося підключитися до мережі"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Пристрій не підключатиметься до Wi-Fi автоматично"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Показати все"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Щоб вибрати іншу мережу, від’єднайте кабель Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Щоб користуватися пристроєм було зручніше, додатки й сервіси можуть шукати бездротові мережі, навіть якщо Wi-Fi вимкнено. Це налаштування можна змінити в параметрах пошуку мереж Wi-Fi. "<annotation id="link">"Змінити"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 7ef014923960..88be783776db 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"اس سے آپ کا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"اس سے آپ کا کیمرا استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"اس سے آپ کا کیمرا یا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"آلہ"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"دوسرا آلہ"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"چارج ہوگئی"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"چارج ہو رہی ہے"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"پاور اطلاع کے کنٹرولز"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"آن"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"آف"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"آن - چہرے پر مبنی"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n"<b>"سطح 5"</b>\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 4"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 3"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n"<b>"سطح 2"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"<b>" سطح 1"</b>\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n"<b>"سطح 0"</b>\n"- ایپ سے تمام اطلاعات مسدود کریں"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"اطلاعات"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"آپ کو یہ اطلاعات مزید دکھائی نہیں دیں گی"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"کھولنے کے لیے فنگر پرنٹ کا استعمال کریں"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"توثیق مطلوب ہے۔ توثیق کرنے کے لیے فنگر پرنٹ سینسر کو ٹچ کریں۔"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"جاری فون کال"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"موبائل ڈیٹا خودکار طور پر منسلک نہیں ہوگا"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"کوئی کنکشن نہیں"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"کوئی دوسرا نیٹ ورک دستیاب نہیں ہے"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"کوئی نیٹ ورکس دستیاب نہیں ہیں"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"نیٹ ورک کی تفصیلات"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"منسلک کرنے کے لیے نیٹ ورک پر تھپتھپائیں"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"نیٹ ورکس کو دیکھنے کے لیے غیر مقفل کریں"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"نیٹ ورکس تلاش کیے جا رہے ہیں…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"نیٹ ورک سے منسلک ہونے میں ناکام ہو گیا"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ابھی Wi-Fi خود کار طور پر منسلک نہیں ہوگا"</string> + <string name="see_all_networks" msgid="3773666844913168122">"سبھی دیکھیں"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"نیٹ ورکس پر سوئچ کرنے کیلئے، ایتھرنیٹ غیر منسلک کریں"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"آلے کے تجربے کو بہتر بنانے کے لیے، Wi‑Fi کے آف ہونے پر بھی ایپس اور سروسز کسی بھی وقت Wi‑Fi نیٹ ورکس اسکین کر سکتی ہیں۔ آپ اسے Wi‑Fi اسکیننگ کی ترتیبات میں تبدیل کر سکتے ہیں۔ "<annotation id="link">"تبدیل کریں"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 08ac980d3bee..fb396a91421c 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamerangizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera va mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Qurilma"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Boshqa qurilma"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Quvvat oldi"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Quvvat olmoqda"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Bildirishnomalar uchun kengaytirilgan boshqaruv"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Yoniq"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Yoqilmagan"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Yoqish - Yuz asosida"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Bildirishnomalar uchun kengaytirilgan boshqaruv yordamida ilova bildirishnomalarining muhimlik darajasini (0-5) sozlash mumkin. \n\n"<b>"5-daraja"</b>" \n- Bildirishnomani ro‘yxatning boshida ko‘rsatish \n- To‘liq ekranli bildirishnomalarni ko‘rsatish \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"4-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"3-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n\n"<b>"2-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n\n"<b>"1-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n- Ekran qulfi va holat qatorida ko‘rsatmaslik \n- Bildirishnomani ro‘yxatning oxirida ko‘rsatish \n\n"<b>"0-daraja"</b>" \n- Ilovadan keladigan barcha bildirishnomalarni bloklash"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Bildirishnomalar"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Bu bildirishnomalar endi chiqmaydi"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ochish uchun barmoq izidan foydalaning"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ulandi"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil internetga avtomatik ulanmaydi"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Internetga ulanmagansiz"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Boshqa tarmoqlar mavjud emas"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Hech qanday tarmoq mavjud emas"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Tarmoq tafsilotlari"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ulanish uchun tarmoq ustiga bosing"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Tarmoqlarni koʻrish uchun qulfdan chiqaring"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Tarmoqlar qidirilmoqda…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Tarmoqqa ulanmadi"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi hozir avtomatik ulanmaydi"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Hammasi"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Boshqa tarmoqqa almashish uchun Ethernet tarmogʻini uzing"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Qurilma ishlashini yaxshilash uchun ilova va xizmatlar hatto Wi-Fi yoqilmaganda ham istalgan vaqt Wi-Fi tarmoqlarni qidirishi mumkin. Buni taqiqlash uchun Wi-Fi tarmoqlarni qidirish funksiyasini faolsizlantiring. "<annotation id="link">"Sozlamalarni ochish"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 60b1232cd8a3..7eb2a8b4eb11 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng micrô của bạn."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh của bạn."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh hoặc micrô của bạn."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Thiết bị"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Thiết bị khác"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Đã sạc đầy"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Đang sạc"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Điều khiển thông báo nguồn"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Bật"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Đang tắt"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Đang bật – Dựa trên khuôn mặt"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Thông báo"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Bạn sẽ không thấy các thông báo này nữa"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Dùng vân tay để mở"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Bạn cần phải xác thực. Hãy chạm vào cảm biến vân tay để xác thực."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Đang gọi điện thoại"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Dữ liệu di động sẽ không tự động kết nối"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Không có kết nối mạng"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Không có mạng nào khác"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Không có mạng"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Thông tin chi tiết về mạng"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Nhấn vào một mạng để kết nối"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Mở khóa để xem mạng"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Đang tìm mạng…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Không kết nối được với mạng"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Tạm thời, Wi-Fi sẽ không tự động kết nối"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Xem tất cả"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Để chuyển mạng, hãy rút cáp Ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Để cải thiện trải nghiệm khi dùng thiết bị, các ứng dụng và dịch vụ vẫn có thể quét tìm mạng Wi‑Fi bất cứ lúc nào, ngay cả khi Wi‑Fi tắt. Bạn có thể thay đổi chế độ này trong phần cài đặt tính năng Quét tìm Wi‑Fi. "<annotation id="link">"Thay đổi"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 357e59e7ece5..faae83c6dd83 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"这将会为所有获准使用您麦克风的应用和服务启用这项权限。"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"这将会为所有获准使用您摄像头的应用和服务启用这项权限。"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您的摄像头或麦克风的应用和服务启用这项权限。"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"其他设备"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充满"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"正在充电"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"高级通知设置"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"已开启"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"已关闭"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已开启 - 基于人脸"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"通知"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"您将不会再看到这些通知"</string> @@ -1058,7 +1060,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> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指纹即可打开"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要进行身份验证。请轻触指纹传感器以验证身份。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"正在进行通话"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"没有其他可用网络"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"没有可用网络"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"WLAN"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"网络详情"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"点按要连接的网络"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"解锁即可查看网络"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜索网络…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"未能连接到网络"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WLAN 暂时无法自动连接"</string> + <string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切换网络,请断开以太网连接"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"为了提升设备的使用体验,即使 WLAN 已关闭,应用和服务仍可以随时扫描 WLAN 网络。您可以在 WLAN 扫描设置中更改此设置。"<annotation id="link">"更改"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index f8ede3a55b88..b5c40693865e 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的麥克風。"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機。"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機或麥克風。"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已完成充電"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"通知控制項"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"開啟"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"關閉"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已開啟 - 根據面孔偵測"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"通知控制項讓您設定應用程式通知的重要性 (0 至 5 級)。\n\n"<b>"第 5 級"</b>" \n- 在通知清單頂部顯示 \n- 允許全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 4 級"</b>" \n- 阻止全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 3 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n\n"<b>"第 2 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n\n"<b>"第 1 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n- 從上鎖畫面和狀態列中隱藏 \n- 在通知清單底部顯示 \n\n"<b>"第 0 級"</b>" \n- 封鎖所有應用程式通知"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"通知"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"您不會再看到這些通知"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。掂一下指紋感應器就可以驗證。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"不會自動連線至流動數據"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有連線"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網絡"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"沒有可用的網絡"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"網絡詳細資料"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"輕按網絡以連線"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"解鎖即可查看網絡"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜尋網絡…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"無法連接網絡"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"目前系統不會自動連線至 Wi-Fi"</string> + <string name="see_all_networks" msgid="3773666844913168122">"顯示全部"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切換網絡,請中斷以太網連線"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"為改善裝置的使用體驗,應用程式和服務仍可隨時掃瞄 Wi-Fi 網絡 (即使 Wi-Fi 已關閉)。您可在 Wi-Fi 掃瞄設定中變更此設定。"<annotation id="link">"變更"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index df84fb0699c9..a23ec38a6327 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"這麼做可允許所有應用程式和服務使用麥克風。"</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"這麼做可允許所有應用程式和服務使用相機。"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"這麼做可允許所有應用程式和服務使用相機或麥克風。"</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充飽"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"電源通知控制項"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"開啟"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"關閉"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已開啟 - 依臉部方向旋轉"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"只要使用電源通知控制項,你就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n"<b>"等級 5"</b>" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 4"</b>" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 3"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n"<b>"等級 2"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n"<b>"等級 1"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n"<b>"等級 0"</b>" \n- 封鎖應用程式的所有通知"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"通知"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"你不會再看到這些通知"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。輕觸指紋感應器即可進行驗證。"</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"系統將不會自動使用行動數據連線"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有網路連線"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網路"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"沒有可用的網路"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"網路詳細資料"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"輕觸要連線的網路"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"解鎖螢幕即可查看網路"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜尋網路…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"無法連上網路"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"目前不會自動連上 Wi-Fi"</string> + <string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切換網路,請中斷乙太網路連線"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"為提升裝置的使用體驗,應用程式和服務仍可隨時掃描 Wi‑Fi 網路,即使 Wi-Fi 連線功能處於關閉狀態時亦然。你可以前往「掃描 Wi-Fi」設定進行變更。"<annotation id="link">"變更"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index fe97daa7682e..983e2f751fdd 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> @@ -434,7 +435,7 @@ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa imakrofoni yakho."</string> <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho."</string> <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho noma imakrofoni."</string> - <string name="media_seamless_remote_device" msgid="177033467332920464">"Idivayisi"</string> + <string name="media_seamless_other_device" msgid="4654849800789196737">"Enye idivayisi"</string> <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string> <string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kushajiwe"</string> <string name="expanded_header_battery_charging" msgid="1717522253171025549">"Iyashaja"</string> @@ -709,6 +710,7 @@ <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Izilawuli zesaziso zamandla"</string> <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Vuliwe"</string> <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Valiwe"</string> + <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Vuliwe - Kususelwe kubuso"</string> <string name="power_notification_controls_description" msgid="1334963837572708952">"Ngezilawuli zesaziso zamandla, ungasetha ileveli ebalulekile kusuka ku-0 kuya ku-5 kusuka kuzaziso zohlelo lokusebenza. \n\n"<b>"Ileveli 5"</b>" \n- Ibonisa phezulu kuhlu lwesaziso \n- Vumela ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 4"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 3"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n\n"<b>"Ileveli 2"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo nokudlidliza \n\n"<b>"Ileveli 1"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo noma ukudlidliza \n- Fihla kusuka kusikrini sokukhiya nebha yesimo \n- Bonisa phansi kohlu lwesaziso \n\n"<b>"Ileveli 0"</b>" \n- Vimbela zonke izaziso kusuka kuhlelo lokusebenza"</string> <string name="notification_header_default_channel" msgid="225454696914642444">"Izaziso"</string> <string name="notification_channel_disabled" msgid="928065923928416337">"Ngeke usabona lezi zaziso"</string> @@ -1161,4 +1163,21 @@ <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Sebenzisa izigxivizo zeminwe ukuvula"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string> <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string> + <string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string> + <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string> + <string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string> + <string name="mobile_data_off_summary" msgid="3663995422004150567">"Idatha yeselula ngeke ikwazi ukuxhuma ngokuzenzekelayo"</string> + <string name="mobile_data_no_connection" msgid="1713872434869947377">"Alukho uxhumano"</string> + <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Awekho amanye amanethiwekhi atholakalayo"</string> + <string name="all_network_unavailable" msgid="4112774339909373349">"Awekho amanethiwekhi atholakalayo"</string> + <string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string> + <string name="pref_title_network_details" msgid="1639455355897668883">"Imininingwane yenethiwekhi"</string> + <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Thepha inethiwekhi ukuze uxhume"</string> + <string name="unlock_to_view_networks" msgid="5072880496312015676">"Vula ukuze ubuke amanethiwekhi"</string> + <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Iseshela amanethiwekhi…"</string> + <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Yehlulekile ukuxhuma kunethiwekhi"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"I-Wi-Fi ngeke ixhume ngokuzenzakalelayo okwamanje"</string> + <string name="see_all_networks" msgid="3773666844913168122">"Bona konke"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ukuze ushintshe amanethiwekhi, nqamula i-ethernet"</string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ukuze kuthuthukiswe ukuzizwela kwedivayisi, ama-app namasevisi kusengakwazi ukuskena amanethiwekhi we-Wi-Fi noma kunini, ngisho noma i-Wi-Fi ivaliwe, Ungashintsha lokhu kumasethingi Wokuskena i-Wi-Fi. "<annotation id="link">"Shintsha"</annotation></string> </resources> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index b5337d363e12..3121ce37490a 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -69,6 +69,10 @@ <declare-styleable name="DateView"> <attr name="datePattern" format="string" /> </declare-styleable> + <declare-styleable name="VariableDateView"> + <attr name="longDatePattern" format="string" /> + <attr name="shortDatePattern" format="string" /> + </declare-styleable> <declare-styleable name="PseudoGridView"> <attr name="numColumns" format="integer" /> <attr name="verticalSpacing" format="dimension" /> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 2260d2175268..f539b0cf68a1 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -16,7 +16,7 @@ * limitations under the License. */ --> -<resources> +<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <drawable name="notification_number_text_color">#ffffffff</drawable> <drawable name="ticker_background_color">#ff1d1d1d</drawable> <drawable name="system_bar_background">@color/system_bar_background_opaque</drawable> @@ -187,10 +187,8 @@ <!-- UDFPS colors --> <color name="udfps_enroll_icon">#000000</color> <!-- 100% black --> <color name="udfps_moving_target_fill">#cc4285f4</color> <!-- 80% blue --> - <color name="udfps_enroll_progress">#ff669DF6</color> <!-- 100% blue --> - - <!-- Logout button --> - <color name="logout_button_bg_color">#ccffffff</color> + <color name="udfps_enroll_progress">#ff669DF6</color> <!-- blue 400 --> + <color name="udfps_enroll_progress_help">#ffEE675C</color> <!-- red 400 --> <!-- Color for the Assistant invocation lights --> <color name="default_invocation_lights_color">#ffffffff</color> <!-- white --> @@ -281,4 +279,16 @@ <color name="wallet_card_border">#33FFFFFF</color> <color name="people_tile_background">@android:color/system_accent2_50</color> + + <!-- Internet Dialog --> + <!-- Material next state on color--> + <color name="settingslib_state_on_color">@color/settingslib_state_on</color> + <!-- Material next state off color--> + <color name="settingslib_state_off_color">@color/settingslib_state_off</color> + <!-- Material next track on color--> + <color name="settingslib_track_on_color">@color/settingslib_track_on</color> + <!-- Material next track off color--> + <color name="settingslib_track_off_color">@color/settingslib_track_off</color> + <color name="connected_network_primary_color">#191C18</color> + <color name="connected_network_secondary_color">#41493D</color> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 78db2a8a3485..c231afc41953 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -90,7 +90,7 @@ <dimen name="status_bar_left_clock_starting_padding">0dp</dimen> <!-- End padding for left-aligned status bar clock --> - <dimen name="status_bar_left_clock_end_padding">7dp</dimen> + <dimen name="status_bar_left_clock_end_padding">2dp</dimen> <!-- Spacing after the wifi signals that is present if there are any icons following it. --> <dimen name="status_bar_wifi_signal_spacer_width">2.5dp</dimen> @@ -331,11 +331,10 @@ <dimen name="global_screenshot_x_scale">80dp</dimen> <dimen name="screenshot_bg_protection_height">242dp</dimen> <dimen name="screenshot_preview_elevation">4dp</dimen> - <dimen name="screenshot_offset_y">24dp</dimen> + <dimen name="screenshot_offset_y">8dp</dimen> <dimen name="screenshot_offset_x">16dp</dimen> <dimen name="screenshot_dismiss_button_tappable_size">48dp</dimen> <dimen name="screenshot_dismiss_button_margin">8dp</dimen> - <dimen name="screenshot_action_container_offset_y">16dp</dimen> <dimen name="screenshot_action_container_corner_radius">18dp</dimen> <dimen name="screenshot_action_container_padding_vertical">4dp</dimen> <dimen name="screenshot_action_container_margin_horizontal">8dp</dimen> @@ -744,9 +743,7 @@ <!-- The margin between the status view and the notifications on Keyguard.--> <dimen name="keyguard_status_view_bottom_margin">20dp</dimen> <!-- Minimum margin between clock and status bar --> - <dimen name="keyguard_clock_top_margin">36dp</dimen> - <!-- The margin between top of clock and bottom of lock icon. --> - <dimen name="keyguard_clock_lock_margin">16dp</dimen> + <dimen name="keyguard_clock_top_margin">18dp</dimen> <!-- The amount to shift the clocks during a small/large transition --> <dimen name="keyguard_clock_switch_y_shift">10dp</dimen> <!-- When large clock is showing, offset the smartspace by this amount --> @@ -1150,9 +1147,9 @@ <dimen name="default_burn_in_prevention_offset">15dp</dimen> <!-- The maximum offset for the under-display fingerprint sensor (UDFPS) icon in either - direction that elements aer moved to prevent burn-in on AOD--> - <dimen name="udfps_burn_in_offset_x">2dp</dimen> - <dimen name="udfps_burn_in_offset_y">8dp</dimen> + direction that elements are moved to prevent burn-in on AOD--> + <dimen name="udfps_burn_in_offset_x">7px</dimen> + <dimen name="udfps_burn_in_offset_y">28px</dimen> <dimen name="corner_size">8dp</dimen> <dimen name="top_padding">0dp</dimen> @@ -1243,10 +1240,7 @@ <integer name="wired_charging_keyguard_text_animation_distance">-30</integer> <!-- Logout button --> - <dimen name="logout_button_layout_height">32dp</dimen> - <dimen name="logout_button_padding_horizontal">16dp</dimen> - <dimen name="logout_button_margin_bottom">12dp</dimen> - <dimen name="logout_button_corner_radius">4dp</dimen> + <dimen name="logout_button_corner_radius">50dp</dimen> <!-- Blur radius on status bar window and power menu --> <dimen name="min_window_blur_radius">1px</dimen> @@ -1277,7 +1271,7 @@ <dimen name="ongoing_appops_dialog_circle_size">32dp</dimen> - <dimen name="ongoing_appops_dialog_icon_size">20dp</dimen> + <dimen name="ongoing_appops_dialog_icon_size">16dp</dimen> <dimen name="ongoing_appops_dialog_side_padding">16dp</dimen> @@ -1299,8 +1293,6 @@ <dimen name="qs_media_action_margin">12dp</dimen> <dimen name="qs_seamless_height">24dp</dimen> <dimen name="qs_seamless_icon_size">12dp</dimen> - <dimen name="qs_seamless_fallback_icon_size">@dimen/qs_seamless_icon_size</dimen> - <dimen name="qs_seamless_fallback_margin">20dp</dimen> <dimen name="qs_footer_horizontal_margin">22dp</dimen> <dimen name="qs_media_disabled_seekbar_height">1dp</dimen> <dimen name="qs_media_enabled_seekbar_height">2dp</dimen> @@ -1310,6 +1302,7 @@ <!-- Size of Smartspace media recommendations cards in the QSPanel carousel --> <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen> <dimen name="qs_aa_media_rec_album_size_expanded">76dp</dimen> + <dimen name="qs_aa_media_gradient_bg_width">32dp</dimen> <dimen name="qs_aa_media_rec_album_margin">8dp</dimen> <dimen name="qs_aa_media_rec_album_margin_vert">4dp</dimen> <dimen name="qq_aa_media_rec_header_text_size">16sp</dimen> @@ -1590,4 +1583,42 @@ <!-- The padding between the icon and the text. --> <dimen name="ongoing_call_chip_icon_text_padding">4dp</dimen> <dimen name="ongoing_call_chip_corner_radius">28dp</dimen> + + <!-- Internet panel related dimensions --> + <dimen name="internet_dialog_list_margin">12dp</dimen> + <dimen name="internet_dialog_list_max_height">646dp</dimen> + <dimen name="internet_dialog_list_max_width">@dimen/match_parent</dimen> + + <!-- Signal icon in internet dialog --> + <dimen name="signal_strength_icon_size">24dp</dimen> + + <!-- Internet dialog related dimensions --> + <dimen name="internet_dialog_corner_radius">24dp</dimen> + <!-- End margin of network layout --> + <dimen name="internet_dialog_network_layout_margin">16dp</dimen> + <!-- Size of switch bar in internet dialog --> + <dimen name="settingslib_switchbar_margin">16dp</dimen> + <!-- Minimum width of switch --> + <dimen name="settingslib_min_switch_width">52dp</dimen> + <!-- Size of layout margin left --> + <dimen name="settingslib_switchbar_padding_left">20dp</dimen> + <!-- Size of layout margin right --> + <dimen name="settingslib_switchbar_padding_right">20dp</dimen> + <!-- Radius of switch bar --> + <dimen name="settingslib_switch_bar_radius">35dp</dimen> + <!-- Margin of switch thumb --> + <dimen name="settingslib_switch_thumb_margin">4dp</dimen> + <!-- Size of switch thumb --> + <dimen name="settingslib_switch_thumb_size">20dp</dimen> + <!-- Width of switch track --> + <dimen name="settingslib_switch_track_width">52dp</dimen> + <!-- Height of switch track --> + <dimen name="settingslib_switch_track_height">28dp</dimen> + <!-- Radius of switch track --> + <dimen name="settingslib_switch_track_radius">35dp</dimen> + + <!-- Height percentage of the parent container occupied by the communal view --> + <item name="communal_source_height_percentage" format="float" type="dimen">0.80</item> + + <dimen name="drag_and_drop_icon_size">70dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index a67021611812..4ad4fa9d0854 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] --> @@ -1006,7 +1008,7 @@ <string name="sensor_privacy_start_use_mic_camera_dialog_content">This unblocks access for all apps and services allowed to use your camera or microphone.</string> <!-- Default name for the media device shown in the output switcher when the name is not available [CHAR LIMIT=30] --> - <string name="media_seamless_remote_device">Device</string> + <string name="media_seamless_other_device">Other device</string> <!-- QuickStep: Accessibility to toggle overview [CHAR LIMIT=40] --> <string name="quick_step_accessibility_toggle_overview">Toggle Overview</string> @@ -1777,6 +1779,8 @@ <string name="tuner_full_importance_settings">Power notification controls</string> <string name="tuner_full_importance_settings_on">On</string> <string name="tuner_full_importance_settings_off">Off</string> + <!-- [CHAR LIMIT=NONE] Notification camera based rotation enabled description --> + <string name="rotation_lock_camera_rotation_on">On - Face-based</string> <string name="power_notification_controls_description">With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n<b>Level 5</b> \n- Show at the top of the notification list @@ -2992,4 +2996,43 @@ <string name="global_actions_change_description" translatable="false"><xliff:g>%1$s</xliff:g></string> <!-- URL for more information about changes in global actions --> <string name="global_actions_change_url" translatable="false"></string> + + <!-- Provider Model: Default title of the mobile network in the mobile layout. [CHAR LIMIT=50] --> + <string name="mobile_data_settings_title">Mobile data</string> + <!-- Provider Model: Summary text separator for preferences including a short description + (eg. "Connected / 5G"). [CHAR LIMIT=50] --> + <string name="preference_summary_default_combination"><xliff:g id="state" example="Connected">%1$s</xliff:g> / <xliff:g id="networkMode" example="LTE">%2$s</xliff:g></string> + <!-- Provider Model: + Summary indicating that a SIM has an active mobile data connection [CHAR LIMIT=50] --> + <string name="mobile_data_connection_active">Connected</string> + <!-- Provider Model: + Summary indicating that a SIM has no mobile data connection [CHAR LIMIT=50] --> + <string name="mobile_data_off_summary">Mobile data won\u0027t auto\u2011connect</string> + <!-- Provider Model: + Summary indicating that a active SIM and no network available [CHAR LIMIT=50] --> + <string name="mobile_data_no_connection">No connection</string> + <!-- Provider Model: Summary indicating that no other networks available [CHAR LIMIT=50] --> + <string name="non_carrier_network_unavailable">No other networks available</string> + <!-- Provider Model: Summary indicating that no networks available [CHAR LIMIT=50] --> + <string name="all_network_unavailable">No networks available</string> + <!-- Provider Model: Panel title text for turning on the Wi-Fi networks. [CHAR LIMIT=40] --> + <string name="turn_on_wifi">Wi\u2011Fi</string> + <!-- Provider Model: Title for detail page of wifi network [CHAR LIMIT=30] --> + <string name="pref_title_network_details" msgid="7329759534269363308">"Network details"</string> + <!-- Provider Model: Panel subtitle for tapping a network to connect to internet. [CHAR LIMIT=60] --> + <string name="tap_a_network_to_connect">Tap a network to connect</string> + <!-- Provider Model: Panel subtitle for unlocking screen to view networks. [CHAR LIMIT=60] --> + <string name="unlock_to_view_networks">Unlock to view networks</string> + <!-- Provider Model: Wi-Fi settings. text displayed when Wi-Fi is on and network list is empty [CHAR LIMIT=50]--> + <string name="wifi_empty_list_wifi_on">Searching for networks\u2026</string> + <!-- Provider Model: Failure notification for connect --> + <string name="wifi_failed_connect_message">Failed to connect to network</string> + <!-- Provider Model: Toast message for when the user selects cellular as the internet provider and Wi-Fi auto-connect is temporarily disabled [CHAR LIMIT=60]--> + <string name="wifi_wont_autoconnect_for_now">Wi\u2011Fi won\u2019t auto-connect for now</string> + <!-- Provider Model: Title to see all the networks [CHAR LIMIT=50] --> + <string name="see_all_networks">See all</string> + <!-- Summary for warning to disconnect ethernet first then switch to other networks. [CHAR LIMIT=60] --> + <string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string> + <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi scanning is on. [CHAR LIMIT=NONE] --> + <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 51eabf60385e..93d60cce2915 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -416,7 +416,9 @@ </style> <!-- Overridden by values-television/styles.xml with tv-specific settings --> - <style name="volume_dialog_theme" parent="Theme.SystemUI"/> + <style name="volume_dialog_theme" parent="Theme.SystemUI"> + <item name="android:windowIsFloating">true</item> + </style> <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog" /> @@ -903,4 +905,108 @@ <!-- Setting a placeholder will avoid using the SystemUI icon on the splash screen. --> <item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_blank</item> </style> + + <style name="Animation.InternetDialog" parent="@android:style/Animation.InputMethod"> + </style> + + <style name="Widget.SliceView.Panel"> + <item name="titleSize">16sp</item> + <item name="rowStyle">@style/SliceRow</item> + <item name="android:background">?android:attr/colorBackgroundFloating</item> + </style> + + <style name="SliceRow"> + <!-- 2dp start padding for the start icon --> + <item name="titleItemStartPadding">2dp</item> + <item name="titleItemEndPadding">0dp</item> + + <!-- Padding between content and the start icon is 14dp --> + <item name="contentStartPadding">14dp</item> + <!-- Padding between content and end items is 16dp --> + <item name="contentEndPadding">16dp</item> + + <!-- Both side margins of end item are 16dp --> + <item name="endItemStartPadding">16dp</item> + <item name="endItemEndPadding">16dp</item> + + <!-- Both side margins of bottom divider are 12dp --> + <item name="bottomDividerStartPadding">12dp</item> + <item name="bottomDividerEndPadding">12dp</item> + + <item name="actionDividerHeight">32dp</item> + </style> + + <style name="Theme.SystemUI.Dialog.Internet"> + <item name="android:windowBackground">@drawable/internet_dialog_background</item> + </style> + + <style name="MainSwitch.Settingslib" parent="@android:style/Theme.DeviceDefault"> + <item name="android:switchMinWidth">@dimen/settingslib_min_switch_width</item> + </style> + + <style name="TrimmedHorizontalProgressBar" + parent="android:Widget.Material.ProgressBar.Horizontal"> + <item name="android:indeterminateDrawable"> + @drawable/progress_indeterminate_horizontal_material_trimmed + </item> + <item name="android:minHeight">4dp</item> + <item name="android:maxHeight">4dp</item> + </style> + + <!-- Internet Dialog --> + <style name="InternetDialog"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_gravity">center_vertical|start</item> + <item name="android:layout_marginStart">@dimen/internet_dialog_network_layout_margin</item> + </style> + + <style name="InternetDialog.Network"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">88dp</item> + <item name="android:layout_marginEnd">@dimen/internet_dialog_network_layout_margin</item> + <item name="android:paddingStart">22dp</item> + <item name="android:paddingEnd">22dp</item> + <item name="android:orientation">horizontal</item> + <item name="android:focusable">true</item> + <item name="android:clickable">true</item> + </style> + + <style name="InternetDialog.NetworkTitle"> + <item name="android:layout_marginEnd">7dp</item> + <item name="android:ellipsize">end</item> + <item name="android:textAppearance">@style/TextAppearance.InternetDialog</item> + </style> + + <style name="InternetDialog.NetworkTitle.Active"> + <item name="android:textAppearance">@style/TextAppearance.InternetDialog.Active</item> + </style> + + <style name="InternetDialog.NetworkSummary"> + <item name="android:layout_marginEnd">34dp</item> + <item name="android:ellipsize">end</item> + <item name="android:textAppearance">@style/TextAppearance.InternetDialog.Secondary</item> + </style> + + <style name="InternetDialog.NetworkSummary.Active"> + <item name="android:textAppearance">@style/TextAppearance.InternetDialog.Secondary.Active + </item> + </style> + + <style name="TextAppearance.InternetDialog"> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + <item name="android:textSize">16sp</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textDirection">locale</item> + </style> + + <style name="TextAppearance.InternetDialog.Secondary"> + <item name="android:textSize">14sp</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> + </style> + + <style name="TextAppearance.InternetDialog.Active"/> + + <style name="TextAppearance.InternetDialog.Secondary.Active"/> + </resources> diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml index d6c6a60d56b8..c3510b61e68a 100644 --- a/packages/SystemUI/res/xml/media_collapsed.xml +++ b/packages/SystemUI/res/xml/media_collapsed.xml @@ -44,23 +44,6 @@ /> <Constraint - android:id="@+id/media_seamless_fallback" - android:layout_width="@dimen/qs_seamless_fallback_icon_size" - android:layout_height="@dimen/qs_seamless_fallback_icon_size" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginStart="@dimen/qs_center_guideline_padding" - android:layout_marginEnd="@dimen/qs_seamless_fallback_margin" - android:alpha="0.5" - android:visibility="gone" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@id/center_horizontal_guideline" - app:layout_constraintStart_toEndOf="@id/center_vertical_guideline" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Constraint android:id="@+id/album_art" android:layout_width="@dimen/qs_media_album_size_small" android:layout_height="@dimen/qs_media_album_size_small" diff --git a/packages/SystemUI/res/xml/media_expanded.xml b/packages/SystemUI/res/xml/media_expanded.xml index 0e284e6ad631..6b83aae38e15 100644 --- a/packages/SystemUI/res/xml/media_expanded.xml +++ b/packages/SystemUI/res/xml/media_expanded.xml @@ -45,22 +45,6 @@ android:layout_marginBottom="4dp" /> <Constraint - android:id="@+id/media_seamless_fallback" - android:layout_width="@dimen/qs_seamless_fallback_icon_size" - android:layout_height="@dimen/qs_seamless_fallback_icon_size" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="16dp" - android:layout_marginStart="@dimen/qs_center_guideline_padding" - android:layout_marginEnd="@dimen/qs_seamless_fallback_margin" - android:alpha="0.5" - android:visibility="gone" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toEndOf="@id/center_vertical_guideline" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Constraint android:id="@+id/album_art" android:layout_width="@dimen/qs_media_album_size" android:layout_height="@dimen/qs_media_album_size" diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml index 5c41ad82bd0b..b6258d1c71eb 100644 --- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml +++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml @@ -19,25 +19,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> <Constraint - android:id="@+id/recommendation_card_icon" - android:layout_width="@dimen/qs_media_icon_size" - android:layout_height="@dimen/qs_media_icon_size" - android:layout_marginTop="@dimen/qs_media_padding" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0" /> - - <Constraint - android:id="@+id/recommendation_card_text" - android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0" /> - - <Constraint android:id="@+id/media_cover1_container" android:layout_width="0dp" android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml index 8a3d5ca75a77..2fb33415e0df 100644 --- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml +++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml @@ -19,25 +19,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> <Constraint - android:id="@+id/recommendation_card_icon" - android:layout_width="@dimen/qs_media_icon_size" - android:layout_height="@dimen/qs_media_icon_size" - android:layout_marginTop="@dimen/qs_media_padding" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0" /> - - <Constraint - android:id="@+id/recommendation_card_text" - android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0" /> - - <Constraint android:id="@+id/media_cover1_container" android:layout_width="0dp" android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java index 92f89d6b90fd..a383cab94c36 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -20,12 +20,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.graphics.Color; import android.icu.text.NumberFormat; +import androidx.annotation.VisibleForTesting; + import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.BatteryController; @@ -67,20 +71,20 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie BroadcastDispatcher broadcastDispatcher, BatteryController batteryController, KeyguardUpdateMonitor keyguardUpdateMonitor, - KeyguardBypassController bypassController) { + KeyguardBypassController bypassController, + @Main Resources resources + ) { super(view); mStatusBarStateController = statusBarStateController; - mIsDozing = mStatusBarStateController.isDozing(); - mDozeAmount = mStatusBarStateController.getDozeAmount(); mBroadcastDispatcher = broadcastDispatcher; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mBypassController = bypassController; mBatteryController = batteryController; mBurmeseNumerals = mBurmeseNf.format(FORMAT_NUMBER); - mBurmeseLineSpacing = getContext().getResources().getFloat( + mBurmeseLineSpacing = resources.getFloat( R.dimen.keyguard_clock_line_spacing_scale_burmese); - mDefaultLineSpacing = getContext().getResources().getFloat( + mDefaultLineSpacing = resources.getFloat( R.dimen.keyguard_clock_line_spacing_scale); } @@ -106,7 +110,7 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie } }; - private final StatusBarStateController.StateListener mStatusBarStatePersistentListener = + private final StatusBarStateController.StateListener mStatusBarStateListener = new StatusBarStateController.StateListener() { @Override public void onDozeAmountChanged(float linear, float eased) { @@ -144,11 +148,11 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); mDozeAmount = mStatusBarStateController.getDozeAmount(); + mIsDozing = mStatusBarStateController.isDozing() || mDozeAmount != 0; mBatteryController.addCallback(mBatteryCallback); mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); - mStatusBarStateController.removeCallback(mStatusBarStatePersistentListener); - mStatusBarStateController.addCallback(mStatusBarStatePersistentListener); + mStatusBarStateController.addCallback(mStatusBarStateListener); refreshTime(); initColors(); @@ -160,9 +164,7 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie mBroadcastDispatcher.unregisterReceiver(mLocaleBroadcastReceiver); mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback); mBatteryController.removeCallback(mBatteryCallback); - if (!mView.isAttachedToWindow()) { - mStatusBarStateController.removeCallback(mStatusBarStatePersistentListener); - } + mStatusBarStateController.removeCallback(mStatusBarStateListener); } /** Animate the clock appearance */ @@ -191,6 +193,14 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie mView.refreshFormat(); } + /** + * Return locallly stored dozing state. + */ + @VisibleForTesting + public boolean isDozing() { + return mIsDozing; + } + private void updateLocale() { Locale currLocale = Locale.getDefault(); if (!Objects.equals(currLocale, mLocale)) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index f4a3fb236ffa..7a01b4e8c971 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -20,6 +20,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.WallpaperManager; +import android.content.res.Resources; import android.text.TextUtils; import android.view.View; import android.widget.FrameLayout; @@ -30,6 +31,7 @@ import com.android.keyguard.clock.ClockManager; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.plugins.ClockPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -65,18 +67,22 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS private final BroadcastDispatcher mBroadcastDispatcher; private final BatteryController mBatteryController; private final LockscreenSmartspaceController mSmartspaceController; + private final Resources mResources; /** * Clock for both small and large sizes */ private AnimatableClockController mClockViewController; - private FrameLayout mClockFrame; + private FrameLayout mClockFrame; // top aligned clock private AnimatableClockController mLargeClockViewController; - private FrameLayout mLargeClockFrame; + private FrameLayout mLargeClockFrame; // centered clock private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final KeyguardBypassController mBypassController; + private int mLargeClockTopMargin = 0; + private int mKeyguardClockTopMargin = 0; + /** * Listener for changes to the color palette. * @@ -113,7 +119,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS KeyguardBypassController bypassController, LockscreenSmartspaceController smartspaceController, KeyguardUnlockAnimationController keyguardUnlockAnimationController, - SmartspaceTransitionController smartspaceTransitionController) { + SmartspaceTransitionController smartspaceTransitionController, + @Main Resources resources) { super(keyguardClockSwitch); mStatusBarStateController = statusBarStateController; mColorExtractor = colorExtractor; @@ -125,6 +132,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mKeyguardUpdateMonitor = keyguardUpdateMonitor; mBypassController = bypassController; mSmartspaceController = smartspaceController; + mResources = resources; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mSmartspaceTransitionController = smartspaceTransitionController; @@ -154,7 +162,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mBroadcastDispatcher, mBatteryController, mKeyguardUpdateMonitor, - mBypassController); + mBypassController, + mResources); mClockViewController.init(); mLargeClockViewController = @@ -164,7 +173,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mBroadcastDispatcher, mBatteryController, mKeyguardUpdateMonitor, - mBypassController); + mBypassController, + mResources); mLargeClockViewController.init(); } @@ -175,6 +185,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } mColorExtractor.addOnColorsChangedListener(mColorsListener); mView.updateColors(getGradientColors()); + mKeyguardClockTopMargin = + mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); if (mOnlyClock) { View ksa = mView.findViewById(R.id.keyguard_status_area); @@ -249,6 +261,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS */ public void onDensityOrFontScaleChanged() { mView.onDensityOrFontScaleChanged(); + mKeyguardClockTopMargin = + mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); updateClockLayout(); } @@ -257,9 +271,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS if (mSmartspaceController.isEnabled()) { RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); - lp.topMargin = getContext().getResources().getDimensionPixelSize( + mLargeClockTopMargin = getContext().getResources().getDimensionPixelSize( R.dimen.keyguard_large_clock_top_margin); + lp.topMargin = mLargeClockTopMargin; mLargeClockFrame.setLayoutParams(lp); + } else { + mLargeClockTopMargin = 0; } } @@ -369,6 +386,28 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } } + /** + * Get y-bottom position of the currently visible clock on the keyguard. + * We can't directly getBottom() because clock changes positions in AOD for burn-in + */ + int getClockBottom(int statusBarHeaderHeight) { + if (mLargeClockFrame.getVisibility() == View.VISIBLE) { + View clock = mLargeClockFrame.findViewById( + com.android.systemui.R.id.animatable_clock_view_large); + int frameHeight = mLargeClockFrame.getHeight(); + int clockHeight = clock.getHeight(); + return frameHeight / 2 + clockHeight / 2; + } else { + return mClockFrame.findViewById( + com.android.systemui.R.id.animatable_clock_view).getHeight() + + statusBarHeaderHeight + mKeyguardClockTopMargin; + } + } + + boolean isClockTopAligned() { + return mLargeClockFrame.getVisibility() != View.VISIBLE; + } + private void updateAodIcons() { NotificationIconContainer nic = (NotificationIconContainer) mView.findViewById( diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 72e502816534..6b3e9c27c25f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -185,6 +185,20 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV } /** + * Get y-bottom position of the currently visible clock. + */ + public int getClockBottom(int statusBarHeaderHeight) { + return mKeyguardClockSwitchController.getClockBottom(statusBarHeaderHeight); + } + + /** + * @return true if the currently displayed clock is top aligned (as opposed to center aligned) + */ + public boolean isClockTopAligned() { + return mKeyguardClockSwitchController.isClockTopAligned(); + } + + /** * Set whether the view accessibility importance mode. */ public void setStatusAccessibilityImportance(int mode) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java index 28a54d56b071..e115c342c4fe 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java @@ -132,8 +132,7 @@ public class KeyguardVisibilityHelper { .alpha(1f) .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable) .start(); - } else if (mUnlockedScreenOffAnimationController - .isScreenOffLightRevealAnimationPlaying()) { + } else if (mUnlockedScreenOffAnimationController.shouldAnimateInKeyguard()) { mKeyguardViewVisibilityAnimating = true; // Ask the screen off animation controller to animate the keyguard visibility for us diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java index 5c34bebdaa4e..ef4353b93179 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java @@ -27,6 +27,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.android.settingslib.Utils; import com.android.systemui.Dumpable; @@ -47,6 +48,7 @@ public class LockIconView extends FrameLayout implements Dumpable { private ImageView mBgView; private int mLockIconColor; + private boolean mUseBackground = false; public LockIconView(Context context, AttributeSet attrs) { super(context, attrs); @@ -60,8 +62,8 @@ public class LockIconView extends FrameLayout implements Dumpable { mBgView = findViewById(R.id.lock_icon_bg); } - void updateColorAndBackgroundVisibility(boolean useBackground) { - if (useBackground && mLockIcon.getDrawable() != null) { + void updateColorAndBackgroundVisibility() { + if (mUseBackground && mLockIcon.getDrawable() != null) { mLockIconColor = Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary); mBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg)); @@ -77,6 +79,9 @@ public class LockIconView extends FrameLayout implements Dumpable { void setImageDrawable(Drawable drawable) { mLockIcon.setImageDrawable(drawable); + + if (!mUseBackground) return; + if (drawable == null) { mBgView.setVisibility(View.INVISIBLE); } else { @@ -84,6 +89,18 @@ public class LockIconView extends FrameLayout implements Dumpable { } } + /** + * Whether or not to render the lock icon background. Mainly used for UDPFS. + */ + public void setUseBackground(boolean useBackground) { + mUseBackground = useBackground; + updateColorAndBackgroundVisibility(); + } + + /** + * Set the location of the lock icon. + */ + @VisibleForTesting public void setCenterLocation(@NonNull PointF center, int radius) { mLockIconCenter = center; mRadius = radius; diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index a41997ce3107..52ebf2fa09d0 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -49,6 +49,7 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.biometrics.AuthRippleController; import com.android.systemui.biometrics.UdfpsController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; @@ -72,7 +73,8 @@ import javax.inject.Inject; /** * Controls when to show the LockIcon affordance (lock/unlocked icon or circle) on lock screen. * - * This view will only be shown if the user has UDFPS or FaceAuth enrolled + * For devices with UDFPS, the lock icon will show at the sensor location. Else, the lock + * icon will show a set distance from the bottom of the device. */ @StatusBarComponent.StatusBarScope public class LockIconViewController extends ViewController<LockIconView> implements Dumpable { @@ -106,6 +108,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull private CharSequence mUnlockedLabel; @NonNull private CharSequence mLockedLabel; @Nullable private final Vibrator mVibrator; + @Nullable private final AuthRippleController mAuthRippleController; private boolean mIsDozing; private boolean mIsBouncerShowing; @@ -149,7 +152,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull AccessibilityManager accessibilityManager, @NonNull ConfigurationController configurationController, @NonNull @Main DelayableExecutor executor, - @Nullable Vibrator vibrator + @Nullable Vibrator vibrator, + @Nullable AuthRippleController authRippleController ) { super(view); mStatusBarStateController = statusBarStateController; @@ -162,6 +166,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mConfigurationController = configurationController; mExecutor = executor; mVibrator = vibrator; + mAuthRippleController = authRippleController; final Context context = view.getContext(); mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp); @@ -340,7 +345,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme } private void updateColors() { - mView.updateColorAndBackgroundVisibility(mUdfpsSupported); + mView.updateColorAndBackgroundVisibility(); } private void updateConfiguration() { @@ -420,6 +425,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme boolean wasUdfpsEnrolled = mUdfpsEnrolled; mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null; + mView.setUseBackground(mUdfpsSupported); + mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled(); if (wasUdfpsSupported != mUdfpsSupported || wasUdfpsEnrolled != mUdfpsEnrolled) { updateVisibility(); @@ -621,6 +628,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme // pre-emptively set to true to hide view mIsBouncerShowing = true; + if (mUdfpsSupported && mShowUnlockIcon && mAuthRippleController != null) { + mAuthRippleController.showRipple(FINGERPRINT); + } updateVisibility(); if (mOnGestureDetectedRunnable != null) { mOnGestureDetectedRunnable.run(); diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java index 3a0357d2a284..4331f52eb1a2 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java @@ -16,7 +16,8 @@ package com.android.keyguard.dagger; -import com.android.systemui.statusbar.phone.UserAvatarView; +import android.widget.FrameLayout; + import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController; import dagger.BindsInstance; @@ -31,8 +32,7 @@ public interface KeyguardQsUserSwitchComponent { /** Simple factory for {@link KeyguardUserSwitcherComponent}. */ @Subcomponent.Factory interface Factory { - KeyguardQsUserSwitchComponent build( - @BindsInstance UserAvatarView userAvatarView); + KeyguardQsUserSwitchComponent build(@BindsInstance FrameLayout userAvatarContainer); } /** Builds a {@link KeyguardQsUserSwitchController}. */ diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 76f30a80114a..00b33a416df4 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -65,6 +65,7 @@ import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.PowerUI; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.qs.ReduceBrightColorsController; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.recents.Recents; import com.android.systemui.screenrecord.RecordingController; @@ -364,6 +365,7 @@ public class Dependency { @Inject Lazy<UiEventLogger> mUiEventLogger; @Inject Lazy<FeatureFlags> mFeatureFlagsLazy; @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy; + @Inject Lazy<InternetDialogFactory> mInternetDialogFactory; @Inject public Dependency() { @@ -578,6 +580,7 @@ public class Dependency { mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get); mProviders.put(EdgeBackGestureHandler.Factory.class, mEdgeBackGestureHandlerFactoryLazy::get); + mProviders.put(InternetDialogFactory.class, mInternetDialogFactory::get); mProviders.put(UiEventLogger.class, mUiEventLogger::get); mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get); mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get); diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index a68f79604b25..8379ccf3154a 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -20,6 +20,8 @@ import android.app.WallpaperColors; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManager.DisplayListener; import android.os.Handler; import android.os.HandlerThread; import android.os.SystemClock; @@ -29,7 +31,6 @@ import android.util.ArraySet; import android.util.Log; import android.util.MathUtils; import android.util.Size; -import android.view.DisplayInfo; import android.view.SurfaceHolder; import android.view.WindowManager; @@ -90,7 +91,7 @@ public class ImageWallpaper extends WallpaperService { mMiniBitmap = null; } - class GLEngine extends Engine { + class GLEngine extends Engine implements DisplayListener { // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin) // set min to 64 px (CTS covers this), please refer to ag/4867989 for detail. @VisibleForTesting @@ -102,15 +103,15 @@ public class ImageWallpaper extends WallpaperService { private EglHelper mEglHelper; private final Runnable mFinishRenderingTask = this::finishRendering; private boolean mNeedRedraw; - private int mWidth = 1; - private int mHeight = 1; + + private boolean mDisplaySizeValid = false; + private int mDisplayWidth = 1; + private int mDisplayHeight = 1; + private int mImgWidth = 1; private int mImgHeight = 1; - private float mPageWidth = 1.f; - private float mPageOffset = 1.f; - GLEngine() { - } + GLEngine() { } @VisibleForTesting GLEngine(Handler handler) { @@ -119,18 +120,29 @@ public class ImageWallpaper extends WallpaperService { @Override public void onCreate(SurfaceHolder surfaceHolder) { + Trace.beginSection("ImageWallpaper.Engine#onCreate"); mEglHelper = getEglHelperInstance(); // Deferred init renderer because we need to get wallpaper by display context. mRenderer = getRendererInstance(); setFixedSizeAllowed(true); updateSurfaceSize(); - Rect window = getDisplayContext() - .getSystemService(WindowManager.class) - .getCurrentWindowMetrics() - .getBounds(); - mHeight = window.height(); - mWidth = window.width(); mRenderer.setOnBitmapChanged(this::updateMiniBitmap); + getDisplayContext().getSystemService(DisplayManager.class) + .registerDisplayListener(this, mWorker.getThreadHandler()); + Trace.endSection(); + } + + @Override + public void onDisplayAdded(int displayId) { } + + @Override + public void onDisplayRemoved(int displayId) { } + + @Override + public void onDisplayChanged(int displayId) { + if (displayId == getDisplayContext().getDisplayId()) { + mDisplaySizeValid = false; + } } EglHelper getEglHelperInstance() { @@ -154,26 +166,10 @@ public class ImageWallpaper extends WallpaperService { if (pages == mPages) return; mPages = pages; if (mMiniBitmap == null || mMiniBitmap.isRecycled()) return; - updateShift(); mWorker.getThreadHandler().post(() -> computeAndNotifyLocalColors(new ArrayList<>(mColorAreas), mMiniBitmap)); } - private void updateShift() { - if (mImgHeight == 0) { - mPageOffset = 0; - mPageWidth = 1; - return; - } - // calculate shift - DisplayInfo displayInfo = new DisplayInfo(); - getDisplayContext().getDisplay().getDisplayInfo(displayInfo); - int screenWidth = displayInfo.getNaturalWidth(); - float imgWidth = Math.min(mImgWidth > 0 ? screenWidth / (float) mImgWidth : 1.f, 1.f); - mPageWidth = imgWidth; - mPageOffset = (1 - imgWidth) / (float) (mPages - 1); - } - private void updateMiniBitmap(Bitmap b) { if (b == null) return; int size = Math.min(b.getWidth(), b.getHeight()); @@ -203,13 +199,22 @@ public class ImageWallpaper extends WallpaperService { } @Override + public boolean shouldWaitForEngineShown() { + return true; + } + + @Override public void onDestroy() { + getDisplayContext().getSystemService(DisplayManager.class) + .unregisterDisplayListener(this); mMiniBitmap = null; mWorker.getThreadHandler().post(() -> { + Trace.beginSection("ImageWallpaper.Engine#onDestroy"); mRenderer.finish(); mRenderer = null; mEglHelper.finish(); mEglHelper = null; + Trace.endSection(); }); } @@ -268,6 +273,16 @@ public class ImageWallpaper extends WallpaperService { * (1-Wr)]. */ private RectF pageToImgRect(RectF area) { + if (!mDisplaySizeValid) { + Rect window = getDisplayContext() + .getSystemService(WindowManager.class) + .getCurrentWindowMetrics() + .getBounds(); + mDisplayWidth = window.width(); + mDisplayHeight = window.height(); + mDisplaySizeValid = true; + } + // Width of a page for the caller of this API. float virtualPageWidth = 1f / (float) mPages; float leftPosOnPage = (area.left % virtualPageWidth) / virtualPageWidth; @@ -275,12 +290,24 @@ public class ImageWallpaper extends WallpaperService { int currentPage = (int) Math.floor(area.centerX() / virtualPageWidth); RectF imgArea = new RectF(); + + if (mImgWidth == 0 || mImgHeight == 0 || mDisplayWidth <= 0 || mDisplayHeight <= 0) { + return imgArea; + } + imgArea.bottom = area.bottom; imgArea.top = area.top; + + float imageScale = Math.min(((float) mImgHeight) / mDisplayHeight, 1); + float mappedScreenWidth = mDisplayWidth * imageScale; + float pageWidth = Math.min(1.0f, + mImgWidth > 0 ? mappedScreenWidth / (float) mImgWidth : 1.f); + float pageOffset = (1 - pageWidth) / (float) (mPages - 1); + imgArea.left = MathUtils.constrain( - leftPosOnPage * mPageWidth + currentPage * mPageOffset, 0, 1); + leftPosOnPage * pageWidth + currentPage * pageOffset, 0, 1); imgArea.right = MathUtils.constrain( - rightPosOnPage * mPageWidth + currentPage * mPageOffset, 0, 1); + rightPosOnPage * pageWidth + currentPage * pageOffset, 0, 1); if (imgArea.left > imgArea.right) { // take full page imgArea.left = 0; @@ -293,7 +320,6 @@ public class ImageWallpaper extends WallpaperService { private List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas, Bitmap b) { List<WallpaperColors> colors = new ArrayList<>(areas.size()); - updateShift(); for (int i = 0; i < areas.size(); i++) { RectF area = pageToImgRect(areas.get(i)); if (area == null || !LOCAL_COLOR_BOUNDS.contains(area)) { @@ -322,8 +348,10 @@ public class ImageWallpaper extends WallpaperService { public void onSurfaceCreated(SurfaceHolder holder) { if (mWorker == null) return; mWorker.getThreadHandler().post(() -> { + Trace.beginSection("ImageWallpaper#onSurfaceCreated"); mEglHelper.init(holder, needSupportWideColorGamut()); mRenderer.onSurfaceCreated(); + Trace.endSection(); }); } @@ -340,9 +368,11 @@ public class ImageWallpaper extends WallpaperService { } private void drawFrame() { + Trace.beginSection("ImageWallpaper#drawFrame"); preRender(); requestRender(); postRender(); + Trace.endSection(); } public void preRender() { @@ -409,6 +439,7 @@ public class ImageWallpaper extends WallpaperService { // This method should only be invoked from worker thread. Trace.beginSection("ImageWallpaper#postRender"); scheduleFinishRendering(); + reportEngineShown(false /* waitForEngineShown */); Trace.endSection(); } diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index affad7a57d86..8c63f7bec23c 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -438,6 +438,12 @@ public class SwipeHelper implements Gefingerpoken { private boolean mCancelled; @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + mCallback.onBeginDrag(animView); + } + + @Override public void onAnimationCancel(Animator animation) { mCancelled = true; } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java index d8e80fe99331..0d7551ff66e9 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java @@ -30,7 +30,7 @@ import java.util.Optional; /** * A span that turns the text wrapped by annotation tag into the clickable link text. */ -class AnnotationLinkSpan extends ClickableSpan { +public class AnnotationLinkSpan extends ClickableSpan { private final Optional<View.OnClickListener> mClickListener; private AnnotationLinkSpan(View.OnClickListener listener) { @@ -50,7 +50,7 @@ class AnnotationLinkSpan extends ClickableSpan { * @param linkInfos used to attach the click action into the corresponding span * @return the text attached with the span */ - static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) { + public static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) { final SpannableString msg = new SpannableString(text); final Annotation[] spans = msg.getSpans(/* queryStart= */ 0, msg.length(), Annotation.class); @@ -78,12 +78,12 @@ class AnnotationLinkSpan extends ClickableSpan { /** * Data class to store the annotation and the click action. */ - static class LinkInfo { - static final String DEFAULT_ANNOTATION = "link"; + public static class LinkInfo { + public static final String DEFAULT_ANNOTATION = "link"; private final Optional<String> mAnnotation; private final Optional<View.OnClickListener> mListener; - LinkInfo(@NonNull String annotation, View.OnClickListener listener) { + public LinkInfo(@NonNull String annotation, View.OnClickListener listener) { mAnnotation = Optional.of(annotation); mListener = Optional.ofNullable(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java index 81a13a236685..408201558a9b 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java @@ -57,7 +57,9 @@ public class AssistOrbController { public void run() { mView.removeCallbacks(this); mView.show(false /* show */, true /* animate */, () -> { - mWindowManager.removeView(mView); + if (mView.isAttachedToWindow()) { + mWindowManager.removeView(mView); + } }); } }; diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt index c9e67715decb..5616a00592f2 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 @@ import com.android.systemui.people.widget.PeopleBackupHelper * 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/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 3f61d3c6af9a..fd37b3509a4e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -126,6 +126,7 @@ public class AuthContainerView extends LinearLayout boolean mCredentialAllowed; boolean mSkipIntro; long mOperationId; + long mRequestId; @BiometricMultiSensorMode int mMultiSensorConfig; } @@ -172,6 +173,12 @@ public class AuthContainerView extends LinearLayout return this; } + /** Unique id for this request. */ + public Builder setRequestId(long requestId) { + mConfig.mRequestId = requestId; + return this; + } + /** The multi-sensor mode. */ public Builder setMultiSensorConfig(@BiometricMultiSensorMode int multiSensorConfig) { mConfig.mMultiSensorConfig = multiSensorConfig; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index a4123c769d1e..0790af94f287 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -42,6 +42,7 @@ import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.hardware.fingerprint.IUdfpsHbmListener; import android.os.Bundle; @@ -49,6 +50,7 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; +import android.util.SparseBooleanArray; import android.view.MotionEvent; import android.view.WindowManager; @@ -76,6 +78,9 @@ import kotlin.Unit; /** * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the * appropriate biometric UI (e.g. BiometricDialogView). + * + * Also coordinates biometric-related things, such as UDFPS, with + * {@link com.android.keyguard.KeyguardUpdateMonitor} */ @SysUISingleton public class AuthController extends SystemUI implements CommandQueue.Callbacks, @@ -115,6 +120,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps; @Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps; + @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser; + private class BiometricTaskStackListener extends TaskStackListener { @Override public void onTaskStackChanged() { @@ -122,6 +129,21 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, } } + private final FingerprintStateListener mFingerprintStateListener = + new FingerprintStateListener() { + @Override + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { + Log.d(TAG, "onEnrollmentsChanged, userId: " + userId + + ", sensorId: " + sensorId + + ", hasEnrollments: " + hasEnrollments); + for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) { + if (prop.sensorId == sensorId) { + mUdfpsEnrolledForUser.put(userId, hasEnrollments); + } + } + } + }; + @NonNull private final IFingerprintAuthenticatorsRegisteredCallback mFingerprintAuthenticatorsRegisteredCallback = @@ -436,6 +458,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, mUdfpsControllerFactory = udfpsControllerFactory; mSidefpsControllerFactory = sidefpsControllerFactory; mWindowManager = windowManager; + mUdfpsEnrolledForUser = new SparseBooleanArray(); mOrientationListener = new BiometricOrientationEventListener(context, () -> { onOrientationChanged(); @@ -474,6 +497,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, if (mFingerprintManager != null) { mFingerprintManager.addAuthenticatorsRegisteredCallback( mFingerprintAuthenticatorsRegisteredCallback); + mFingerprintManager.registerFingerprintStateListener(mFingerprintStateListener); } mTaskStackListener = new BiometricTaskStackListener(); @@ -501,7 +525,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Override public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, - int userId, String opPackageName, long operationId, + int userId, long operationId, String opPackageName, long requestId, @BiometricMultiSensorMode int multiSensorConfig) { @Authenticators.Types final int authenticators = promptInfo.getAuthenticators(); @@ -515,6 +539,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, + ", credentialAllowed: " + credentialAllowed + ", requireConfirmation: " + requireConfirmation + ", operationId: " + operationId + + ", requestId: " + requestId + ", multiSensorConfig: " + multiSensorConfig); } SomeArgs args = SomeArgs.obtain(); @@ -526,6 +551,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, args.argi1 = userId; args.arg6 = opPackageName; args.arg7 = operationId; + args.arg8 = requestId; args.argi2 = multiSensorConfig; boolean skipAnimation = false; @@ -629,6 +655,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, if (mCurrentDialog == null) { // Could be possible if the caller canceled authentication after credential success // but before the client was notified. + if (DEBUG) Log.d(TAG, "dialog already gone"); return; } @@ -670,7 +697,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, return false; } - return mFingerprintManager.hasEnrolledTemplatesForAnySensor(userId, mUdfpsProps); + return mUdfpsEnrolledForUser.get(userId); } private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) { @@ -683,6 +710,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, final int userId = args.argi1; final String opPackageName = (String) args.arg6; final long operationId = (long) args.arg7; + final long requestId = (long) args.arg8; final @BiometricMultiSensorMode int multiSensorConfig = args.argi2; // Create a new dialog but do not replace the current one yet. @@ -695,6 +723,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, opPackageName, skipAnimation, operationId, + requestId, multiSensorConfig); if (newDialog == null) { @@ -772,7 +801,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds, boolean credentialAllowed, String opPackageName, - boolean skipIntro, long operationId, + boolean skipIntro, long operationId, long requestId, @BiometricMultiSensorMode int multiSensorConfig) { return new AuthContainerView.Builder(mContext) .setCallback(this) @@ -782,10 +811,15 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, .setOpPackageName(opPackageName) .setSkipIntro(skipIntro) .setOperationId(operationId) + .setRequestId(requestId) .setMultiSensorConfig(multiSensorConfig) .build(sensorIds, credentialAllowed, mFpProps, mFaceProps); } + /** + * AuthController callback used to receive signal for when biometric authenticators are + * registered. + */ public interface Callback { /** * Called when authenticators are registered. If authenticators are already diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 54f932184331..9d4a67dfddba 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -39,11 +39,9 @@ import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; import android.media.AudioAttributes; import android.os.Handler; -import android.os.Looper; 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; @@ -64,7 +62,6 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -72,10 +69,12 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; 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.HashSet; import java.util.Optional; @@ -93,7 +92,7 @@ import kotlin.Unit; * controls/manages all UDFPS sensors. In other words, a single controller is registered with * {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such * as {@link FingerprintManager#onPointerDown(int, int, int, float, float)} or - * {@link IUdfpsOverlayController#showUdfpsOverlay(int)}should all have + * {@link IUdfpsOverlayController#showUdfpsOverlay(int)} should all have * {@code sensorId} parameters. */ @SuppressWarnings("deprecation") @@ -117,9 +116,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager; @NonNull private final DumpManager mDumpManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @NonNull private final KeyguardViewMediator mKeyguardViewMediator; @Nullable private final Vibrator mVibrator; - @NonNull private final Handler mMainHandler; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @NonNull private final AccessibilityManager mAccessibilityManager; @@ -127,6 +124,9 @@ public class UdfpsController implements DozeReceiver { @Nullable private final UdfpsHbmProvider mHbmProvider; @NonNull private final KeyguardBypassController mKeyguardBypassController; @NonNull private final ConfigurationController mConfigurationController; + @NonNull private final SystemClock mSystemClock; + @NonNull private final UnlockedScreenOffAnimationController + mUnlockedScreenOffAnimationController; @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. @@ -165,7 +165,8 @@ public class UdfpsController implements DozeReceiver { public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + // vibration will bypass battery saver mode: + .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY) .build(); public static final VibrationEffect EFFECT_CLICK = @@ -243,7 +244,7 @@ public class UdfpsController implements DozeReceiver { final UdfpsEnrollHelper enrollHelper; if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) { - enrollHelper = new UdfpsEnrollHelper(mContext, reason); + enrollHelper = new UdfpsEnrollHelper(mContext, mFingerprintManager, reason); } else { enrollHelper = null; } @@ -454,19 +455,19 @@ public class UdfpsController implements DozeReceiver { 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"); @@ -517,7 +518,6 @@ public class UdfpsController implements DozeReceiver { @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, - @NonNull KeyguardViewMediator keyguardViewMediator, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, @@ -530,11 +530,12 @@ public class UdfpsController implements DozeReceiver { @NonNull KeyguardBypassController keyguardBypassController, @NonNull DisplayManager displayManager, @Main Handler mainHandler, - @NonNull ConfigurationController configurationController) { + @NonNull ConfigurationController configurationController, + @NonNull SystemClock systemClock, + @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { mContext = context; mExecution = execution; // TODO (b/185124905): inject main handler and vibrator once done prototyping - mMainHandler = new Handler(Looper.getMainLooper()); mVibrator = vibrator; mInflater = inflater; // The fingerprint manager is queried for UDFPS before this class is constructed, so the @@ -548,7 +549,6 @@ public class UdfpsController implements DozeReceiver { mKeyguardViewManager = statusBarKeyguardViewManager; mDumpManager = dumpManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mKeyguardViewMediator = keyguardViewMediator; mFalsingManager = falsingManager; mPowerManager = powerManager; mAccessibilityManager = accessibilityManager; @@ -566,6 +566,8 @@ public class UdfpsController implements DozeReceiver { mainHandler); mKeyguardBypassController = keyguardBypassController; mConfigurationController = configurationController; + mSystemClock = systemClock; + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -655,6 +657,20 @@ public class UdfpsController implements DozeReceiver { } } + private boolean shouldRotate(@Nullable UdfpsAnimationViewController animation) { + if (!(animation instanceof UdfpsKeyguardViewController)) { + // always rotate view if we're not on the keyguard + return true; + } + + // on the keyguard, make sure we don't rotate if we're going to sleep or not occluded + if (mKeyguardUpdateMonitor.isGoingToSleep() || !mKeyguardStateController.isOccluded()) { + return false; + } + + return true; + } + private WindowManager.LayoutParams computeLayoutParams( @Nullable UdfpsAnimationViewController animation) { final int paddingX = animation != null ? animation.getPaddingX() : 0; @@ -678,9 +694,11 @@ public class UdfpsController implements DozeReceiver { // Transform dimensions if the device is in landscape mode switch (mContext.getDisplay().getRotation()) { case Surface.ROTATION_90: - if (animation instanceof UdfpsKeyguardViewController - && mKeyguardUpdateMonitor.isGoingToSleep()) { + if (!shouldRotate(animation)) { + Log.v(TAG, "skip rotating udfps location ROTATION_90"); break; + } else { + Log.v(TAG, "rotate udfps location ROTATION_90"); } mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius - paddingX; @@ -689,9 +707,11 @@ public class UdfpsController implements DozeReceiver { break; case Surface.ROTATION_270: - if (animation instanceof UdfpsKeyguardViewController - && mKeyguardUpdateMonitor.isGoingToSleep()) { + if (!shouldRotate(animation)) { + Log.v(TAG, "skip rotating udfps location ROTATION_270"); break; + } else { + Log.v(TAG, "rotate udfps location ROTATION_270"); } mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius - paddingX; @@ -708,15 +728,21 @@ public class UdfpsController implements DozeReceiver { return mCoreLayoutParams; } + private void onOrientationChanged() { // When the configuration changes it's almost always necessary to destroy and re-create // the overlay's window to pass it the new LayoutParams. // Hiding the overlay will destroy its window. It's safe to hide the overlay regardless // of whether it is already hidden. + final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateAuth(); hideUdfpsOverlay(); + // If the overlay needs to be shown, this will re-create and show the overlay with the // updated LayoutParams. Otherwise, the overlay will remain hidden. updateOverlay(); + if (wasShowingAltAuth) { + mKeyguardViewManager.showGenericBouncer(true); + } } private void showUdfpsOverlay(@NonNull ServerRequest request) { @@ -782,12 +808,12 @@ public class UdfpsController implements DozeReceiver { mStatusBar, mKeyguardViewManager, mKeyguardUpdateMonitor, - mFgExecutor, mDumpManager, - mKeyguardViewMediator, mLockscreenShadeTransitionController, mConfigurationController, + mSystemClock, mKeyguardStateController, + mUnlockedScreenOffAnimationController, this ); case IUdfpsOverlayController.REASON_AUTH_BP: @@ -823,10 +849,14 @@ public class UdfpsController implements DozeReceiver { Log.v(TAG, "hideUdfpsOverlay | removing window"); // Reset the controller back to its starting state. onFingerUp(); + boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateAuth(); mWindowManager.removeView(mView); mView.setOnTouchListener(null); mView.setOnHoverListener(null); mView.setAnimationViewController(null); + if (wasShowingAltAuth) { + mKeyguardViewManager.resetAlternateAuth(true); + } mAccessibilityManager.removeTouchExplorationStateChangeListener( mTouchExplorationStateChangeListener); mView = null; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java index 8ac6df7198b7..f720d54bc746 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.PointF; +import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Build; import android.os.UserHandle; @@ -44,16 +45,6 @@ public class UdfpsEnrollHelper { private static final String NEW_COORDS_OVERRIDE = "com.android.systemui.biometrics.UdfpsNewCoords"; - static final int ENROLL_STAGE_COUNT = 4; - - // TODO(b/198928407): Consolidate with FingerprintEnrollEnrolling - private static final int[] STAGE_THRESHOLDS = new int[] { - 2, // center - 18, // guided - 22, // fingertip - 38, // edges - }; - interface Listener { void onEnrollmentProgress(int remaining, int totalSteps); void onEnrollmentHelp(int remaining, int totalSteps); @@ -61,6 +52,7 @@ public class UdfpsEnrollHelper { } @NonNull private final Context mContext; + @NonNull private final FingerprintManager mFingerprintManager; // IUdfpsOverlayController reason private final int mEnrollReason; private final boolean mAccessibilityEnabled; @@ -77,8 +69,11 @@ public class UdfpsEnrollHelper { @Nullable Listener mListener; - public UdfpsEnrollHelper(@NonNull Context context, int reason) { + public UdfpsEnrollHelper(@NonNull Context context, + @NonNull FingerprintManager fingerprintManager, int reason) { + mContext = context; + mFingerprintManager = fingerprintManager; mEnrollReason = reason; final AccessibilityManager am = context.getSystemService(AccessibilityManager.class); @@ -127,12 +122,12 @@ public class UdfpsEnrollHelper { } } - static int getStageThreshold(int index) { - return STAGE_THRESHOLDS[index]; + int getStageCount() { + return mFingerprintManager.getEnrollStageCount(); } - static int getLastStageThreshold() { - return STAGE_THRESHOLDS[ENROLL_STAGE_COUNT - 1]; + int getStageThresholdSteps(int totalSteps, int stageIndex) { + return Math.round(totalSteps * mFingerprintManager.getEnrollStageThreshold(stageIndex)); } boolean shouldShowProgressBar() { @@ -153,19 +148,6 @@ public class UdfpsEnrollHelper { } } - if (mTotalSteps == -1) { - mTotalSteps = remaining; - - // Allocate (or subtract) any extra steps for the first enroll stage. - final int extraSteps = mTotalSteps - getLastStageThreshold(); - if (extraSteps != 0) { - for (int stageIndex = 0; stageIndex < ENROLL_STAGE_COUNT; stageIndex++) { - STAGE_THRESHOLDS[stageIndex] = - Math.max(0, STAGE_THRESHOLDS[stageIndex] + extraSteps); - } - } - } - mRemainingSteps = remaining; if (mListener != null) { @@ -194,7 +176,7 @@ public class UdfpsEnrollHelper { if (mTotalSteps == -1 || mRemainingSteps == -1) { return true; } - return mTotalSteps - mRemainingSteps < STAGE_THRESHOLDS[0]; + return mTotalSteps - mRemainingSteps < getStageThresholdSteps(mTotalSteps, 0); } boolean isGuidedEnrollmentStage() { @@ -202,7 +184,8 @@ public class UdfpsEnrollHelper { return false; } final int progressSteps = mTotalSteps - mRemainingSteps; - return progressSteps >= STAGE_THRESHOLDS[0] && progressSteps < STAGE_THRESHOLDS[1]; + return progressSteps >= getStageThresholdSteps(mTotalSteps, 0) + && progressSteps < getStageThresholdSteps(mTotalSteps, 1); } boolean isTipEnrollmentStage() { @@ -210,14 +193,15 @@ public class UdfpsEnrollHelper { return false; } final int progressSteps = mTotalSteps - mRemainingSteps; - return progressSteps >= STAGE_THRESHOLDS[1] && progressSteps < STAGE_THRESHOLDS[2]; + return progressSteps >= getStageThresholdSteps(mTotalSteps, 1) + && progressSteps < getStageThresholdSteps(mTotalSteps, 2); } boolean isEdgeEnrollmentStage() { if (mTotalSteps == -1 || mRemainingSteps == -1) { return false; } - return mTotalSteps - mRemainingSteps >= STAGE_THRESHOLDS[2]; + return mTotalSteps - mRemainingSteps >= getStageThresholdSteps(mTotalSteps, 2); } @NonNull diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java index b56543f4851b..f772720c3cf1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java @@ -36,72 +36,109 @@ public class UdfpsEnrollProgressBarDrawable extends Drawable { private static final float SEGMENT_GAP_ANGLE = 12f; - @NonNull private final List<UdfpsEnrollProgressBarSegment> mSegments; + @NonNull private final Context mContext; + + @Nullable private UdfpsEnrollHelper mEnrollHelper; + @NonNull private List<UdfpsEnrollProgressBarSegment> mSegments = new ArrayList<>(); + private int mTotalSteps = 1; + private int mProgressSteps = 0; + private boolean mIsShowingHelp = false; public UdfpsEnrollProgressBarDrawable(@NonNull Context context) { - mSegments = new ArrayList<>(UdfpsEnrollHelper.ENROLL_STAGE_COUNT); - float startAngle = SEGMENT_GAP_ANGLE / 2f; - final float sweepAngle = (360f / UdfpsEnrollHelper.ENROLL_STAGE_COUNT) - SEGMENT_GAP_ANGLE; - final Runnable invalidateRunnable = this::invalidateSelf; - for (int index = 0; index < UdfpsEnrollHelper.ENROLL_STAGE_COUNT; index++) { - mSegments.add(new UdfpsEnrollProgressBarSegment(context, getBounds(), startAngle, - sweepAngle, SEGMENT_GAP_ANGLE, invalidateRunnable)); - startAngle += sweepAngle + SEGMENT_GAP_ANGLE; - } + mContext = context; } - void setEnrollmentProgress(int remaining, int totalSteps) { - if (remaining == totalSteps) { - // Show some progress for the initial touch. - setEnrollmentProgress(1); - } else { - setEnrollmentProgress(totalSteps - remaining); + void setEnrollHelper(@Nullable UdfpsEnrollHelper enrollHelper) { + mEnrollHelper = enrollHelper; + if (enrollHelper != null) { + final int stageCount = enrollHelper.getStageCount(); + mSegments = new ArrayList<>(stageCount); + float startAngle = SEGMENT_GAP_ANGLE / 2f; + final float sweepAngle = (360f / stageCount) - SEGMENT_GAP_ANGLE; + final Runnable invalidateRunnable = this::invalidateSelf; + for (int index = 0; index < stageCount; index++) { + mSegments.add(new UdfpsEnrollProgressBarSegment(mContext, getBounds(), startAngle, + sweepAngle, SEGMENT_GAP_ANGLE, invalidateRunnable)); + startAngle += sweepAngle + SEGMENT_GAP_ANGLE; + } + invalidateSelf(); } } - private void setEnrollmentProgress(int progressSteps) { - Log.d(TAG, "setEnrollmentProgress: progressSteps = " + progressSteps); + void onEnrollmentProgress(int remaining, int totalSteps) { + mTotalSteps = totalSteps; + updateState(getProgressSteps(remaining, totalSteps), false /* isShowingHelp */); + } - int segmentIndex = 0; - int prevThreshold = 0; - while (segmentIndex < mSegments.size()) { - final UdfpsEnrollProgressBarSegment segment = mSegments.get(segmentIndex); - final int threshold = UdfpsEnrollHelper.getStageThreshold(segmentIndex); + void onEnrollmentHelp(int remaining, int totalSteps) { + updateState(getProgressSteps(remaining, totalSteps), true /* isShowingHelp */); + } + + void onLastStepAcquired() { + updateState(mTotalSteps, false /* isShowingHelp */); + } + + private static int getProgressSteps(int remaining, int totalSteps) { + // Show some progress for the initial touch. + return Math.max(1, totalSteps - remaining); + } + + private void updateState(int progressSteps, boolean isShowingHelp) { + updateProgress(progressSteps); + updateFillColor(isShowingHelp); + } + + private void updateProgress(int progressSteps) { + if (mProgressSteps == progressSteps) { + return; + } + mProgressSteps = progressSteps; - if (progressSteps >= threshold && !segment.isFilledOrFilling()) { - Log.d(TAG, "setEnrollmentProgress: segment[" + segmentIndex + "] complete"); + if (mEnrollHelper == null) { + Log.e(TAG, "updateState: UDFPS enroll helper was null"); + return; + } + + int index = 0; + int prevThreshold = 0; + while (index < mSegments.size()) { + final UdfpsEnrollProgressBarSegment segment = mSegments.get(index); + final int thresholdSteps = mEnrollHelper.getStageThresholdSteps(mTotalSteps, index); + if (progressSteps >= thresholdSteps && segment.getProgress() < 1f) { segment.updateProgress(1f); break; - } else if (progressSteps >= prevThreshold && progressSteps < threshold) { + } else if (progressSteps >= prevThreshold && progressSteps < thresholdSteps) { final int relativeSteps = progressSteps - prevThreshold; - final int relativeThreshold = threshold - prevThreshold; + final int relativeThreshold = thresholdSteps - prevThreshold; final float segmentProgress = (float) relativeSteps / (float) relativeThreshold; - Log.d(TAG, "setEnrollmentProgress: segment[" + segmentIndex + "] progress = " - + segmentProgress); segment.updateProgress(segmentProgress); break; } - segmentIndex++; - prevThreshold = threshold; + index++; + prevThreshold = thresholdSteps; } - if (progressSteps >= UdfpsEnrollHelper.getLastStageThreshold()) { - Log.d(TAG, "setEnrollmentProgress: startCompletionAnimation"); + if (progressSteps >= mTotalSteps) { for (final UdfpsEnrollProgressBarSegment segment : mSegments) { segment.startCompletionAnimation(); } } else { - Log.d(TAG, "setEnrollmentProgress: cancelCompletionAnimation"); for (final UdfpsEnrollProgressBarSegment segment : mSegments) { segment.cancelCompletionAnimation(); } } } - void onLastStepAcquired() { - Log.d(TAG, "setEnrollmentProgress: onLastStepAcquired"); - setEnrollmentProgress(UdfpsEnrollHelper.getLastStageThreshold()); + private void updateFillColor(boolean isShowingHelp) { + if (mIsShowingHelp == isShowingHelp) { + return; + } + mIsShowingHelp = isShowingHelp; + + for (final UdfpsEnrollProgressBarSegment segment : mSegments) { + segment.updateFillColor(isShowingHelp); + } } @Override @@ -123,12 +160,10 @@ public class UdfpsEnrollProgressBarDrawable extends Drawable { @Override public void setAlpha(int alpha) { - } @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { - } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarSegment.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarSegment.java index 5f24380b6ce3..bd6ab4443630 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarSegment.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarSegment.java @@ -39,6 +39,7 @@ import com.android.systemui.R; public class UdfpsEnrollProgressBarSegment { private static final String TAG = "UdfpsProgressBarSegment"; + private static final long FILL_COLOR_ANIMATION_DURATION_MS = 200L; private static final long PROGRESS_ANIMATION_DURATION_MS = 400L; private static final long OVER_SWEEP_ANIMATION_DELAY_MS = 200L; private static final long OVER_SWEEP_ANIMATION_DURATION_MS = 200L; @@ -53,16 +54,21 @@ public class UdfpsEnrollProgressBarSegment { private final float mSweepAngle; private final float mMaxOverSweepAngle; private final float mStrokeWidthPx; + @ColorInt private final int mProgressColor; + @ColorInt private final int mHelpColor; @NonNull private final Paint mBackgroundPaint; @NonNull private final Paint mProgressPaint; - private boolean mIsFilledOrFilling = false; - private float mProgress = 0f; + private float mAnimatedProgress = 0f; @Nullable private ValueAnimator mProgressAnimator; @NonNull private final ValueAnimator.AnimatorUpdateListener mProgressUpdateListener; + private boolean mIsShowingHelp = false; + @Nullable private ValueAnimator mFillColorAnimator; + @NonNull private final ValueAnimator.AnimatorUpdateListener mFillColorUpdateListener; + private float mOverSweepAngle = 0f; @Nullable private ValueAnimator mOverSweepAnimator; @Nullable private ValueAnimator mOverSweepReverseAnimator; @@ -79,6 +85,8 @@ public class UdfpsEnrollProgressBarSegment { mSweepAngle = sweepAngle; mMaxOverSweepAngle = maxOverSweepAngle; mStrokeWidthPx = Utils.dpToPixels(context, STROKE_WIDTH_DP); + mProgressColor = context.getColor(R.color.udfps_enroll_progress); + mHelpColor = context.getColor(R.color.udfps_enroll_progress_help); mBackgroundPaint = new Paint(); mBackgroundPaint.setStrokeWidth(mStrokeWidthPx); @@ -100,13 +108,18 @@ public class UdfpsEnrollProgressBarSegment { // Progress should not be color extracted mProgressPaint = new Paint(); mProgressPaint.setStrokeWidth(mStrokeWidthPx); - mProgressPaint.setColor(context.getColor(R.color.udfps_enroll_progress)); + mProgressPaint.setColor(mProgressColor); mProgressPaint.setAntiAlias(true); mProgressPaint.setStyle(Paint.Style.STROKE); mProgressPaint.setStrokeCap(Paint.Cap.ROUND); mProgressUpdateListener = animation -> { - mProgress = (float) animation.getAnimatedValue(); + mAnimatedProgress = (float) animation.getAnimatedValue(); + mInvalidateRunnable.run(); + }; + + mFillColorUpdateListener = animation -> { + mProgressPaint.setColor((int) animation.getAnimatedValue()); mInvalidateRunnable.run(); }; @@ -129,11 +142,9 @@ public class UdfpsEnrollProgressBarSegment { * Draws this segment to the given canvas. */ public void draw(@NonNull Canvas canvas) { - Log.d(TAG, "draw: mProgress = " + mProgress); - final float halfPaddingPx = mStrokeWidthPx / 2f; - if (mProgress < 1f) { + if (mAnimatedProgress < 1f) { // Draw the unfilled background color of the segment. canvas.drawArc( halfPaddingPx, @@ -146,7 +157,7 @@ public class UdfpsEnrollProgressBarSegment { mBackgroundPaint); } - if (mProgress > 0f) { + if (mAnimatedProgress > 0f) { // Draw the filled progress portion of the segment. canvas.drawArc( halfPaddingPx, @@ -154,17 +165,18 @@ public class UdfpsEnrollProgressBarSegment { mBounds.right - halfPaddingPx, mBounds.bottom - halfPaddingPx, mStartAngle, - mSweepAngle * mProgress + mOverSweepAngle, + mSweepAngle * mAnimatedProgress + mOverSweepAngle, false /* useCenter */, mProgressPaint); } } /** - * @return Whether this segment is filled or in the process of being filled. + * @return The fill progress of this segment, in the range [0, 1]. If fill progress is being + * animated, returns the value it is animating to. */ - public boolean isFilledOrFilling() { - return mIsFilledOrFilling; + public float getProgress() { + return mProgress; } /** @@ -177,27 +189,44 @@ public class UdfpsEnrollProgressBarSegment { } private void updateProgress(float progress, long animationDurationMs) { - Log.d(TAG, "updateProgress: progress = " + progress - + ", duration = " + animationDurationMs); - if (mProgress == progress) { - Log.d(TAG, "updateProgress skipped: progress == mProgress"); return; } - - mIsFilledOrFilling = progress >= 1f; + mProgress = progress; if (mProgressAnimator != null && mProgressAnimator.isRunning()) { mProgressAnimator.cancel(); } - mProgressAnimator = ValueAnimator.ofFloat(mProgress, progress); + mProgressAnimator = ValueAnimator.ofFloat(mAnimatedProgress, progress); mProgressAnimator.setDuration(animationDurationMs); mProgressAnimator.addUpdateListener(mProgressUpdateListener); mProgressAnimator.start(); } /** + * Updates the fill color of this segment, animating if necessary. + * + * @param isShowingHelp Whether fill color should indicate that a help message is being shown. + */ + public void updateFillColor(boolean isShowingHelp) { + if (mIsShowingHelp == isShowingHelp) { + return; + } + mIsShowingHelp = isShowingHelp; + + if (mFillColorAnimator != null && mFillColorAnimator.isRunning()) { + mFillColorAnimator.cancel(); + } + + @ColorInt final int targetColor = isShowingHelp ? mHelpColor : mProgressColor; + mFillColorAnimator = ValueAnimator.ofArgb(mProgressPaint.getColor(), targetColor); + mFillColorAnimator.setDuration(FILL_COLOR_ANIMATION_DURATION_MS); + mFillColorAnimator.addUpdateListener(mFillColorUpdateListener); + mFillColorAnimator.start(); + } + + /** * Queues and runs the completion animation for this segment. */ public void startCompletionAnimation() { @@ -208,18 +237,16 @@ public class UdfpsEnrollProgressBarSegment { return; } - Log.d(TAG, "startCompletionAnimation: mProgress = " + mProgress - + ", mOverSweepAngle = " + mOverSweepAngle); - // Reset sweep angle back to zero if the animation is being rolled back. if (mOverSweepReverseAnimator != null && mOverSweepReverseAnimator.isRunning()) { mOverSweepReverseAnimator.cancel(); mOverSweepAngle = 0f; } - // Start filling the segment if it isn't already. - if (mProgress < 1f) { + // Clear help color and start filling the segment if it isn't already. + if (mAnimatedProgress < 1f) { updateProgress(1f, OVER_SWEEP_ANIMATION_DELAY_MS); + updateFillColor(false /* isShowingHelp */); } // Queue the animation to run after fill completes. @@ -230,9 +257,6 @@ public class UdfpsEnrollProgressBarSegment { * Cancels (and reverses, if necessary) a queued or running completion animation. */ public void cancelCompletionAnimation() { - Log.d(TAG, "cancelCompletionAnimation: mProgress = " + mProgress - + ", mOverSweepAngle = " + mOverSweepAngle); - // Cancel the animation if it's queued or running. mHandler.removeCallbacks(mOverSweepAnimationRunnable); if (mOverSweepAnimator != null && mOverSweepAnimator.isRunning()) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java index 6f02c64e4cf7..64b096867ec1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java @@ -73,24 +73,22 @@ public class UdfpsEnrollView extends UdfpsAnimationView { } void setEnrollHelper(UdfpsEnrollHelper enrollHelper) { + mFingerprintProgressDrawable.setEnrollHelper(enrollHelper); mFingerprintDrawable.setEnrollHelper(enrollHelper); } void onEnrollmentProgress(int remaining, int totalSteps) { mHandler.post(() -> { - mFingerprintProgressDrawable.setEnrollmentProgress(remaining, totalSteps); + mFingerprintProgressDrawable.onEnrollmentProgress(remaining, totalSteps); mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps); }); } void onEnrollmentHelp(int remaining, int totalSteps) { - mHandler.post( - () -> mFingerprintProgressDrawable.setEnrollmentProgress(remaining, totalSteps)); + mHandler.post(() -> mFingerprintProgressDrawable.onEnrollmentHelp(remaining, totalSteps)); } void onLastStepAcquired() { - mHandler.post(() -> { - mFingerprintProgressDrawable.onLastStepAcquired(); - }); + mHandler.post(mFingerprintProgressDrawable::onLastStepAcquired); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 888672316c8a..c128e5e2ab30 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -26,16 +26,16 @@ import android.view.MotionEvent; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.time.SystemClock; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -46,12 +46,13 @@ import java.io.PrintWriter; public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> { @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @NonNull private final DelayableExecutor mExecutor; - @NonNull private final KeyguardViewMediator mKeyguardViewMediator; @NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController; @NonNull private final ConfigurationController mConfigurationController; + @NonNull private final SystemClock mSystemClock; @NonNull private final KeyguardStateController mKeyguardStateController; @NonNull private final UdfpsController mUdfpsController; + @NonNull private final UnlockedScreenOffAnimationController + mUnlockedScreenOffAnimationController; private boolean mShowingUdfpsBouncer; private boolean mUdfpsRequested; @@ -60,7 +61,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud private int mStatusBarState; private float mTransitionToFullShadeProgress; private float mLastDozeAmount; - + private long mLastUdfpsBouncerShowTime = -1; private float mStatusBarExpansion; private boolean mLaunchTransitionFadingAway; @@ -78,22 +79,22 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @NonNull StatusBar statusBar, @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, - @NonNull DelayableExecutor mainDelayableExecutor, @NonNull DumpManager dumpManager, - @NonNull KeyguardViewMediator keyguardViewMediator, @NonNull LockscreenShadeTransitionController transitionController, @NonNull ConfigurationController configurationController, + @NonNull SystemClock systemClock, @NonNull KeyguardStateController keyguardStateController, + @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, @NonNull UdfpsController udfpsController) { super(view, statusBarStateController, statusBar, dumpManager); mKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mExecutor = mainDelayableExecutor; - mKeyguardViewMediator = keyguardViewMediator; mLockScreenShadeTransitionController = transitionController; mConfigurationController = configurationController; + mSystemClock = systemClock; mKeyguardStateController = keyguardStateController; mUdfpsController = udfpsController; + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; } @Override @@ -102,6 +103,12 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud } @Override + public void onInit() { + super.onInit(); + mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); + } + + @Override protected void onViewAttached() { super.onViewAttached(); final float dozeAmount = mStatusBarStateController.getDozeAmount(); @@ -124,6 +131,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this); + mUnlockedScreenOffAnimationController.addCallback(mUnlockedScreenOffCallback); } @Override @@ -140,6 +148,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) { mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null); } + mUnlockedScreenOffAnimationController.removeCallback(mUnlockedScreenOffCallback); } @Override @@ -170,6 +179,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud boolean udfpsAffordanceWasNotShowing = shouldPauseAuth(); mShowingUdfpsBouncer = show; if (mShowingUdfpsBouncer) { + mLastUdfpsBouncerShowTime = mSystemClock.uptimeMillis(); + } + if (mShowingUdfpsBouncer) { if (udfpsAffordanceWasNotShowing) { mView.animateInUdfpsBouncer(null); } @@ -237,16 +249,25 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud * 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. */ @@ -400,4 +421,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud updatePauseAuth(); } }; + + private final UnlockedScreenOffAnimationController.Callback mUnlockedScreenOffCallback = + (linear, eased) -> mStateListener.onDozeAmountChanged(linear, eased); } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt index 4104e3184efd..46a03e809b06 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt @@ -16,6 +16,10 @@ package com.android.systemui.controls.ui +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.os.Bundle import android.view.View import android.view.ViewGroup @@ -23,18 +27,25 @@ import android.view.WindowInsets import android.view.WindowInsets.Type import com.android.systemui.R +import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.controls.management.ControlsAnimations import com.android.systemui.util.LifecycleActivity import javax.inject.Inject /** - * Displays Device Controls inside an activity + * Displays Device Controls inside an activity. This activity is available to be displayed over the + * lockscreen if the user has allowed it via + * [android.provider.Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]. This activity will be + * destroyed on SCREEN_OFF events, due to issues with occluded activities over lockscreen as well as + * user expectations for the activity to not continue running. */ class ControlsActivity @Inject constructor( - private val uiController: ControlsUiController + private val uiController: ControlsUiController, + private val broadcastDispatcher: BroadcastDispatcher ) : LifecycleActivity() { private lateinit var parent: ViewGroup + private lateinit var broadcastReceiver: BroadcastReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -62,6 +73,8 @@ class ControlsActivity @Inject constructor( WindowInsets.CONSUMED } } + + initBroadcastReceiver() } override fun onResume() { @@ -83,4 +96,25 @@ class ControlsActivity @Inject constructor( uiController.hide() } + + override fun onDestroy() { + super.onDestroy() + + broadcastDispatcher.unregisterReceiver(broadcastReceiver) + } + + private fun initBroadcastReceiver() { + broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val action = intent.getAction() + if (Intent.ACTION_SCREEN_OFF.equals(action)) { + finish() + } + } + } + + val filter = IntentFilter() + filter.addAction(Intent.ACTION_SCREEN_OFF) + broadcastDispatcher.registerReceiver(broadcastReceiver, filter) + } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 567d0cb3e6cb..72da7f4f893a 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -256,13 +256,13 @@ class ControlsUiControllerImpl @Inject constructor ( // Force animations when transitioning from a dialog to an activity intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true) - if (keyguardStateController.isUnlocked()) { + if (keyguardStateController.isShowing()) { + activityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */) + } else { activityContext.startActivity( intent, ActivityOptions.makeSceneTransitionAnimation(activityContext as Activity).toBundle() ) - } else { - activityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */) } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index c97a30e6e13e..79ee6a8e8830 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -198,9 +198,11 @@ public class DependencyProvider { @SysUISingleton @Provides static ThemeOverlayApplier provideThemeOverlayManager(Context context, - @Background Executor bgExecutor, OverlayManager overlayManager, + @Background Executor bgExecutor, + @Main Executor mainExecutor, + OverlayManager overlayManager, DumpManager dumpManager) { - return new ThemeOverlayApplier(overlayManager, bgExecutor, + return new ThemeOverlayApplier(overlayManager, bgExecutor, mainExecutor, context.getString(R.string.launcher_overlayable_package), context.getString(R.string.themepicker_overlayable_package), dumpManager); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 657d9246be8f..845d7dc26ee5 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -275,6 +275,13 @@ public class DozeLog implements Dumpable { } /** + * Appends sensor event dropped event to logs + */ + public void traceSensorEventDropped(int sensorEvent, String reason) { + mLogger.logSensorEventDropped(sensorEvent, reason); + } + + /** * Appends pulse dropped event to logs * @param reason why the pulse was dropped */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index fe37d49980b2..dc186182432f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -205,6 +205,15 @@ class DozeLogger @Inject constructor( }) } + fun logSensorEventDropped(sensorEvent: Int, reason: String) { + buffer.log(TAG, INFO, { + int1 = sensorEvent + str1 = reason + }, { + "SensorEvent [$int1] dropped, reason=$str1" + }) + } + fun logPulseDropped(reason: String) { buffer.log(TAG, INFO, { str1 = reason diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 8d4ac75a0748..058f37a2ef38 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -29,8 +29,8 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; -import android.view.Display; +import com.android.systemui.dock.DockManager; import com.android.systemui.doze.dagger.BrightnessSensor; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.doze.dagger.WrappedService; @@ -74,6 +74,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private final Optional<Sensor> mLightSensorOptional; private final WakefulnessLifecycle mWakefulnessLifecycle; private final DozeParameters mDozeParameters; + private final DockManager mDockManager; private final int[] mSensorToBrightness; private final int[] mSensorToScrimOpacity; private final int mScreenBrightnessDim; @@ -101,6 +102,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi AlwaysOnDisplayPolicy alwaysOnDisplayPolicy, WakefulnessLifecycle wakefulnessLifecycle, DozeParameters dozeParameters, + DockManager dockManager, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { mContext = context; mDozeService = service; @@ -110,6 +112,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi mDozeParameters = dozeParameters; mDozeHost = host; mHandler = handler; + mDockManager = dockManager; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness; @@ -122,7 +125,15 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { switch (newState) { case INITIALIZED: + resetBrightnessToDefault(); + break; + case DOZE_AOD: + case DOZE_REQUEST_PULSE: + case DOZE_AOD_DOCKED: + setLightSensorEnabled(true); + break; case DOZE: + setLightSensorEnabled(false); resetBrightnessToDefault(); break; case FINISH: @@ -135,15 +146,6 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } } - @Override - public void onScreenState(int state) { - if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) { - setLightSensorEnabled(true); - } else { - setLightSensorEnabled(false); - } - } - private void onDestroy() { setLightSensorEnabled(false); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index b2db86f16104..55e6154b829d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -456,13 +456,24 @@ public class DozeSensors { public void updateListening() { if (!mConfigured || mSensor == null) return; - if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting) - && !mRegistered) { - mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); - if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered); + if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)) { + if (!mRegistered) { + mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); + if (DEBUG) { + Log.d(TAG, "requestTriggerSensor[" + mSensor + + "] " + mRegistered); + } + } else { + if (DEBUG) { + Log.d(TAG, "requestTriggerSensor[" + mSensor + + "] already registered"); + } + } } else if (mRegistered) { final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor); - if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt); + if (DEBUG) { + Log.d(TAG, "cancelTriggerSensor[" + mSensor + "] " + rt); + } mRegistered = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 455f3c0d6ac2..756adca724e9 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -41,6 +41,7 @@ import com.android.systemui.dock.DockManager; import com.android.systemui.doze.DozeMachine.State; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.Assert; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -92,6 +93,7 @@ public class DozeTriggers implements DozeMachine.Part { private final BroadcastDispatcher mBroadcastDispatcher; private final AuthController mAuthController; private final DelayableExecutor mMainExecutor; + private final KeyguardStateController mKeyguardStateController; private final UiEventLogger mUiEventLogger; private long mNotificationPulseTime; @@ -179,7 +181,8 @@ public class DozeTriggers implements DozeMachine.Part { DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher, SecureSettings secureSettings, AuthController authController, @Main DelayableExecutor mainExecutor, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + KeyguardStateController keyguardStateController) { mContext = context; mDozeHost = dozeHost; mConfig = config; @@ -198,6 +201,7 @@ public class DozeTriggers implements DozeMachine.Part { mAuthController = authController; mMainExecutor = mainExecutor; mUiEventLogger = uiEventLogger; + mKeyguardStateController = keyguardStateController; } @Override @@ -294,6 +298,7 @@ public class DozeTriggers implements DozeMachine.Part { proximityCheckThenCall((result) -> { if (result != null && result) { // In pocket, drop event. + mDozeLog.traceSensorEventDropped(pulseReason, "prox reporting near"); return; } if (isDoubleTap || isTap) { @@ -302,6 +307,10 @@ public class DozeTriggers implements DozeMachine.Part { } gentleWakeUp(pulseReason); } else if (isPickup) { + if (shouldDropPickupEvent()) { + mDozeLog.traceSensorEventDropped(pulseReason, "keyguard occluded"); + return; + } gentleWakeUp(pulseReason); } else if (isUdfpsLongPress) { final State state = mMachine.getState(); @@ -320,7 +329,7 @@ public class DozeTriggers implements DozeMachine.Part { }, true /* alreadyPerformedProxCheck */, pulseReason); } - if (isPickup) { + if (isPickup && !shouldDropPickupEvent()) { final long timeSinceNotification = SystemClock.elapsedRealtime() - mNotificationPulseTime; final boolean withinVibrationThreshold = @@ -329,6 +338,10 @@ public class DozeTriggers implements DozeMachine.Part { } } + private boolean shouldDropPickupEvent() { + return mKeyguardStateController.isOccluded(); + } + private void gentleWakeUp(int reason) { // Log screen wake up reason (lift/pickup, tap, double-tap) Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason)) diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt index bfa478088cad..5b327bd5e4c1 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 @@ import javax.inject.Inject * 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 28f63b07e584..6561bd5a5323 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 @@ import javax.inject.Inject * 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 bc4ced452630..1b4a47e4bf39 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.logging.UiEventLogger; 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; @@ -172,7 +173,8 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite SysUiState sysUiState, @Main Handler handler, PackageManager packageManager, - StatusBar statusBar) { + StatusBar statusBar, + KeyguardUpdateMonitor keyguardUpdateMonitor) { super(context, windowManagerFuncs, @@ -204,7 +206,8 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite sysUiState, handler, packageManager, - statusBar); + statusBar, + keyguardUpdateMonitor); mLockPatternUtils = lockPatternUtils; mKeyguardStateController = keyguardStateController; @@ -266,7 +269,7 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite this::getWalletViewController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger(), - getStatusBar()); + getStatusBar(), getKeyguardUpdateMonitor(), mLockPatternUtils); if (shouldShowLockMessage(dialog)) { dialog.showLockMessage(); @@ -334,12 +337,13 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, - StatusBar statusBar) { + StatusBar statusBar, 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, null, - statusBar); + statusBar, 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 06e74821869e..9ada54b9ef6f 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.Window; 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.statusbar.IStatusBarService; 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; @@ -170,6 +172,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene 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 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected Handler mMainHandler; private int mSmallestScreenWidthDp; private final StatusBar mStatusBar; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @VisibleForTesting public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum { @@ -338,7 +346,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene SysUiState sysUiState, @Main Handler handler, PackageManager packageManager, - StatusBar statusBar) { + StatusBar statusBar, + KeyguardUpdateMonitor keyguardUpdateMonitor) { mContext = context; mWindowManagerFuncs = windowManagerFuncs; mAudioManager = audioManager; @@ -369,6 +378,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mMainHandler = handler; mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp; mStatusBar = statusBar; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; // receive broadcasts IntentFilter filter = new IntentFilter(); @@ -422,6 +432,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene return mStatusBar; } + protected KeyguardUpdateMonitor getKeyguardUpdateMonitor() { + return mKeyguardUpdateMonitor; + } + /** * Show the global actions dialog (creating if necessary) * @@ -653,7 +667,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mAdapter, mOverflowAdapter, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger, - mInfoProvider, mStatusBar); + mInfoProvider, mStatusBar, mKeyguardUpdateMonitor, mLockPatternUtils); dialog.setOnDismissListener(this); dialog.setOnShowListener(this); @@ -2122,6 +2136,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private GlobalActionsInfoProvider mInfoProvider; private GestureDetector mGestureDetector; private StatusBar mStatusBar; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private LockPatternUtils mLockPatternUtils; protected ViewGroup mContainer; @@ -2173,7 +2189,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, - @Nullable GlobalActionsInfoProvider infoProvider, StatusBar statusBar) { + @Nullable GlobalActionsInfoProvider infoProvider, StatusBar statusBar, + KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) { super(context, themeRes); mContext = context; mAdapter = adapter; @@ -2188,6 +2205,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mUiEventLogger = uiEventLogger; mInfoProvider = infoProvider; mStatusBar = statusBar; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mLockPatternUtils = lockPatternUtils; mGestureDetector = new GestureDetector(mContext, mGestureListener); @@ -2308,6 +2327,14 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene if (mInfoProvider != null && mInfoProvider.shouldShowMessage()) { mInfoProvider.addPanel(mContext, mContainer, mAdapter.getCount(), () -> dismiss()); } + + // 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() { @@ -2319,6 +2346,37 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene 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/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index d30783c29f92..a51ec54ebcce 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -102,7 +102,6 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { @Override public Size reportSurfaceSize() { - mTexture.use(null /* consumer */); mSurfaceSize.set(mTexture.getTextureDimensions()); return new Size(mSurfaceSize.width(), mSurfaceSize.height()); } @@ -124,6 +123,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { private final WallpaperManager mWallpaperManager; private Bitmap mBitmap; private boolean mWcgContent; + private boolean mTextureUsed; private WallpaperTexture(WallpaperManager wallpaperManager) { mWallpaperManager = wallpaperManager; @@ -141,6 +141,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { mWallpaperManager.forgetLoadedWallpaper(); if (mBitmap != null) { mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); + mTextureUsed = true; } else { Log.w(TAG, "Can't get bitmap"); } @@ -171,6 +172,9 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { } private Rect getTextureDimensions() { + if (!mTextureUsed) { + mDimensions.set(mWallpaperManager.peekBitmapDimensions()); + } return mDimensions; } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java index 2d215e0f1f62..a424674ed252 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java @@ -100,8 +100,7 @@ public class KeyguardIndicationRotateTextViewController extends */ public void updateIndication(@IndicationType int type, KeyguardIndication newIndication, boolean updateImmediately) { - if (type == INDICATION_TYPE_NOW_PLAYING - || type == INDICATION_TYPE_REVERSE_CHARGING) { + if (type == INDICATION_TYPE_REVERSE_CHARGING) { // temporarily don't show here, instead use AmbientContainer b/181049781 return; } @@ -303,7 +302,6 @@ public class KeyguardIndicationRotateTextViewController extends public static final int INDICATION_TYPE_TRUST = 6; public static final int INDICATION_TYPE_RESTING = 7; public static final int INDICATION_TYPE_USER_LOCKED = 8; - public static final int INDICATION_TYPE_NOW_PLAYING = 9; public static final int INDICATION_TYPE_REVERSE_CHARGING = 10; @IntDef({ @@ -317,7 +315,6 @@ public class KeyguardIndicationRotateTextViewController extends INDICATION_TYPE_TRUST, INDICATION_TYPE_RESTING, INDICATION_TYPE_USER_LOCKED, - INDICATION_TYPE_NOW_PLAYING, INDICATION_TYPE_REVERSE_CHARGING, }) @Retention(RetentionPolicy.SOURCE) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 5751c0fddde0..926b4cc94c6a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2827,7 +2827,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } } - private void setShowingLocked(boolean showing) { + void setShowingLocked(boolean showing) { setShowingLocked(showing, false /* forceCallbacks */); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index 2facf3dedd18..c743fe125cf7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -212,14 +212,32 @@ class MediaCarouselController @Inject constructor( isSsReactivated: Boolean ) { if (addOrUpdatePlayer(key, oldKey, data)) { + // Log card received if a new resumable media card is added MediaPlayerData.getMediaPlayer(key)?.let { logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, + it.mUid, /* isRecommendationCard */ false, it.surfaceForSmartspaceLogging, rank = MediaPlayerData.getMediaPlayerIndex(key)) } } + if (isSsReactivated) { + // If resumable media is reactivated by headphone connection, update instance + // id for each card and log a receive event. + MediaPlayerData.players().forEachIndexed { index, it -> + if (it.recommendationViewHolder == null) { + it.mInstanceId = SmallHash.hash(it.mUid + + systemClock.currentTimeMillis().toInt()) + logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED + it.mInstanceId, + it.mUid, + /* isRecommendationCard */ false, + it.surfaceForSmartspaceLogging, + rank = index) + } + } + } if (mediaCarouselScrollHandler.visibleToUser && isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) { // It could happen that reactived media player isn't visible to user because @@ -252,6 +270,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayer(key)?.let { logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, + it.mUid, /* isRecommendationCard */ true, it.surfaceForSmartspaceLogging, rank = MediaPlayerData.getMediaPlayerIndex(key)) @@ -261,6 +280,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayerIndex(key)) { logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN it.mInstanceId, + it.mUid, /* isRecommendationCard */ true, it.surfaceForSmartspaceLogging) } @@ -339,9 +359,9 @@ class MediaCarouselController @Inject constructor( if (activeMediaIndex != -1) { previousVisiblePlayerKey?.let { val previousVisibleIndex = MediaPlayerData.playerKeys() - .indexOfFirst { key -> it == key } + .indexOfFirst { key -> it == key } mediaCarouselScrollHandler - .scrollToPlayer(previousVisibleIndex, activeMediaIndex) + .scrollToPlayer(previousVisibleIndex, activeMediaIndex) } ?: { mediaCarouselScrollHandler.scrollToPlayer(destIndex = activeMediaIndex) } @@ -355,11 +375,11 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.moveIfExists(oldKey, key) val existingPlayer = MediaPlayerData.getMediaPlayer(key) val curVisibleMediaKey = MediaPlayerData.playerKeys() - .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) + .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) if (existingPlayer == null) { var newPlayer = mediaControlPanelFactory.get() newPlayer.attachPlayer( - PlayerViewHolder.create(LayoutInflater.from(context), mediaContent)) + PlayerViewHolder.create(LayoutInflater.from(context), mediaContent)) newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) @@ -407,14 +427,14 @@ class MediaCarouselController @Inject constructor( var newRecs = mediaControlPanelFactory.get() newRecs.attachRecommendation( - RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)) + RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)) newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT) + ViewGroup.LayoutParams.WRAP_CONTENT) newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp) newRecs.bindRecommendation(data.copy(backgroundColor = bgColor)) val curVisibleMediaKey = MediaPlayerData.playerKeys() - .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) + .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) MediaPlayerData.addMediaRecommendation(key, data, newRecs, shouldPrioritize, systemClock) updatePlayerToState(newRecs, noAnimation = true) reorderAllPlayers(curVisibleMediaKey) @@ -462,7 +482,7 @@ class MediaCarouselController @Inject constructor( removePlayer(key, dismissMediaData = false, dismissRecommendation = false) smartspaceMediaData?.let { addSmartspaceMediaRecommendations( - it.targetId, it, MediaPlayerData.shouldPrioritizeSs) + it.targetId, it, MediaPlayerData.shouldPrioritizeSs) } } else { removePlayer(key, dismissMediaData = false, dismissRecommendation = false) @@ -585,7 +605,7 @@ class MediaCarouselController @Inject constructor( ?: endShowsActive if (currentlyShowingOnlyActive != endShowsActive || ((currentTransitionProgress != 1.0f && currentTransitionProgress != 0.0f) && - startShowsActive != endShowsActive)) { + startShowsActive != endShowsActive)) { // Whenever we're transitioning from between differing states or the endstate differs // we reset the translation currentlyShowingOnlyActive = endShowsActive @@ -696,23 +716,43 @@ class MediaCarouselController @Inject constructor( } logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN mediaControlPanel.mInstanceId, + mediaControlPanel.mUid, isRecommendationCard, mediaControlPanel.surfaceForSmartspaceLogging) } } @JvmOverloads + /** + * Log Smartspace events + * + * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN) + * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new + * instanceId + * @param uid uid for the application that media comes from + * @param isRecommendationCard whether the card is media recommendation + * @param surface which display surface the media card is on (e.g. lockscreen, shade) + * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1 + * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc. + * @param interactedSubcardCardinality how many media items were shown to the user when there + * is user interaction + * @param rank the rank for media card in the media carousel, starting from 0 + * + */ fun logSmartspaceCardReported( eventId: Int, instanceId: Int, + uid: Int, isRecommendationCard: Boolean, surface: Int, + interactedSubcardRank: Int = 0, + interactedSubcardCardinality: Int = 0, rank: Int = mediaCarouselScrollHandler.visibleMediaIndex ) { // Only log media resume card when Smartspace data is available if (!isRecommendationCard && - !mediaManager.smartspaceMediaData.isActive && - MediaPlayerData.smartspaceMediaData == null) { + !mediaManager.smartspaceMediaData.isActive && + MediaPlayerData.smartspaceMediaData == null) { return } @@ -720,13 +760,21 @@ class MediaCarouselController @Inject constructor( SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, eventId, instanceId, - if (isRecommendationCard) - SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS - else - SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_RESUME_MEDIA, + // Deprecated, replaced with AiAi feature type so we don't need to create logging + // card type for each new feature. + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD, surface, rank, - mediaContent.getChildCount()) + mediaContent.getChildCount(), + if (isRecommendationCard) + 15 // MEDIA_RECOMMENDATION + else + 31, // MEDIA_RESUME + uid, + interactedSubcardRank, + interactedSubcardCardinality, + 0 // received_latency_millis + ) /* ktlint-disable max-line-length */ } @@ -738,18 +786,20 @@ class MediaCarouselController @Inject constructor( if (!recommendation.isEmpty()) { logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS recommendation.get(0).mInstanceId, + recommendation.get(0).mUid, true, recommendation.get(0).surfaceForSmartspaceLogging, - /* rank */-1) + rank = -1) } else { val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex if (MediaPlayerData.players().size > visibleMediaIndex) { val player = MediaPlayerData.players().elementAt(visibleMediaIndex) logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS player.mInstanceId, - false, + player.mUid, + false, player.surfaceForSmartspaceLogging, - /* rank */-1) + rank = -1) } } mediaManager.onSwipeToDismiss() @@ -768,7 +818,7 @@ class MediaCarouselController @Inject constructor( @VisibleForTesting internal object MediaPlayerData { private val EMPTY = MediaData(-1, false, 0, null, null, null, null, null, - emptyList(), emptyList(), "INVALID", null, null, null, true, null) + emptyList(), emptyList(), "INVALID", null, null, null, true, null) // Whether should prioritize Smartspace card. internal var shouldPrioritizeSs: Boolean = false private set @@ -776,18 +826,18 @@ internal object MediaPlayerData { private set data class MediaSortKey( - // Whether the item represents a Smartspace media recommendation. + // Whether the item represents a Smartspace media recommendation. val isSsMediaRec: Boolean, val data: MediaData, val updateTime: Long = 0 ) private val comparator = - compareByDescending<MediaSortKey> { it.data.isPlaying } - .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } - .thenByDescending { it.data.isLocalSession } - .thenByDescending { !it.data.resumption } - .thenByDescending { it.updateTime } + compareByDescending<MediaSortKey> { it.data.isPlaying } + .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } + .thenByDescending { it.data.isLocalSession } + .thenByDescending { !it.data.resumption } + .thenByDescending { it.updateTime } private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator) private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf() @@ -808,7 +858,8 @@ internal object MediaPlayerData { ) { shouldPrioritizeSs = shouldPrioritize removeMediaPlayer(key) - val sortKey = MediaSortKey(isSsMediaRec = true, EMPTY, clock.currentTimeMillis()) + val sortKey = MediaSortKey(/* isSsMediaRec= */ true, + EMPTY.copy(isPlaying = false), clock.currentTimeMillis()) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) smartspaceMediaData = data @@ -888,4 +939,4 @@ internal object MediaPlayerData { } return false } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 15a70831b2f9..e7445f920ffe 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -33,6 +33,7 @@ import android.graphics.drawable.Icon; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; +import android.os.Process; import android.text.Layout; import android.util.Log; import android.view.View; @@ -74,6 +75,8 @@ public class MediaControlPanel { private static final String TAG = "MediaControlPanel"; private static final float DISABLED_ALPHA = 0.38f; + private static final String EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME = "com.google" + + ".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity"; private static final String EXTRAS_SMARTSPACE_INTENT = "com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT"; private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3; @@ -111,6 +114,9 @@ public class MediaControlPanel { private int mAlbumArtSize; // Instance id for logging purpose. protected int mInstanceId = -1; + // Uid for the media app. + protected int mUid = Process.INVALID_UID; + private int mSmartspaceMediaItemsCount; private MediaCarouselController mMediaCarouselController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; @@ -248,7 +254,8 @@ public class MediaControlPanel { openGuts(); return true; } else { - return false; + closeGuts(); + return true; } }); mRecommendationViewHolder.getCancel().setOnClickListener(v -> { @@ -266,7 +273,13 @@ public class MediaControlPanel { } mKey = key; MediaSession.Token token = data.getToken(); - mInstanceId = SmallHash.hash(data.getPackageName()); + PackageManager packageManager = mContext.getPackageManager(); + try { + mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Unable to look up package name", e); + } + mInstanceId = SmallHash.hash(mUid); mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { @@ -360,27 +373,16 @@ public class MediaControlPanel { final MediaDeviceData device = data.getDevice(); final int seamlessId = mPlayerViewHolder.getSeamless().getId(); - final int seamlessFallbackId = mPlayerViewHolder.getSeamlessFallback().getId(); - final boolean showFallback = device != null && !device.getEnabled(); - final int seamlessFallbackVisibility = showFallback ? View.VISIBLE : View.GONE; - mPlayerViewHolder.getSeamlessFallback().setVisibility(seamlessFallbackVisibility); - expandedSet.setVisibility(seamlessFallbackId, seamlessFallbackVisibility); - collapsedSet.setVisibility(seamlessFallbackId, seamlessFallbackVisibility); - final int seamlessVisibility = showFallback ? View.GONE : View.VISIBLE; - mPlayerViewHolder.getSeamless().setVisibility(seamlessVisibility); - expandedSet.setVisibility(seamlessId, seamlessVisibility); - collapsedSet.setVisibility(seamlessId, seamlessVisibility); - final float seamlessAlpha = data.getResumption() ? DISABLED_ALPHA : 1.0f; + // Disable clicking on output switcher for invalid devices and resumption controls + final boolean seamlessDisabled = (device != null && !device.getEnabled()) + || data.getResumption(); + final float seamlessAlpha = seamlessDisabled ? DISABLED_ALPHA : 1.0f; expandedSet.setAlpha(seamlessId, seamlessAlpha); collapsedSet.setAlpha(seamlessId, seamlessAlpha); - // Disable clicking on output switcher for resumption controls. - mPlayerViewHolder.getSeamless().setEnabled(!data.getResumption()); + mPlayerViewHolder.getSeamless().setEnabled(!seamlessDisabled); String deviceString = null; - if (showFallback) { - iconView.setImageDrawable(null); - } else if (device != null) { + if (device != null && device.getEnabled()) { Drawable icon = device.getIcon(); - iconView.setVisibility(View.VISIBLE); if (icon instanceof AdaptiveIcon) { AdaptiveIcon aIcon = (AdaptiveIcon) icon; aIcon.setBackgroundColor(mBackgroundColor); @@ -391,10 +393,9 @@ public class MediaControlPanel { deviceString = device.getName(); } else { // Reset to default - Log.w(TAG, "device is null. Not binding output chip."); - iconView.setVisibility(View.GONE); - deviceString = mContext.getString( - com.android.internal.R.string.ext_media_seamless_action); + Log.w(TAG, "Device is null or not enabled: " + device + ", not binding output chip."); + iconView.setImageResource(R.drawable.ic_media_home_devices); + deviceString = mContext.getString(R.string.media_seamless_other_device); } deviceName.setText(deviceString); seamlessView.setContentDescription(deviceString); @@ -531,10 +532,11 @@ public class MediaControlPanel { } // Set up recommendation card's header. - ApplicationInfo applicationInfo = null; + ApplicationInfo applicationInfo; try { applicationInfo = mContext.getPackageManager() .getApplicationInfo(data.getPackageName(), 0 /* flags */); + mUid = applicationInfo.uid; } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Fail to get media recommendation's app info", e); return; @@ -553,7 +555,8 @@ public class MediaControlPanel { headerTitleText.setText(appLabel); } // Set up media rec card's tap action if applicable. - setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction()); + setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(), + /* interactedSubcardRank */ -1); // Set up media rec card's accessibility label. recommendationCard.setContentDescription( mContext.getString(R.string.controls_media_smartspace_rec_description, appLabel)); @@ -567,7 +570,8 @@ public class MediaControlPanel { ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); int mediaRecommendationNum = Math.min(mediaRecommendationList.size(), MEDIA_RECOMMENDATION_MAX_NUM); - for (int itemIndex = 0, uiComponentIndex = 0; + int uiComponentIndex = 0; + for (int itemIndex = 0; itemIndex < mediaRecommendationNum && uiComponentIndex < mediaRecommendationNum; itemIndex++) { SmartspaceAction recommendation = mediaRecommendationList.get(itemIndex); @@ -582,7 +586,16 @@ public class MediaControlPanel { // Set up the media item's click listener if applicable. ViewGroup mediaCoverContainer = mediaCoverContainers.get(uiComponentIndex); - setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation); + setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation, + uiComponentIndex); + // Bubble up the long-click event to the card. + mediaCoverContainer.setOnLongClickListener(v -> { + View parent = (View) v.getParent(); + if (parent != null) { + parent.performLongClick(); + } + return true; + }); // Set up the accessibility label for the media item. String artistName = recommendation.getExtras() @@ -614,10 +627,10 @@ public class MediaControlPanel { mediaCoverItemsResIds.get(uiComponentIndex), true); setVisibleAndAlpha(expandedSet, mediaCoverContainersResIds.get(uiComponentIndex), true); - uiComponentIndex++; } + mSmartspaceMediaItemsCount = uiComponentIndex; // Set up long press to show guts setting panel. mRecommendationViewHolder.getDismiss().setOnClickListener(v -> { logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS @@ -625,6 +638,22 @@ public class MediaControlPanel { closeGuts(); mMediaDataManagerLazy.get().dismissSmartspaceRecommendation( data.getTargetId(), MediaViewController.GUTS_ANIMATION_DURATION + 100L); + + Intent dismissIntent = data.getDismissIntent(); + if (dismissIntent == null) { + Log.w(TAG, "Cannot create dismiss action click action: " + + "extras missing dismiss_intent."); + return; + } + + if (dismissIntent.getComponent() != null + && dismissIntent.getComponent().getClassName() + .equals(EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME)) { + // Dismiss the card Smartspace data through Smartspace trampoline activity. + mContext.startActivity(dismissIntent); + } else { + mContext.sendBroadcast(dismissIntent); + } }); mController = null; @@ -750,7 +779,8 @@ public class MediaControlPanel { private void setSmartspaceRecItemOnClickListener( @NonNull View view, - @NonNull SmartspaceAction action) { + @NonNull SmartspaceAction action, + int interactedSubcardRank) { if (view == null || action == null || action.getIntent() == null || action.getIntent().getExtras() == null) { Log.e(TAG, "No tap action can be set up"); @@ -758,9 +788,10 @@ public class MediaControlPanel { } view.setOnClickListener(v -> { - // When media recommendation card is shown, it will always be the top card. logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK - /* isRecommendationCard */ true); + /* isRecommendationCard */ true, + interactedSubcardRank, + getSmartspaceSubCardCardinality()); if (shouldSmartspaceRecItemOpenInForeground(action)) { // Request to unlock the device if the activity needs to be opened in foreground. @@ -818,9 +849,28 @@ public class MediaControlPanel { } private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard) { + logSmartspaceCardReported(eventId, isRecommendationCard, + /* interactedSubcardRank */ 0, + /* interactedSubcardCardinality */ 0); + } + + private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, + int interactedSubcardRank, int interactedSubcardCardinality) { mMediaCarouselController.logSmartspaceCardReported(eventId, mInstanceId, + mUid, isRecommendationCard, - getSurfaceForSmartspaceLogging()); + getSurfaceForSmartspaceLogging(), + interactedSubcardRank, + interactedSubcardCardinality); + } + + private int getSmartspaceSubCardCardinality() { + if (!mMediaCarouselController.getMediaCarouselScrollHandler().getQsExpanded() + && mSmartspaceMediaItemsCount > 3) { + return 3; + } + + return mSmartspaceMediaItemsCount; } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index c8deb014f781..79206e86da09 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -16,6 +16,7 @@ package com.android.systemui.media +import android.content.Context import android.os.SystemProperties import android.util.Log import com.android.internal.annotations.VisibleForTesting @@ -32,6 +33,8 @@ import kotlin.collections.LinkedHashMap private const val TAG = "MediaDataFilter" private const val DEBUG = true +private const val EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME = ("com.google" + + ".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity") private const val RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY = "resumable_media_max_age_seconds" /** @@ -51,6 +54,7 @@ internal val SMARTSPACE_MAX_AGE = SystemProperties * background users (e.g. timeouts). */ class MediaDataFilter @Inject constructor( + private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, private val mediaResumeListener: MediaResumeListener, private val lockscreenUserManager: NotificationLockscreenUserManager, @@ -229,6 +233,18 @@ class MediaDataFilter @Inject constructor( mediaDataManager.setTimedOut(it, timedOut = true, forceUpdate = true) } if (smartspaceMediaData.isActive) { + val dismissIntent = smartspaceMediaData.dismissIntent + if (dismissIntent == null) { + Log.w(TAG, "Cannot create dismiss action click action: " + + "extras missing dismiss_intent.") + } else if (dismissIntent.getComponent() != null && + dismissIntent.getComponent().getClassName() + == EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME) { + // Dismiss the card Smartspace data through Smartspace trampoline activity. + context.startActivity(dismissIntent) + } else { + context.sendBroadcast(dismissIntent) + } smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 0a28b47923da..eacdab6e537d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -76,12 +76,13 @@ private val ART_URIS = arrayOf( private const val TAG = "MediaDataManager" private const val DEBUG = true +private const val EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY = "dismiss_intent" private val LOADING = MediaData(-1, false, 0, null, null, null, null, null, emptyList(), emptyList(), "INVALID", null, null, null, true, null) @VisibleForTesting internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, - "INVALID", null, emptyList(), 0) + "INVALID", null, emptyList(), null, 0) fun isMediaNotification(sbn: StatusBarNotification): Boolean { if (!sbn.notification.hasMediaSession()) { @@ -212,8 +213,8 @@ class MediaDataManager( mediaDataCombineLatest.addListener(mediaDataFilter) // Set up links back into the pipeline for listeners that need to send events upstream. - mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean -> - setTimedOut(token, timedOut) } + mediaTimeoutListener.timeoutCallback = { key: String, timedOut: Boolean -> + setTimedOut(key, timedOut) } mediaResumeListener.setManager(this) mediaDataFilter.mediaDataManager = this @@ -414,14 +415,18 @@ class MediaDataManager( * This will make the player not active anymore, hiding it from QQS and Keyguard. * @see MediaData.active */ - internal fun setTimedOut(token: String, timedOut: Boolean, forceUpdate: Boolean = false) { - mediaEntries[token]?.let { + internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) { + mediaEntries[key]?.let { if (it.active == !timedOut && !forceUpdate) { + if (it.resumption) { + if (DEBUG) Log.d(TAG, "timing out resume player $key") + dismissMediaData(key, 0L /* delay */) + } return } it.active = !timedOut - if (DEBUG) Log.d(TAG, "Updating $token timedOut: $timedOut") - onMediaDataLoaded(token, token, it) + if (DEBUG) Log.d(TAG, "Updating $key timedOut: $timedOut") + onMediaDataLoaded(key, key, it) } } @@ -879,12 +884,22 @@ class MediaDataManager( target: SmartspaceTarget, isActive: Boolean ): SmartspaceMediaData { + var dismissIntent: Intent? = null + if (target.baseAction != null && target.baseAction.extras != null) { + dismissIntent = target + .baseAction + .extras + .getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent + } packageName(target)?.let { return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it, - target.baseAction, target.iconGrid, 0) + target.baseAction, target.iconGrid, + dismissIntent, 0) } return EMPTY_SMARTSPACE_MEDIA_DATA - .copy(targetId = target.smartspaceTargetId, isActive = isActive) + .copy(targetId = target.smartspaceTargetId, + isActive = isActive, + dismissIntent = dismissIntent) } private fun packageName(target: SmartspaceTarget): String? { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index ab568c8c5a85..608c784f5d39 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -35,6 +35,7 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.tuner.TunerService import com.android.systemui.util.Utils +import com.android.systemui.util.time.SystemClock import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.ConcurrentLinkedQueue @@ -53,11 +54,13 @@ class MediaResumeListener @Inject constructor( @Background private val backgroundExecutor: Executor, private val tunerService: TunerService, private val mediaBrowserFactory: ResumeMediaBrowserFactory, - dumpManager: DumpManager + dumpManager: DumpManager, + private val systemClock: SystemClock ) : MediaDataManager.Listener, Dumpable { private var useMediaResumption: Boolean = Utils.useMediaResumption(context) - private val resumeComponents: ConcurrentLinkedQueue<ComponentName> = ConcurrentLinkedQueue() + private val resumeComponents: ConcurrentLinkedQueue<Pair<ComponentName, Long>> = + ConcurrentLinkedQueue() private lateinit var mediaDataManager: MediaDataManager @@ -131,14 +134,32 @@ class MediaResumeListener @Inject constructor( val listString = prefs.getString(MEDIA_PREFERENCE_KEY + currentUserId, null) val components = listString?.split(ResumeMediaBrowser.DELIMITER.toRegex()) ?.dropLastWhile { it.isEmpty() } + var needsUpdate = false components?.forEach { val info = it.split("/") val packageName = info[0] val className = info[1] val component = ComponentName(packageName, className) - resumeComponents.add(component) + + val lastPlayed = if (info.size == 3) { + try { + info[2].toLong() + } catch (e: NumberFormatException) { + needsUpdate = true + systemClock.currentTimeMillis() + } + } else { + needsUpdate = true + systemClock.currentTimeMillis() + } + resumeComponents.add(component to lastPlayed) } Log.d(TAG, "loaded resume components ${resumeComponents.toArray().contentToString()}") + + if (needsUpdate) { + // Save any missing times that we had to fill in + writeSharedPrefs() + } } /** @@ -149,9 +170,12 @@ class MediaResumeListener @Inject constructor( return } + val now = systemClock.currentTimeMillis() resumeComponents.forEach { - val browser = mediaBrowserFactory.create(mediaBrowserCallback, it) - browser.findRecentMedia() + if (now.minus(it.second) <= RESUME_MEDIA_TIMEOUT) { + val browser = mediaBrowserFactory.create(mediaBrowserCallback, it.first) + browser.findRecentMedia() + } } } @@ -234,18 +258,24 @@ class MediaResumeListener @Inject constructor( */ private fun updateResumptionList(componentName: ComponentName) { // Remove if exists - resumeComponents.remove(componentName) + resumeComponents.remove(resumeComponents.find { it.first.equals(componentName) }) // Insert at front of queue - resumeComponents.add(componentName) + val currentTime = systemClock.currentTimeMillis() + resumeComponents.add(componentName to currentTime) // Remove old components if over the limit if (resumeComponents.size > ResumeMediaBrowser.MAX_RESUMPTION_CONTROLS) { resumeComponents.remove() } - // Save changes + writeSharedPrefs() + } + + private fun writeSharedPrefs() { val sb = StringBuilder() resumeComponents.forEach { - sb.append(it.flattenToString()) + sb.append(it.first.flattenToString()) + sb.append("/") + sb.append(it.second) sb.append(ResumeMediaBrowser.DELIMITER) } val prefs = context.getSharedPreferences(MEDIA_PREFERENCES, Context.MODE_PRIVATE) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt index 9a3919326cbd..6f047712c954 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -20,6 +20,7 @@ import android.media.session.MediaController import android.media.session.PlaybackState import android.os.SystemProperties import android.util.Log +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState @@ -29,9 +30,15 @@ import javax.inject.Inject private const val DEBUG = true private const val TAG = "MediaTimeout" -private val PAUSED_MEDIA_TIMEOUT = SystemProperties + +@VisibleForTesting +val PAUSED_MEDIA_TIMEOUT = SystemProperties .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10)) +@VisibleForTesting +val RESUME_MEDIA_TIMEOUT = SystemProperties + .getLong("debug.sysui.media_timeout_resume", TimeUnit.DAYS.toMillis(3)) + /** * Controller responsible for keeping track of playback states and expiring inactive streams. */ @@ -45,8 +52,9 @@ class MediaTimeoutListener @Inject constructor( /** * Callback representing that a media object is now expired: - * @param token Media session unique identifier - * @param pauseTimeout True when expired for {@code PAUSED_MEDIA_TIMEOUT} + * @param key Media control unique identifier + * @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media, + * or {@code RESUME_MEDIA_TIMEOUT} for resume media */ lateinit var timeoutCallback: (String, Boolean) -> Unit @@ -122,6 +130,7 @@ class MediaTimeoutListener @Inject constructor( var timedOut = false var playing: Boolean? = null + var resumption: Boolean? = null var destroyed = false var mediaData: MediaData = data @@ -159,12 +168,19 @@ class MediaTimeoutListener @Inject constructor( } override fun onSessionDestroyed() { - // If the session is destroyed, the controller is no longer valid, and we will need to - // recreate it if this key is updated later if (DEBUG) { Log.d(TAG, "Session destroyed for $key") } - destroy() + + if (resumption == true) { + // Some apps create a session when MBS is queried. We should unregister the + // controller since it will no longer be valid, but don't cancel the timeout + mediaController?.unregisterCallback(this) + } else { + // For active controls, if the session is destroyed, clean up everything since we + // will need to recreate it if this key is updated later + destroy() + } } private fun processState(state: PlaybackState?, dispatchEvents: Boolean) { @@ -173,20 +189,28 @@ class MediaTimeoutListener @Inject constructor( } val isPlaying = state != null && isPlayingState(state.state) - if (playing == isPlaying && playing != null) { + val resumptionChanged = resumption != mediaData.resumption + if (playing == isPlaying && playing != null && !resumptionChanged) { return } playing = isPlaying + resumption = mediaData.resumption if (!isPlaying) { if (DEBUG) { - Log.v(TAG, "schedule timeout for $key") + Log.v(TAG, "schedule timeout for $key playing $isPlaying, $resumption") } - if (cancellation != null) { + if (cancellation != null && !resumptionChanged) { + // if the media changed resume state, we'll need to adjust the timeout length if (DEBUG) Log.d(TAG, "cancellation already exists, continuing.") return } - expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state") + expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state, $resumption") + val timeout = if (mediaData.resumption) { + RESUME_MEDIA_TIMEOUT + } else { + PAUSED_MEDIA_TIMEOUT + } cancellation = mainExecutor.executeDelayed({ cancellation = null if (DEBUG) { @@ -195,7 +219,7 @@ class MediaTimeoutListener @Inject constructor( timedOut = true // this event is async, so it's safe even when `dispatchEvents` is false timeoutCallback(key, timedOut) - }, PAUSED_MEDIA_TIMEOUT) + }, timeout) } else { expireMediaTimeout(key, "playback started - $state, $key") timedOut = false diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt index 791f59d3ae13..35603b6ef6cc 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt @@ -43,7 +43,6 @@ class PlayerViewHolder private constructor(itemView: View) { val seamless = itemView.requireViewById<ViewGroup>(R.id.media_seamless) val seamlessIcon = itemView.requireViewById<ImageView>(R.id.media_seamless_image) val seamlessText = itemView.requireViewById<TextView>(R.id.media_seamless_text) - val seamlessFallback = itemView.requireViewById<ImageView>(R.id.media_seamless_fallback) // Seek bar val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar) @@ -124,7 +123,6 @@ class PlayerViewHolder private constructor(itemView: View) { R.id.header_title, R.id.header_artist, R.id.media_seamless, - R.id.media_seamless_fallback, R.id.notification_media_progress_time, R.id.media_progress_bar, R.id.action0, diff --git a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt index 9ac128920edb..61fdefd4579f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt @@ -17,6 +17,7 @@ package com.android.systemui.media import android.app.smartspace.SmartspaceAction +import android.content.Intent /** State of a Smartspace media recommendations view. */ data class SmartspaceMediaData( @@ -45,6 +46,10 @@ data class SmartspaceMediaData( */ val recommendations: List<SmartspaceAction>, /** + * Intent for the user's initiated dismissal. + */ + val dismissIntent: Intent?, + /** * View's background color. */ val backgroundColor: Int diff --git a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt index b6c2ef1db82a..140a1fef93f7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt @@ -1,10 +1,13 @@ package com.android.systemui.media import android.app.smartspace.SmartspaceTarget +import android.util.Log import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener import javax.inject.Inject +private const val TAG = "SsMediaDataProvider" + /** Provides SmartspaceTargets of media types for SystemUI media control. */ class SmartspaceMediaDataProvider @Inject constructor() : BcSmartspaceDataPlugin { @@ -31,6 +34,10 @@ class SmartspaceMediaDataProvider @Inject constructor() : BcSmartspaceDataPlugin } } + if (!mediaTargets.isEmpty()) { + Log.d(TAG, "Forwarding Smartspace media updates $mediaTargets") + } + smartspaceMediaTargets = mediaTargets smartspaceMediaTargetListeners.forEach { it.onSmartspaceTargetsUpdated(smartspaceMediaTargets) diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index cb11454e44ee..8e6eb02bb6f6 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -410,6 +410,12 @@ public class NavigationBar implements View.OnAttachStateChangeListener, new Handler(Looper.getMainLooper())) { @Override public void onChange(boolean selfChange, Uri uri) { + // TODO(b/198002034): Content observers currently can still be called back after being + // unregistered, and in this case we can ignore the change if the nav bar has been + // destroyed already + if (mNavigationBarView == null) { + return; + } updateAssistantEntrypoints(); } }; @@ -601,6 +607,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } public void destroyView() { + setAutoHideController(/* autoHideController */ null); mCommandQueue.removeCallback(this); mContext.getSystemService(WindowManager.class).removeViewImmediate( mNavigationBarView.getRootView()); @@ -651,7 +658,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, if (mIsOnDefaultDisplay) { final RotationButtonController rotationButtonController = mNavigationBarView.getRotationButtonController(); - rotationButtonController.addRotationCallback(mRotationWatcher); + rotationButtonController.setRotationCallback(mRotationWatcher); // Reset user rotation pref to match that of the WindowManager if starting in locked // mode. This will automatically happen when switching from auto-rotate to locked mode. @@ -690,6 +697,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Override public void onViewDetachedFromWindow(View v) { + final RotationButtonController rotationButtonController = + mNavigationBarView.getRotationButtonController(); + rotationButtonController.setRotationCallback(null); mNavigationBarView.getBarTransitions().destroy(); mNavigationBarView.getLightTransitionsController().destroy(mContext); mOverviewProxyService.removeCallback(mOverviewProxyListener); @@ -937,6 +947,11 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Override public void onRotationProposal(final int rotation, boolean isValid) { + // The CommandQueue callbacks are added when the view is created to ensure we track other + // states, but until the view is attached (at the next traversal), the view's display is + // not valid. Just ignore the rotation in this case. + if (!mNavigationBarView.isAttachedToWindow()) return; + final int winRotation = mNavigationBarView.getDisplay().getRotation(); final boolean rotateSuggestionsDisabled = RotationButtonController .hasDisable2RotateSuggestionFlag(mDisabledFlags2); @@ -1516,7 +1531,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } /** Sets {@link AutoHideController} to the navigation bar. */ - public void setAutoHideController(AutoHideController autoHideController) { + private void setAutoHideController(AutoHideController autoHideController) { mAutoHideController = autoHideController; if (mAutoHideController != null) { mAutoHideController.setNavigationBar(mAutoHideUiElement); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index b9e9240b354a..1628c71ae005 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -395,7 +395,6 @@ public class NavigationBarController implements Callbacks, void removeNavigationBar(int displayId) { NavigationBar navBar = mNavigationBars.get(displayId); if (navBar != null) { - navBar.setAutoHideController(/* autoHideController */ null); navBar.destroyView(); mNavigationBars.remove(displayId); } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 61e803312b55..70c21e43b79a 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -101,10 +101,7 @@ import java.util.function.Consumer; public class NavigationBarView extends FrameLayout implements NavigationModeController.ModeChangedListener { final static boolean DEBUG = false; - final static String TAG = "StatusBar/NavBarView"; - - // slippery nav bar when everything is disabled, e.g. during setup - final static boolean SLIPPERY_WHEN_DISABLED = true; + final static String TAG = "NavBarView"; final static boolean ALTERNATE_CAR_MODE_UI = false; private final RegionSamplingHelper mRegionSamplingHelper; @@ -274,7 +271,7 @@ public class NavigationBarView extends FrameLayout implements }; private final Consumer<Boolean> mRotationButtonListener = (visible) -> { - if (visible) { + if (visible && mAutoHideController != null) { // If the button will actually become visible and the navbar is about to hide, // tell the statusbar to keep it around for longer mAutoHideController.touchAutoHide(); @@ -373,6 +370,12 @@ public class NavigationBarView extends FrameLayout implements } } + @Override + protected boolean onSetAlpha(int alpha) { + Log.e(TAG, "onSetAlpha", new Throwable()); + return super.onSetAlpha(alpha); + } + public void setAutoHideController(AutoHideController autoHideController) { mAutoHideController = autoHideController; } @@ -1313,6 +1316,7 @@ public class NavigationBarView extends FrameLayout implements dumpButton(pw, "back", getBackButton()); dumpButton(pw, "home", getHomeButton()); + dumpButton(pw, "handle", getHomeHandle()); dumpButton(pw, "rcnt", getRecentsButton()); dumpButton(pw, "rota", getRotateSuggestionButton()); dumpButton(pw, "a11y", getAccessibilityButton()); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java index 649ac875b4c2..8ea9ae3c21c5 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java @@ -180,7 +180,7 @@ public class RotationButtonController { TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); } - void addRotationCallback(Consumer<Integer> watcher) { + void setRotationCallback(Consumer<Integer> watcher) { mRotWatcherListener = watcher; } diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt index a626681c0b01..d0aa710ecea6 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt @@ -29,6 +29,7 @@ import android.util.Log import androidx.annotation.MainThread import androidx.annotation.VisibleForTesting import androidx.annotation.WorkerThread +import com.android.internal.logging.UiEventLogger import com.android.systemui.appops.AppOpsController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -67,6 +68,7 @@ class PrivacyDialogController( private val privacyLogger: PrivacyLogger, private val keyguardStateController: KeyguardStateController, private val appOpsController: AppOpsController, + private val uiEventLogger: UiEventLogger, @VisibleForTesting private val dialogProvider: DialogProvider ) { @@ -81,7 +83,8 @@ class PrivacyDialogController( @Main uiExecutor: Executor, privacyLogger: PrivacyLogger, keyguardStateController: KeyguardStateController, - appOpsController: AppOpsController + appOpsController: AppOpsController, + uiEventLogger: UiEventLogger ) : this( permissionManager, packageManager, @@ -93,6 +96,7 @@ class PrivacyDialogController( privacyLogger, keyguardStateController, appOpsController, + uiEventLogger, defaultDialogProvider ) @@ -105,6 +109,7 @@ class PrivacyDialogController( private val onDialogDismissed = object : PrivacyDialog.OnDialogDismissed { override fun onDialogDismissed() { privacyLogger.logPrivacyDialogDismissed() + uiEventLogger.log(PrivacyDialogEvent.PRIVACY_DIALOG_DISMISSED) dialog = null } } @@ -114,6 +119,8 @@ class PrivacyDialogController( val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS) intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) intent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)) + uiEventLogger.log(PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_APP_SETTINGS, + userId, packageName) privacyLogger.logStartSettingsActivityFromDialog(packageName, userId) if (!keyguardStateController.isUnlocked) { // If we are locked, hide the dialog so the user can unlock @@ -155,7 +162,7 @@ class PrivacyDialogController( val items = usage.mapNotNull { val type = filterType(permGroupToPrivacyType(it.permGroupName)) val userInfo = userInfos.firstOrNull { ui -> ui.id == UserHandle.getUserId(it.uid) } - userInfo?.let { ui -> + if (userInfo != null || it.isPhoneCall) { type?.let { t -> // Only try to get the app name if we actually need it val appName = if (it.isPhoneCall) { @@ -171,10 +178,14 @@ class PrivacyDialogController( it.attribution, it.lastAccess, it.isActive, - ui.isManagedProfile, + // If there's no user info, we're in a phoneCall in secondary user + userInfo?.isManagedProfile ?: false, it.isPhoneCall ) } + } else { + // No matching user or phone call + null } } uiExecutor.execute { diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt new file mode 100644 index 000000000000..3ecc5a5e5b00 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt @@ -0,0 +1,30 @@ +/* + * 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.privacy + +import com.android.internal.logging.UiEvent +import com.android.internal.logging.UiEventLogger + +enum class PrivacyDialogEvent(private val _id: Int) : UiEventLogger.UiEventEnum { + @UiEvent(doc = "Privacy dialog is clicked by user to go to the app settings page.") + PRIVACY_DIALOG_ITEM_CLICKED_TO_APP_SETTINGS(904), + + @UiEvent(doc = "Privacy dialog is dismissed by user.") + PRIVACY_DIALOG_DISMISSED(905); + + override fun getId() = _id +}
\ No newline at end of file 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 38b20ee45946..000000000000 --- 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 000000000000..7ffa9d931ff0 --- /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/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index 59e5eb8d6ac8..6f12e467291a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -23,6 +23,7 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Point; +import android.graphics.PointF; import android.util.AttributeSet; import android.view.View; import android.view.WindowInsets; @@ -289,6 +290,16 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { } } + @Override + protected boolean isTransformedTouchPointInView(float x, float y, + View child, PointF outLocalPoint) { + // Prevent touches outside the clipped area from propagating to a child in that area. + if (mClippingEnabled && y + getTranslationY() > mFancyClippingTop) { + return false; + } + return super.isTransformedTouchPointInView(x, y, child, outLocalPoint); + } + private void updateClippingPath() { mFancyClippingPath.reset(); if (!mClippingEnabled) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java index 000fd1c4bd2e..9f585bdfaeb0 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 @@ public interface QSHost { 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/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java index 4739a3f4c7d6..08cb4a9d44b6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.content.res.Configuration; import android.metrics.LogMaker; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dumpable; @@ -80,7 +81,8 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr private final QSHost.Callback mQSHostCallback = this::setTiles; - private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener = + @VisibleForTesting + protected final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener = new QSPanel.OnConfigurationChangedListener() { @Override public void onConfigurationChange(Configuration newConfig) { @@ -156,6 +158,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener); mHost.addCallback(mQSHostCallback); setTiles(); + mLastOrientation = getResources().getConfiguration().orientation; switchTileLayout(true); mDumpManager.registerDumpable(mView.getDumpableTag(), this); @@ -356,8 +359,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr return false; } return mUsingMediaPlayer && mMediaHost.getVisible() - && getResources().getConfiguration().orientation - == Configuration.ORIENTATION_LANDSCAPE; + && mLastOrientation == Configuration.ORIENTATION_LANDSCAPE; } private void logTiles() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 4a75810f86db..e60fb494e82b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -351,6 +351,17 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D 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); @@ -372,6 +383,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D * @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; @@ -386,6 +398,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D } 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/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 77906abce625..84b961e7c48a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -42,6 +42,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconMa import com.android.systemui.statusbar.phone.StatusBarWindowView; import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.policy.Clock; +import com.android.systemui.statusbar.policy.VariableDateView; import java.util.List; @@ -62,11 +63,14 @@ public class QuickStatusBarHeader extends FrameLayout { protected QuickQSPanel mHeaderQsPanel; private View mDatePrivacyView; private View mDateView; + // DateView next to clock. Visible on QQS + private VariableDateView mClockDateView; private View mSecurityHeaderView; private View mClockIconsView; private View mContainer; private View mQSCarriers; + private ViewGroup mClockContainer; private Clock mClockView; private Space mDatePrivacySeparator; private View mClockIconsSeparator; @@ -86,7 +90,6 @@ public class QuickStatusBarHeader extends FrameLayout { private int mWaterfallTopInset; private int mCutOutPaddingLeft; private int mCutOutPaddingRight; - private float mViewAlpha = 1.0f; private float mKeyguardExpansionFraction; private int mTextColorPrimary = Color.TRANSPARENT; private int mTopViewMeasureHeight; @@ -123,18 +126,24 @@ public class QuickStatusBarHeader extends FrameLayout { mIconContainer = findViewById(R.id.statusIcons); mPrivacyChip = findViewById(R.id.privacy_chip); mDateView = findViewById(R.id.date); + mClockDateView = findViewById(R.id.date_clock); mSecurityHeaderView = findViewById(R.id.header_text_container); mClockIconsSeparator = findViewById(R.id.separator); mRightLayout = findViewById(R.id.rightLayout); mDateContainer = findViewById(R.id.date_container); mPrivacyContainer = findViewById(R.id.privacy_container); + mClockContainer = findViewById(R.id.clock_container); mClockView = findViewById(R.id.clock); mDatePrivacySeparator = findViewById(R.id.space); // Tint for the battery icons are handled in setupHost() mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon); updateResources(); + Configuration config = mContext.getResources().getConfiguration(); + setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE); + setSecurityHeaderContainerVisibility( + config.orientation == Configuration.ORIENTATION_LANDSCAPE); // Don't need to worry about tuner settings for this icon mBatteryRemainingIcon.setIgnoreTunerUpdates(true); @@ -177,7 +186,7 @@ public class QuickStatusBarHeader extends FrameLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mDatePrivacyView.getMeasuredHeight() != mTopViewMeasureHeight) { mTopViewMeasureHeight = mDatePrivacyView.getMeasuredHeight(); - updateAnimators(); + post(this::updateAnimators); } } @@ -186,6 +195,8 @@ public class QuickStatusBarHeader extends FrameLayout { super.onConfigurationChanged(newConfig); updateResources(); setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); + setSecurityHeaderContainerVisibility( + newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); } @Override @@ -206,6 +217,10 @@ public class QuickStatusBarHeader extends FrameLayout { mPrivacyContainer.setLayoutParams(lp); } + private void setSecurityHeaderContainerVisibility(boolean landscape) { + mSecurityHeaderView.setVisibility(landscape ? VISIBLE : GONE); + } + private void updateBatteryMode() { if (mConfigShowBatteryEstimate && !mHasCenterCutout) { mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE); @@ -262,6 +277,25 @@ public class QuickStatusBarHeader extends FrameLayout { updateBatteryMode(); updateHeadersPadding(); updateAnimators(); + + updateClockDatePadding(); + } + + private void updateClockDatePadding() { + int startPadding = mContext.getResources() + .getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding); + int endPadding = mContext.getResources() + .getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding); + mClockView.setPaddingRelative( + startPadding, + mClockView.getPaddingTop(), + endPadding, + mClockView.getPaddingBottom() + ); + + MarginLayoutParams lp = (MarginLayoutParams) mClockDateView.getLayoutParams(); + lp.setMarginStart(endPadding); + mClockDateView.setLayoutParams(lp); } private void updateAnimators() { @@ -280,7 +314,8 @@ public class QuickStatusBarHeader extends FrameLayout { TouchAnimator.Builder builder = new TouchAnimator.Builder() .addFloat(mSecurityHeaderView, "alpha", 0, 1) // These views appear on expanding down - .addFloat(mClockView, "alpha", 0, 1) + .addFloat(mDateView, "alpha", 0, 0, 1) + .addFloat(mClockDateView, "alpha", 1, 0, 0) .addFloat(mQSCarriers, "alpha", 0, 1) .setListener(new TouchAnimator.ListenerAdapter() { @Override @@ -289,10 +324,14 @@ public class QuickStatusBarHeader extends FrameLayout { if (!mIsSingleCarrier) { mIconContainer.addIgnoredSlots(mRssiIgnoredSlots); } + // Make it gone so there's enough room for carrier names + mClockDateView.setVisibility(View.GONE); } @Override public void onAnimationStarted() { + mClockDateView.setVisibility(View.VISIBLE); + mClockDateView.setFreezeSwitching(true); setSeparatorVisibility(false); if (!mIsSingleCarrier) { mIconContainer.addIgnoredSlots(mRssiIgnoredSlots); @@ -302,6 +341,8 @@ public class QuickStatusBarHeader extends FrameLayout { @Override public void onAnimationAtStart() { super.onAnimationAtStart(); + mClockDateView.setFreezeSwitching(false); + mClockDateView.setVisibility(View.VISIBLE); setSeparatorVisibility(mShowClockIconsSeparator); // In QQS we never ignore RSSI. mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots); @@ -434,10 +475,11 @@ public class QuickStatusBarHeader extends FrameLayout { mClockIconsSeparator.setVisibility(visible ? View.VISIBLE : View.GONE); mQSCarriers.setVisibility(visible ? View.GONE : View.VISIBLE); - LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mClockView.getLayoutParams(); + LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) mClockContainer.getLayoutParams(); lp.width = visible ? 0 : WRAP_CONTENT; lp.weight = visible ? 1f : 0f; - mClockView.setLayoutParams(lp); + mClockContainer.setLayoutParams(lp); lp = (LinearLayout.LayoutParams) mRightLayout.getLayoutParams(); lp.width = visible ? 0 : WRAP_CONTENT; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index da75c9e45c54..18d6e646b007 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -41,6 +41,7 @@ import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.policy.Clock; +import com.android.systemui.statusbar.policy.VariableDateViewController; import com.android.systemui.util.ViewController; import java.util.List; @@ -71,6 +72,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private final QSExpansionPathInterpolator mQSExpansionPathInterpolator; private final FeatureFlags mFeatureFlags; + private final VariableDateViewController mVariableDateViewControllerDateView; + private final VariableDateViewController mVariableDateViewControllerClockDateView; + private boolean mListening; private boolean mMicCameraIndicatorsEnabled; private boolean mLocationIndicatorsEnabled; @@ -134,7 +138,8 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader SysuiColorExtractor colorExtractor, PrivacyDialogController privacyDialogController, QSExpansionPathInterpolator qsExpansionPathInterpolator, - FeatureFlags featureFlags) { + FeatureFlags featureFlags, + VariableDateViewController.Factory variableDateViewControllerFactory) { super(view); mPrivacyItemController = privacyItemController; mActivityStarter = activityStarter; @@ -154,6 +159,12 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mPrivacyChip = mView.findViewById(R.id.privacy_chip); mClockView = mView.findViewById(R.id.clock); mIconContainer = mView.findViewById(R.id.statusIcons); + mVariableDateViewControllerDateView = variableDateViewControllerFactory.create( + mView.requireViewById(R.id.date) + ); + mVariableDateViewControllerClockDateView = variableDateViewControllerFactory.create( + mView.requireViewById(R.id.date_clock) + ); mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, featureFlags); mDemoModeReceiver = new ClockDemoModeReceiver(mClockView); @@ -205,6 +216,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots); mDemoModeController.addCallback(mDemoModeReceiver); + + mVariableDateViewControllerDateView.init(); + mVariableDateViewControllerClockDateView.init(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index 2e771d6fb669..b1cd03c4a2f2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -116,6 +116,9 @@ public class QSIconViewImpl extends QSIconView { : icon.getInvisibleDrawable(mContext) : null; int padding = icon != null ? icon.getPadding() : 0; if (d != null) { + if (d.getConstantState() != null) { + d = d.getConstantState().newDrawable(); + } d.setAutoMirrored(false); d.setLayoutDirection(getLayoutDirection()); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt index 73d13700d61b..14e0f707d3b5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt @@ -54,7 +54,7 @@ class AlarmTile @Inject constructor( private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null private val icon = ResourceIcon.get(R.drawable.ic_alarm) @VisibleForTesting - internal val defaultIntent = Intent(AlarmClock.ACTION_SET_ALARM) + internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS) private val callback = NextAlarmController.NextAlarmChangeCallback { nextAlarm -> lastAlarmInfo = nextAlarm refreshState() diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index bbfcb865afa8..52b7b7107da2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -152,11 +152,7 @@ public class CastTile extends QSTileImpl<BooleanState> { } List<CastDevice> activeDevices = getActiveDevices(); - // We want to pop up the media route selection dialog if we either have no active devices - // (neither routes nor projection), or if we have an active route. In other cases, we assume - // that a projection is active. This is messy, but this tile never correctly handled the - // case where multiple devices were active :-/. - if (activeDevices.isEmpty() || (activeDevices.get(0).tag instanceof RouteInfo)) { + if (willPopDetail()) { mActivityStarter.postQSRunnableDismissingKeyguard(() -> { showDetail(true); }); @@ -165,6 +161,15 @@ public class CastTile extends QSTileImpl<BooleanState> { } } + // We want to pop up the media route selection dialog if we either have no active devices + // (neither routes nor projection), or if we have an active route. In other cases, we assume + // that a projection is active. This is messy, but this tile never correctly handled the + // case where multiple devices were active :-/. + private boolean willPopDetail() { + List<CastDevice> activeDevices = getActiveDevices(); + return activeDevices.isEmpty() || (activeDevices.get(0).tag instanceof RouteInfo); + } + private List<CastDevice> getActiveDevices() { ArrayList<CastDevice> activeDevices = new ArrayList<>(); for (CastDevice device : mController.getCastDevices()) { @@ -236,10 +241,12 @@ public class CastTile extends QSTileImpl<BooleanState> { state.contentDescription = state.contentDescription + "," + mContext.getString(R.string.accessibility_quick_settings_open_details); state.expandedAccessibilityClassName = Button.class.getName(); + state.forceExpandIcon = willPopDetail(); } else { state.state = Tile.STATE_UNAVAILABLE; String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi); state.secondaryLabel = noWifi; + state.forceExpandIcon = false; } state.stateDescription = state.stateDescription + ", " + state.secondaryLabel; mDetailAdapter.updateItems(devices); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 6f016be18d5b..db1df77a5803 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -50,6 +50,7 @@ import javax.inject.Inject; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTileImpl<BooleanState> { + private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot); private final Icon mWifi4EnabledStatic = ResourceIcon.get(R.drawable.ic_wifi_4_hotspot); private final Icon mWifi5EnabledStatic = ResourceIcon.get(R.drawable.ic_wifi_5_hotspot); @@ -106,7 +107,7 @@ public class HotspotTile extends QSTileImpl<BooleanState> { @Override public Intent getLongClickIntent() { - return new Intent(Settings.ACTION_TETHER_SETTINGS); + return new Intent(Settings.ACTION_WIFI_TETHER_SETTING); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 7cb1421e3f0f..cc9e7485dcff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -51,7 +51,9 @@ import com.android.systemui.qs.AlphaControlledSignalTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -66,15 +68,16 @@ import javax.inject.Inject; /** Quick settings tile: Internet **/ public class InternetTile extends QSTileImpl<SignalState> { private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS); - private static final Intent INTERNET_PANEL = - new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); protected final NetworkController mController; + private final AccessPointController mAccessPointController; private final DataUsageController mDataController; // The last updated tile state, 0: mobile, 1: wifi, 2: ethernet. private int mLastTileState = -1; protected final InternetSignalCallback mSignalCallback = new InternetSignalCallback(); + private final InternetDialogFactory mInternetDialogFactory; + final Handler mHandler; @Inject public InternetTile( @@ -86,11 +89,16 @@ public class InternetTile extends QSTileImpl<SignalState> { StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, - NetworkController networkController + NetworkController networkController, + AccessPointController accessPointController, + InternetDialogFactory internetDialogFactory ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); + mInternetDialogFactory = internetDialogFactory; + mHandler = mainHandler; mController = networkController; + mAccessPointController = accessPointController; mDataController = mController.getMobileDataController(); mController.observe(getLifecycle(), mSignalCallback); } @@ -114,7 +122,9 @@ public class InternetTile extends QSTileImpl<SignalState> { @Override protected void handleClick(@Nullable View view) { - mActivityStarter.postStartActivityDismissingKeyguard(INTERNET_PANEL, 0); + mHandler.post(() -> mInternetDialogFactory.create(true, + mAccessPointController.canConfigMobileData(), + mAccessPointController.canConfigWifi())); } @Override @@ -429,7 +439,7 @@ public class InternetTile extends QSTileImpl<SignalState> { state.icon = ResourceIcon.get(cb.mWifiSignalIconId); } } else if (cb.mNoDefaultNetwork) { - if (cb.mNoNetworksAvailable) { + if (cb.mNoNetworksAvailable || !cb.mEnabled) { state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable); } else { @@ -489,7 +499,7 @@ public class InternetTile extends QSTileImpl<SignalState> { state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.status_bar_airplane); } else if (cb.mNoDefaultNetwork) { - if (cb.mNoNetworksAvailable) { + if (cb.mNoNetworksAvailable || !mSignalCallback.mWifiInfo.mEnabled) { state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable); } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 0bbb5bdd851a..4e936b8137af 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -16,12 +16,19 @@ package com.android.systemui.qs.tiles; +import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; + +import android.Manifest; +import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; +import android.hardware.SensorPrivacyManager; import android.os.Handler; import android.os.Looper; import android.provider.Settings; +import android.provider.Settings.Secure; import android.service.quicksettings.Tile; import android.view.View; import android.widget.Switch; @@ -38,18 +45,25 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.SecureSetting; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback; +import com.android.systemui.util.settings.SecureSettings; import javax.inject.Inject; /** Quick settings tile: Rotation **/ -public class RotationLockTile extends QSTileImpl<BooleanState> { +public class RotationLockTile extends QSTileImpl<BooleanState> implements + BatteryController.BatteryStateChangeCallback { private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate); private final RotationLockController mController; + private final SensorPrivacyManager mPrivacyManager; + private final BatteryController mBatteryController; + private final SecureSetting mSetting; @Inject public RotationLockTile( @@ -61,12 +75,38 @@ public class RotationLockTile extends QSTileImpl<BooleanState> { StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, - RotationLockController rotationLockController + RotationLockController rotationLockController, + SensorPrivacyManager privacyManager, + BatteryController batteryController, + SecureSettings secureSettings ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = rotationLockController; mController.observe(this, mCallback); + mPrivacyManager = privacyManager; + mBatteryController = batteryController; + mPrivacyManager + .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshState()); + int currentUser = host.getUserContext().getUserId(); + mSetting = new SecureSetting( + secureSettings, + mHandler, + Secure.CAMERA_AUTOROTATE, + currentUser + ) { + @Override + protected void handleValueChanged(int value, boolean observedChange) { + // mHandler is the background handler so calling this is OK + handleRefreshState(value); + } + }; + mBatteryController.observe(getLifecycle(), this); + } + + @Override + public void onPowerSaveChanged(boolean isPowerSave) { + refreshState(); } @Override @@ -95,14 +135,33 @@ public class RotationLockTile extends QSTileImpl<BooleanState> { protected void handleUpdateState(BooleanState state, Object arg) { final boolean rotationLocked = mController.isRotationLocked(); + final boolean powerSave = mBatteryController.isPowerSave(); + final boolean cameraLocked = mPrivacyManager.isSensorPrivacyEnabled( + SensorPrivacyManager.Sensors.CAMERA); + final boolean cameraRotation = + !powerSave && !cameraLocked && hasSufficientPermission(mContext) + && mController.isCameraRotationEnabled(); state.value = !rotationLocked; state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label); state.icon = mIcon; state.contentDescription = getAccessibilityString(rotationLocked); + if (!rotationLocked && cameraRotation) { + state.secondaryLabel = mContext.getResources().getString( + R.string.rotation_lock_camera_rotation_on); + } else { + state.secondaryLabel = ""; + } + state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } + @Override + protected void handleUserSwitch(int newUserId) { + mSetting.setUserId(newUserId); + handleRefreshState(mSetting.getValue()); + } + public static boolean isCurrentOrientationLockPortrait(RotationLockController controller, Resources resources) { int lockOrientation = controller.getRotationLockOrientation(); @@ -140,4 +199,11 @@ public class RotationLockTile extends QSTileImpl<BooleanState> { refreshState(rotationLocked); } }; + + private boolean hasSufficientPermission(Context context) { + final PackageManager packageManager = context.getPackageManager(); + final String rotationPackage = packageManager.getRotationResolverPackageName(); + return rotationPackage != null && packageManager.checkPermission( + Manifest.permission.CAMERA, rotationPackage) == PackageManager.PERMISSION_GRANTED; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java new file mode 100644 index 000000000000..99eb5b6519bc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java @@ -0,0 +1,204 @@ +/* + * 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.tiles.dialog; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.text.Html; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.Utils; +import com.android.settingslib.wifi.WifiUtils; +import com.android.systemui.R; +import com.android.wifitrackerlib.WifiEntry; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Adapter for showing Wi-Fi networks. + */ +public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.InternetViewHolder> { + + private static final String TAG = "InternetAdapter"; + private static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG"; + private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; + private static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller"; + + private final InternetDialogController mInternetDialogController; + private List<WifiEntry> mWifiEntries; + private int mWifiEntriesCount; + + protected View mHolderView; + protected Context mContext; + + public InternetAdapter(InternetDialogController controller) { + mInternetDialogController = controller; + } + + @Override + public InternetViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, + int viewType) { + mContext = viewGroup.getContext(); + mHolderView = LayoutInflater.from(mContext).inflate(R.layout.internet_list_item, + viewGroup, false); + return new InternetViewHolder(mHolderView, mInternetDialogController); + } + + @Override + public void onBindViewHolder(@NonNull InternetViewHolder viewHolder, int position) { + if (mWifiEntries == null || position >= mWifiEntriesCount) { + return; + } + viewHolder.onBind(mWifiEntries.get(position)); + } + + /** + * Updates the Wi-Fi networks. + * + * @param wifiEntries the updated Wi-Fi entries. + * @param wifiEntriesCount the total number of Wi-Fi entries. + */ + public void setWifiEntries(@Nullable List<WifiEntry> wifiEntries, int wifiEntriesCount) { + mWifiEntries = wifiEntries; + mWifiEntriesCount = wifiEntriesCount; + } + + /** + * Gets the total number of Wi-Fi networks. + * + * @return The total number of Wi-Fi entries. + */ + @Override + public int getItemCount() { + return mWifiEntriesCount; + } + + /** + * ViewHolder for binding Wi-Fi view. + */ + static class InternetViewHolder extends RecyclerView.ViewHolder { + + final LinearLayout mContainerLayout; + final LinearLayout mWifiListLayout; + final LinearLayout mWifiNetworkLayout; + final ImageView mWifiIcon; + final TextView mWifiTitleText; + final TextView mWifiSummaryText; + final ImageView mWifiEndIcon; + final Context mContext; + final InternetDialogController mInternetDialogController; + + @VisibleForTesting + protected WifiUtils.InternetIconInjector mWifiIconInjector; + + InternetViewHolder(View view, InternetDialogController internetDialogController) { + super(view); + mContext = view.getContext(); + mInternetDialogController = internetDialogController; + mContainerLayout = view.requireViewById(R.id.internet_container); + mWifiListLayout = view.requireViewById(R.id.wifi_list); + mWifiNetworkLayout = view.requireViewById(R.id.wifi_network_layout); + mWifiIcon = view.requireViewById(R.id.wifi_icon); + mWifiTitleText = view.requireViewById(R.id.wifi_title); + mWifiSummaryText = view.requireViewById(R.id.wifi_summary); + mWifiEndIcon = view.requireViewById(R.id.wifi_end_icon); + mWifiIconInjector = mInternetDialogController.getWifiIconInjector(); + } + + void onBind(@NonNull WifiEntry wifiEntry) { + mWifiIcon.setImageDrawable(getWifiDrawable(wifiEntry)); + setWifiNetworkLayout(wifiEntry.getTitle(), + Html.fromHtml(wifiEntry.getSummary(false), Html.FROM_HTML_MODE_LEGACY)); + + final int connectedState = wifiEntry.getConnectedState(); + final int security = wifiEntry.getSecurity(); + updateEndIcon(connectedState, security); + + if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) { + mWifiListLayout.setOnClickListener( + v -> mInternetDialogController.launchWifiNetworkDetailsSetting( + wifiEntry.getKey())); + return; + } + mWifiListLayout.setOnClickListener(v -> { + if (wifiEntry.shouldEditBeforeConnect()) { + final Intent intent = new Intent(ACTION_WIFI_DIALOG); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, wifiEntry.getKey()); + intent.putExtra(EXTRA_CONNECT_FOR_CALLER, false); + mContext.startActivity(intent); + } + mInternetDialogController.connect(wifiEntry); + }); + } + + void setWifiNetworkLayout(CharSequence title, CharSequence summary) { + mWifiTitleText.setText(title); + if (TextUtils.isEmpty(summary)) { + mWifiSummaryText.setVisibility(View.GONE); + return; + } + mWifiSummaryText.setVisibility(View.VISIBLE); + mWifiSummaryText.setText(summary); + } + + Drawable getWifiDrawable(@NonNull WifiEntry wifiEntry) { + if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) { + return null; + } + final Drawable drawable = mWifiIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(), + wifiEntry.getLevel()); + if (drawable == null) { + return null; + } + drawable.setTint( + Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorTertiary)); + final AtomicReference<Drawable> shared = new AtomicReference<>(); + shared.set(drawable); + return shared.get(); + } + + void updateEndIcon(int connectedState, int security) { + Drawable drawable = null; + if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) { + drawable = mContext.getDrawable(R.drawable.ic_settings_24dp); + } else if (security != WifiEntry.SECURITY_NONE && security != WifiEntry.SECURITY_OWE) { + drawable = mContext.getDrawable(R.drawable.ic_friction_lock_closed); + } + if (drawable == null) { + mWifiEndIcon.setVisibility(View.GONE); + return; + } + mWifiEndIcon.setVisibility(View.VISIBLE); + mWifiEndIcon.setImageDrawable(drawable); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java new file mode 100644 index 000000000000..d0271f72153e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -0,0 +1,646 @@ +/* + * 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.tiles.dialog; + +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + +import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA; + +import android.app.AlertDialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.Handler; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; +import android.text.Html; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.Switch; +import android.widget.TextView; + +import androidx.annotation.MainThread; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.annotation.WorkerThread; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; +import com.android.systemui.Prefs; +import com.android.systemui.R; +import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.wifitrackerlib.WifiEntry; + +import java.util.List; +import java.util.concurrent.Executor; + +/** + * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks. + */ +@SysUISingleton +public class InternetDialog extends SystemUIDialog implements + InternetDialogController.InternetDialogCallback, Window.Callback { + private static final String TAG = "InternetDialog"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + static final long PROGRESS_DELAY_MS = 2000L; + + private final Handler mHandler; + private final Executor mBackgroundExecutor; + private final LinearLayoutManager mLayoutManager; + + @VisibleForTesting + protected InternetAdapter mAdapter; + @VisibleForTesting + protected WifiManager mWifiManager; + @VisibleForTesting + protected View mDialogView; + @VisibleForTesting + protected boolean mCanConfigWifi; + + private InternetDialogFactory mInternetDialogFactory; + private SubscriptionManager mSubscriptionManager; + private TelephonyManager mTelephonyManager; + private AlertDialog mAlertDialog; + private UiEventLogger mUiEventLogger; + private Context mContext; + private InternetDialogController mInternetDialogController; + private TextView mInternetDialogTitle; + private TextView mInternetDialogSubTitle; + private View mDivider; + private ProgressBar mProgressBar; + private LinearLayout mInternetDialogLayout; + private LinearLayout mConnectedWifListLayout; + private LinearLayout mMobileNetworkLayout; + private LinearLayout mTurnWifiOnLayout; + private LinearLayout mEthernetLayout; + private TextView mWifiToggleTitleText; + private LinearLayout mWifiScanNotifyLayout; + private TextView mWifiScanNotifyText; + private LinearLayout mSeeAllLayout; + private RecyclerView mWifiRecyclerView; + private ImageView mConnectedWifiIcon; + private ImageView mWifiSettingsIcon; + private TextView mConnectedWifiTitleText; + private TextView mConnectedWifiSummaryText; + private ImageView mSignalIcon; + private TextView mMobileTitleText; + private TextView mMobileSummaryText; + private Switch mMobileDataToggle; + private Switch mWiFiToggle; + private FrameLayout mDoneLayout; + private Drawable mBackgroundOn; + private int mListMaxHeight; + private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private boolean mCanConfigMobileData; + + // Wi-Fi entries + protected WifiEntry mConnectedWifiEntry; + protected int mWifiEntriesCount; + + // Wi-Fi scanning progress bar + protected boolean mIsProgressBarVisible; + protected boolean mIsSearchingHidden; + protected final Runnable mHideProgressBarRunnable = () -> { + setProgressBarVisible(false); + }; + protected Runnable mHideSearchingRunnable = () -> { + mIsSearchingHidden = true; + mInternetDialogSubTitle.setText(getSubtitleText()); + }; + + private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> { + // Set max height for list + if (mInternetDialogLayout.getHeight() > mListMaxHeight) { + ViewGroup.LayoutParams params = mInternetDialogLayout.getLayoutParams(); + params.height = mListMaxHeight; + mInternetDialogLayout.setLayoutParams(params); + } + }; + + public InternetDialog(Context context, InternetDialogFactory internetDialogFactory, + InternetDialogController internetDialogController, boolean canConfigMobileData, + boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger, + @Main Handler handler, @Background Executor executor) { + super(context, R.style.Theme_SystemUI_Dialog_Internet); + if (DEBUG) { + Log.d(TAG, "Init InternetDialog"); + } + mContext = context; + mHandler = handler; + mBackgroundExecutor = executor; + mInternetDialogFactory = internetDialogFactory; + mInternetDialogController = internetDialogController; + mSubscriptionManager = mInternetDialogController.getSubscriptionManager(); + mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId(); + mTelephonyManager = mInternetDialogController.getTelephonyManager(); + mWifiManager = mInternetDialogController.getWifiManager(); + mCanConfigMobileData = canConfigMobileData; + mCanConfigWifi = canConfigWifi; + + mLayoutManager = new LinearLayoutManager(mContext) { + @Override + public boolean canScrollVertically() { + return false; + } + }; + mListMaxHeight = context.getResources().getDimensionPixelSize( + R.dimen.internet_dialog_list_max_height); + mUiEventLogger = uiEventLogger; + mAdapter = new InternetAdapter(mInternetDialogController); + if (!aboveStatusBar) { + getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (DEBUG) { + Log.d(TAG, "onCreate"); + } + mUiEventLogger.log(InternetDialogEvent.INTERNET_DIALOG_SHOW); + mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog, + null); + final Window window = getWindow(); + final WindowManager.LayoutParams layoutParams = window.getAttributes(); + layoutParams.gravity = Gravity.BOTTOM; + // Move down the dialog to overlay the navigation bar. + layoutParams.setFitInsetsTypes( + layoutParams.getFitInsetsTypes() & ~WindowInsets.Type.navigationBars()); + layoutParams.setFitInsetsSides(WindowInsets.Side.all()); + layoutParams.setFitInsetsIgnoringVisibility(true); + window.setAttributes(layoutParams); + window.setContentView(mDialogView); + //Only fix the width for large screen or tablet. + window.setLayout(mContext.getResources().getDimensionPixelSize( + R.dimen.internet_dialog_list_max_width), ViewGroup.LayoutParams.WRAP_CONTENT); + window.setWindowAnimations(R.style.Animation_InternetDialog); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + window.addFlags(FLAG_LAYOUT_NO_LIMITS); + + mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog); + mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title); + mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); + mDivider = mDialogView.requireViewById(R.id.divider); + mProgressBar = mDialogView.requireViewById(R.id.wifi_searching_progress); + mEthernetLayout = mDialogView.requireViewById(R.id.ethernet_layout); + mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout); + mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout); + mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title); + mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); + mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); + mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout); + mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon); + mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title); + mConnectedWifiSummaryText = mDialogView.requireViewById(R.id.wifi_connected_summary); + mWifiSettingsIcon = mDialogView.requireViewById(R.id.wifi_settings_icon); + mWifiRecyclerView = mDialogView.requireViewById(R.id.wifi_list_layout); + mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout); + mDoneLayout = mDialogView.requireViewById(R.id.done_layout); + mSignalIcon = mDialogView.requireViewById(R.id.signal_icon); + mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title); + mMobileSummaryText = mDialogView.requireViewById(R.id.mobile_summary); + mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle); + mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle); + mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on); + mInternetDialogLayout.getViewTreeObserver().addOnGlobalLayoutListener( + mInternetListLayoutListener); + mInternetDialogTitle.setText(getDialogTitleText()); + mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL); + + setOnClickListener(); + mTurnWifiOnLayout.setBackground(null); + mWifiRecyclerView.setLayoutManager(mLayoutManager); + mWifiRecyclerView.setAdapter(mAdapter); + } + + @Override + public void onStart() { + super.onStart(); + if (DEBUG) { + Log.d(TAG, "onStart"); + } + mInternetDialogController.onStart(this, mCanConfigWifi); + if (!mCanConfigWifi) { + hideWifiViews(); + } + } + + @VisibleForTesting + void hideWifiViews() { + setProgressBarVisible(false); + mTurnWifiOnLayout.setVisibility(View.GONE); + mConnectedWifListLayout.setVisibility(View.GONE); + mWifiRecyclerView.setVisibility(View.GONE); + mSeeAllLayout.setVisibility(View.GONE); + } + + @Override + public void onStop() { + super.onStop(); + if (DEBUG) { + Log.d(TAG, "onStop"); + } + mHandler.removeCallbacks(mHideProgressBarRunnable); + mHandler.removeCallbacks(mHideSearchingRunnable); + mMobileNetworkLayout.setOnClickListener(null); + mMobileDataToggle.setOnCheckedChangeListener(null); + mConnectedWifListLayout.setOnClickListener(null); + mSeeAllLayout.setOnClickListener(null); + mWiFiToggle.setOnCheckedChangeListener(null); + mDoneLayout.setOnClickListener(null); + mInternetDialogController.onStop(); + mInternetDialogFactory.destroyDialog(); + } + + @Override + public void dismissDialog() { + if (DEBUG) { + Log.d(TAG, "dismissDialog"); + } + mInternetDialogFactory.destroyDialog(); + dismiss(); + } + + /** + * Update the internet dialog when receiving the callback. + * + * @param shouldUpdateMobileNetwork {@code true} for update the mobile network layout, + * otherwise {@code false}. + */ + void updateDialog(boolean shouldUpdateMobileNetwork) { + if (DEBUG) { + Log.d(TAG, "updateDialog"); + } + if (mInternetDialogController.isAirplaneModeEnabled()) { + mInternetDialogSubTitle.setVisibility(View.GONE); + } else { + mInternetDialogSubTitle.setText(getSubtitleText()); + } + updateEthernet(); + if (shouldUpdateMobileNetwork) { + setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular() + || mInternetDialogController.isCarrierNetworkActive()); + } + + if (!mCanConfigWifi) { + return; + } + + showProgressBar(); + final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked(); + final boolean isWifiEnabled = mWifiManager.isWifiEnabled(); + final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled(); + updateWifiToggle(isWifiEnabled, isDeviceLocked); + updateConnectedWifi(isWifiEnabled, isDeviceLocked); + updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked); + + final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0) + ? View.GONE : View.VISIBLE; + mWifiRecyclerView.setVisibility(visibility); + mSeeAllLayout.setVisibility(visibility); + } + + private void setOnClickListener() { + mMobileNetworkLayout.setOnClickListener(v -> { + if (mInternetDialogController.isMobileDataEnabled() + && !mInternetDialogController.isDeviceLocked()) { + if (!mInternetDialogController.activeNetworkIsCellular()) { + mInternetDialogController.connectCarrierNetwork(); + } + } + }); + mMobileDataToggle.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + if (!isChecked && shouldShowMobileDialog()) { + showTurnOffMobileDialog(); + } else if (!shouldShowMobileDialog()) { + mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId, + isChecked, false); + } + }); + mConnectedWifListLayout.setOnClickListener(v -> onClickConnectedWifi()); + mSeeAllLayout.setOnClickListener(v -> onClickSeeMoreButton()); + mWiFiToggle.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + buttonView.setChecked(isChecked); + mWifiManager.setWifiEnabled(isChecked); + }); + mDoneLayout.setOnClickListener(v -> dismiss()); + } + + @MainThread + private void updateEthernet() { + mEthernetLayout.setVisibility( + mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE); + } + + private void setMobileDataLayout(boolean isCarrierNetworkConnected) { + if (mInternetDialogController.isAirplaneModeEnabled() + || !mInternetDialogController.hasCarrier()) { + mMobileNetworkLayout.setVisibility(View.GONE); + } else { + mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); + mMobileNetworkLayout.setVisibility(View.VISIBLE); + mMobileTitleText.setText(getMobileNetworkTitle()); + if (!TextUtils.isEmpty(getMobileNetworkSummary())) { + mMobileSummaryText.setText( + Html.fromHtml(getMobileNetworkSummary(), Html.FROM_HTML_MODE_LEGACY)); + mMobileSummaryText.setVisibility(View.VISIBLE); + } else { + mMobileSummaryText.setVisibility(View.GONE); + } + + mBackgroundExecutor.execute(() -> { + Drawable drawable = getSignalStrengthDrawable(); + mHandler.post(() -> { + mSignalIcon.setImageDrawable(drawable); + }); + }); + mMobileTitleText.setTextAppearance(isCarrierNetworkConnected + ? R.style.TextAppearance_InternetDialog_Active + : R.style.TextAppearance_InternetDialog); + mMobileSummaryText.setTextAppearance(isCarrierNetworkConnected + ? R.style.TextAppearance_InternetDialog_Secondary_Active + : R.style.TextAppearance_InternetDialog_Secondary); + mMobileNetworkLayout.setBackground(isCarrierNetworkConnected ? mBackgroundOn : null); + + mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); + } + } + + @MainThread + private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) { + mWiFiToggle.setChecked(isWifiEnabled); + if (isDeviceLocked) { + mWifiToggleTitleText.setTextAppearance((mConnectedWifiEntry != null) + ? R.style.TextAppearance_InternetDialog_Active + : R.style.TextAppearance_InternetDialog); + } + mTurnWifiOnLayout.setBackground( + (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null); + } + + @MainThread + private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) { + if (!isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) { + mConnectedWifListLayout.setVisibility(View.GONE); + return; + } + mConnectedWifListLayout.setVisibility(View.VISIBLE); + mConnectedWifiTitleText.setText(mConnectedWifiEntry.getTitle()); + mConnectedWifiSummaryText.setText(mConnectedWifiEntry.getSummary(false)); + mConnectedWifiIcon.setImageDrawable( + mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry)); + mWifiSettingsIcon.setColorFilter( + mContext.getColor(R.color.connected_network_primary_color)); + } + + @MainThread + private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, + boolean isDeviceLocked) { + if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) { + mWifiScanNotifyLayout.setVisibility(View.GONE); + return; + } + if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) { + final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo( + AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION, + v -> mInternetDialogController.launchWifiScanningSetting()); + mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify( + getContext().getText(R.string.wifi_scan_notify_message), linkInfo)); + mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance()); + } + mWifiScanNotifyLayout.setVisibility(View.VISIBLE); + } + + void onClickConnectedWifi() { + if (mConnectedWifiEntry == null) { + return; + } + mInternetDialogController.launchWifiNetworkDetailsSetting(mConnectedWifiEntry.getKey()); + } + + void onClickSeeMoreButton() { + mInternetDialogController.launchNetworkSetting(); + } + + CharSequence getDialogTitleText() { + return mInternetDialogController.getDialogTitleText(); + } + + CharSequence getSubtitleText() { + return mInternetDialogController.getSubtitleText( + mIsProgressBarVisible && !mIsSearchingHidden); + } + + private Drawable getSignalStrengthDrawable() { + return mInternetDialogController.getSignalStrengthDrawable(); + } + + CharSequence getMobileNetworkTitle() { + return mInternetDialogController.getMobileNetworkTitle(); + } + + String getMobileNetworkSummary() { + return mInternetDialogController.getMobileNetworkSummary(); + } + + protected void showProgressBar() { + if (mWifiManager == null || !mWifiManager.isWifiEnabled() + || mInternetDialogController.isDeviceLocked()) { + setProgressBarVisible(false); + return; + } + setProgressBarVisible(true); + if (mConnectedWifiEntry != null || mWifiEntriesCount > 0) { + mHandler.postDelayed(mHideProgressBarRunnable, PROGRESS_DELAY_MS); + } else if (!mIsSearchingHidden) { + mHandler.postDelayed(mHideSearchingRunnable, PROGRESS_DELAY_MS); + } + } + + private void setProgressBarVisible(boolean visible) { + if (mWifiManager.isWifiEnabled() && mAdapter.mHolderView != null + && mAdapter.mHolderView.isAttachedToWindow()) { + mIsProgressBarVisible = true; + } + mIsProgressBarVisible = visible; + mProgressBar.setVisibility(mIsProgressBarVisible ? View.VISIBLE : View.GONE); + mDivider.setVisibility(mIsProgressBarVisible ? View.GONE : View.VISIBLE); + mInternetDialogSubTitle.setText(getSubtitleText()); + } + + private boolean shouldShowMobileDialog() { + boolean flag = Prefs.getBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, + false); + if (mInternetDialogController.isMobileDataEnabled() && !flag) { + return true; + } + return false; + } + + private void showTurnOffMobileDialog() { + CharSequence carrierName = getMobileNetworkTitle(); + boolean isInService = mInternetDialogController.isVoiceStateInService(); + if (TextUtils.isEmpty(carrierName) || !isInService) { + carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier); + } + mAlertDialog = new Builder(mContext) + .setTitle(R.string.mobile_data_disable_title) + .setMessage(mContext.getString(R.string.mobile_data_disable_message, carrierName)) + .setNegativeButton(android.R.string.cancel, (d, w) -> { + mMobileDataToggle.setChecked(true); + }) + .setPositiveButton( + com.android.internal.R.string.alert_windows_notification_turn_off_action, + (d, w) -> { + mInternetDialogController.setMobileDataEnabled(mContext, + mDefaultDataSubId, false, false); + mMobileDataToggle.setChecked(false); + Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true); + }) + .create(); + mAlertDialog.setOnCancelListener(dialog -> mMobileDataToggle.setChecked(true)); + mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + SystemUIDialog.setShowForAllUsers(mAlertDialog, true); + SystemUIDialog.registerDismissListener(mAlertDialog); + SystemUIDialog.setWindowOnTop(mAlertDialog); + mAlertDialog.show(); + } + + @Override + public void onRefreshCarrierInfo() { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onSimStateChanged() { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + @WorkerThread + public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + @WorkerThread + public void onLost(Network network) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onSubscriptionsChanged(int defaultDataSubId) { + mDefaultDataSubId = defaultDataSubId; + mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onUserMobileDataStateChanged(boolean enabled) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onServiceStateChanged(ServiceState serviceState) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + @WorkerThread + public void onDataConnectionStateChanged(int state, int networkType) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { + mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + } + + @Override + @WorkerThread + public void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries, + @Nullable WifiEntry connectedEntry) { + mConnectedWifiEntry = connectedEntry; + mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size(); + mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount); + mHandler.post(() -> { + mAdapter.notifyDataSetChanged(); + updateDialog(false /* shouldUpdateMobileNetwork */); + }); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (mAlertDialog != null && !mAlertDialog.isShowing()) { + if (!hasFocus && isShowing()) { + dismiss(); + } + } + } + + public enum InternetDialogEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "The Internet dialog became visible on the screen.") + INTERNET_DIALOG_SHOW(843); + + private final int mId; + + InternetDialogEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java new file mode 100644 index 000000000000..67e34113bebb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -0,0 +1,1100 @@ +/* + * 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.tiles.dialog; + +import static com.android.settingslib.mobile.MobileMappings.getIconKey; +import static com.android.settingslib.mobile.MobileMappings.mapIconSets; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.UserHandle; +import android.provider.Settings; +import android.telephony.AccessNetworkConstants; +import android.telephony.NetworkRegistrationInfo; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; + +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.annotation.WorkerThread; + +import com.android.internal.logging.UiEventLogger; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.settingslib.DeviceInfoUtils; +import com.android.settingslib.SignalIcon; +import com.android.settingslib.Utils; +import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.MobileMappings; +import com.android.settingslib.mobile.TelephonyIcons; +import com.android.settingslib.net.SignalStrengthUtil; +import com.android.settingslib.wifi.WifiUtils; +import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.LocationController; +import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; +import com.android.systemui.toast.SystemUIToast; +import com.android.systemui.toast.ToastFactory; +import com.android.systemui.util.CarrierConfigTracker; +import com.android.systemui.util.settings.GlobalSettings; +import com.android.wifitrackerlib.MergedCarrierEntry; +import com.android.wifitrackerlib.WifiEntry; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.inject.Inject; + +public class InternetDialogController implements WifiEntry.DisconnectCallback, + NetworkController.AccessPointController.AccessPointCallback { + + private static final String TAG = "InternetDialogController"; + private static final String ACTION_NETWORK_PROVIDER_SETTINGS = + "android.settings.NETWORK_PROVIDER_SETTINGS"; + private static final String ACTION_WIFI_SCANNING_SETTINGS = + "android.settings.WIFI_SCANNING_SETTINGS"; + private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; + public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT); + public static final int NO_CELL_DATA_TYPE_ICON = 0; + private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off; + private static final int SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT = + R.string.tap_a_network_to_connect; + private static final int SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS = + R.string.unlock_to_view_networks; + private static final int SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS = + R.string.wifi_empty_list_wifi_on; + private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE = + R.string.non_carrier_network_unavailable; + private static final int SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE = + R.string.all_network_unavailable; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + static final int MAX_WIFI_ENTRY_COUNT = 4; + + private WifiManager mWifiManager; + private Context mContext; + private SubscriptionManager mSubscriptionManager; + private TelephonyManager mTelephonyManager; + private ConnectivityManager mConnectivityManager; + private CarrierConfigTracker mCarrierConfigTracker; + private TelephonyDisplayInfo mTelephonyDisplayInfo = + new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); + private Handler mHandler; + private Handler mWorkerHandler; + private MobileMappings.Config mConfig = null; + private Executor mExecutor; + private AccessPointController mAccessPointController; + private IntentFilter mConnectionStateFilter; + private InternetDialogCallback mCallback; + private WifiEntry mConnectedEntry; + private int mWifiEntriesCount; + private UiEventLogger mUiEventLogger; + private BroadcastDispatcher mBroadcastDispatcher; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private GlobalSettings mGlobalSettings; + private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private ConnectivityManager.NetworkCallback mConnectivityManagerNetworkCallback; + private WindowManager mWindowManager; + private ToastFactory mToastFactory; + private SignalDrawable mSignalDrawable; + private LocationController mLocationController; + + @VisibleForTesting + static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f; + @VisibleForTesting + static final float TOAST_PARAMS_VERTICAL_WEIGHT = 1.0f; + @VisibleForTesting + static final long SHORT_DURATION_TIMEOUT = 4000; + @VisibleForTesting + protected ActivityStarter mActivityStarter; + @VisibleForTesting + protected SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangedListener; + @VisibleForTesting + protected InternetTelephonyCallback mInternetTelephonyCallback; + @VisibleForTesting + protected WifiUtils.InternetIconInjector mWifiIconInjector; + @VisibleForTesting + protected boolean mCanConfigWifi; + @VisibleForTesting + protected KeyguardStateController mKeyguardStateController; + @VisibleForTesting + protected boolean mHasEthernet = false; + + private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onRefreshCarrierInfo() { + mCallback.onRefreshCarrierInfo(); + } + + @Override + public void onSimStateChanged(int subId, int slotId, int simState) { + mCallback.onSimStateChanged(); + } + }; + + protected List<SubscriptionInfo> getSubscriptionInfo() { + return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false); + } + + @Inject + public InternetDialogController(@NonNull Context context, UiEventLogger uiEventLogger, + ActivityStarter starter, AccessPointController accessPointController, + SubscriptionManager subscriptionManager, TelephonyManager telephonyManager, + @Nullable WifiManager wifiManager, ConnectivityManager connectivityManager, + @Main Handler handler, @Main Executor mainExecutor, + BroadcastDispatcher broadcastDispatcher, KeyguardUpdateMonitor keyguardUpdateMonitor, + GlobalSettings globalSettings, KeyguardStateController keyguardStateController, + WindowManager windowManager, ToastFactory toastFactory, + @Background Handler workerHandler, + CarrierConfigTracker carrierConfigTracker, + LocationController locationController) { + if (DEBUG) { + Log.d(TAG, "Init InternetDialogController"); + } + mHandler = handler; + mWorkerHandler = workerHandler; + mExecutor = mainExecutor; + mContext = context; + mGlobalSettings = globalSettings; + mWifiManager = wifiManager; + mTelephonyManager = telephonyManager; + mConnectivityManager = connectivityManager; + mSubscriptionManager = subscriptionManager; + mCarrierConfigTracker = carrierConfigTracker; + mBroadcastDispatcher = broadcastDispatcher; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mKeyguardStateController = keyguardStateController; + mConnectionStateFilter = new IntentFilter(); + mConnectionStateFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); + mConnectionStateFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); + mUiEventLogger = uiEventLogger; + mActivityStarter = starter; + mAccessPointController = accessPointController; + mWifiIconInjector = new WifiUtils.InternetIconInjector(mContext); + mConnectivityManagerNetworkCallback = new DataConnectivityListener(); + mWindowManager = windowManager; + mToastFactory = toastFactory; + mSignalDrawable = new SignalDrawable(mContext); + mLocationController = locationController; + } + + void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) { + if (DEBUG) { + Log.d(TAG, "onStart"); + } + mCallback = callback; + mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); + mAccessPointController.addAccessPointCallback(this); + mBroadcastDispatcher.registerReceiver(mConnectionStateReceiver, mConnectionStateFilter, + mExecutor); + // Listen the subscription changes + mOnSubscriptionsChangedListener = new InternetOnSubscriptionChangedListener(); + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, + mOnSubscriptionsChangedListener); + mDefaultDataSubId = getDefaultDataSubscriptionId(); + if (DEBUG) { + Log.d(TAG, "Init, SubId: " + mDefaultDataSubId); + } + mConfig = MobileMappings.Config.readConfig(mContext); + mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mInternetTelephonyCallback = new InternetTelephonyCallback(); + mTelephonyManager.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback); + // Listen the connectivity changes + mConnectivityManager.registerDefaultNetworkCallback(mConnectivityManagerNetworkCallback); + mCanConfigWifi = canConfigWifi; + scanWifiAccessPoints(); + } + + void onStop() { + if (DEBUG) { + Log.d(TAG, "onStop"); + } + mBroadcastDispatcher.unregisterReceiver(mConnectionStateReceiver); + mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback); + mSubscriptionManager.removeOnSubscriptionsChangedListener( + mOnSubscriptionsChangedListener); + mAccessPointController.removeAccessPointCallback(this); + mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback); + mConnectivityManager.unregisterNetworkCallback(mConnectivityManagerNetworkCallback); + } + + @VisibleForTesting + boolean isAirplaneModeEnabled() { + return mGlobalSettings.getInt(Settings.Global.AIRPLANE_MODE_ON, 0) != 0; + } + + @VisibleForTesting + protected int getDefaultDataSubscriptionId() { + return mSubscriptionManager.getDefaultDataSubscriptionId(); + } + + @VisibleForTesting + protected Intent getSettingsIntent() { + return new Intent(ACTION_NETWORK_PROVIDER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + + protected Intent getWifiDetailsSettingsIntent(String key) { + if (TextUtils.isEmpty(key)) { + if (DEBUG) { + Log.d(TAG, "connected entry's key is empty"); + } + return null; + } + return WifiUtils.getWifiDetailsSettingsIntent(key); + } + + CharSequence getDialogTitleText() { + if (isAirplaneModeEnabled()) { + return mContext.getText(R.string.airplane_mode); + } + return mContext.getText(R.string.quick_settings_internet_label); + } + + CharSequence getSubtitleText(boolean isProgressBarVisible) { + if (isAirplaneModeEnabled()) { + return null; + } + + if (mCanConfigWifi && !mWifiManager.isWifiEnabled()) { + // When the airplane mode is off and Wi-Fi is disabled. + // Sub-Title: Wi-Fi is off + if (DEBUG) { + Log.d(TAG, "Airplane mode off + Wi-Fi off."); + } + return mContext.getText(SUBTITLE_TEXT_WIFI_IS_OFF); + } + + if (isDeviceLocked()) { + // When the device is locked. + // Sub-Title: Unlock to view networks + if (DEBUG) { + Log.d(TAG, "The device is locked."); + } + return mContext.getText(SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS); + } + + if (mConnectedEntry != null || mWifiEntriesCount > 0) { + return mCanConfigWifi ? mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT) : null; + } + + if (mCanConfigWifi && isProgressBarVisible) { + // When the Wi-Fi scan result callback is received + // Sub-Title: Searching for networks... + return mContext.getText(SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS); + } + + // Sub-Title: + // show non_carrier_network_unavailable + // - while Wi-Fi on + no Wi-Fi item + // - while Wi-Fi on + no Wi-Fi item + mobile data off + // show all_network_unavailable: + // - while Wi-Fi on + no Wi-Fi item + no carrier item + // - while Wi-Fi on + no Wi-Fi item + service is out of service + // - while Wi-Fi on + no Wi-Fi item + mobile data on + no carrier data. + if (DEBUG) { + Log.d(TAG, "No Wi-Fi item."); + } + if (!hasCarrier() || (!isVoiceStateInService() && !isDataStateInService())) { + if (DEBUG) { + Log.d(TAG, "No carrier or service is out of service."); + } + return mContext.getText(SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE); + } + + if (mCanConfigWifi && !isMobileDataEnabled()) { + if (DEBUG) { + Log.d(TAG, "Mobile data off"); + } + return mContext.getText(SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE); + } + + if (!activeNetworkIsCellular()) { + if (DEBUG) { + Log.d(TAG, "No carrier data."); + } + return mContext.getText(SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE); + } + + if (mCanConfigWifi) { + return mContext.getText(SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE); + } + return null; + } + + Drawable getInternetWifiDrawable(@NonNull WifiEntry wifiEntry) { + if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) { + return null; + } + final Drawable drawable = + mWifiIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(), wifiEntry.getLevel()); + if (drawable == null) { + return null; + } + drawable.setTint(mContext.getColor(R.color.connected_network_primary_color)); + return drawable; + } + + Drawable getSignalStrengthDrawable() { + Drawable drawable = mContext.getDrawable( + R.drawable.ic_signal_strength_zero_bar_no_internet); + try { + if (mTelephonyManager == null) { + if (DEBUG) { + Log.d(TAG, "TelephonyManager is null"); + } + return drawable; + } + + if (isDataStateInService() || isVoiceStateInService()) { + AtomicReference<Drawable> shared = new AtomicReference<>(); + shared.set(getSignalStrengthDrawableWithLevel()); + drawable = shared.get(); + } + + int tintColor = Utils.getColorAttrDefaultColor(mContext, + android.R.attr.textColorTertiary); + if (activeNetworkIsCellular() || isCarrierNetworkActive()) { + tintColor = mContext.getColor(R.color.connected_network_primary_color); + } + drawable.setTint(tintColor); + } catch (Throwable e) { + e.printStackTrace(); + } + return drawable; + } + + /** + * To get the signal bar icon with level. + * + * @return The Drawable which is a signal bar icon with level. + */ + Drawable getSignalStrengthDrawableWithLevel() { + final SignalStrength strength = mTelephonyManager.getSignalStrength(); + int level = (strength == null) ? 0 : strength.getLevel(); + int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; + if (mSubscriptionManager != null && shouldInflateSignalStrength(mDefaultDataSubId)) { + level += 1; + numLevels += 1; + } + return getSignalStrengthIcon(mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON, + !isMobileDataEnabled()); + } + + Drawable getSignalStrengthIcon(Context context, int level, int numLevels, + int iconType, boolean cutOut) { + mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut)); + + // Make the network type drawable + final Drawable networkDrawable = + iconType == NO_CELL_DATA_TYPE_ICON + ? EMPTY_DRAWABLE + : context.getResources().getDrawable(iconType, context.getTheme()); + + // Overlay the two drawables + final Drawable[] layers = {networkDrawable, mSignalDrawable}; + final int iconSize = + context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size); + + final LayerDrawable icons = new LayerDrawable(layers); + // Set the network type icon at the top left + icons.setLayerGravity(0 /* index of networkDrawable */, Gravity.TOP | Gravity.LEFT); + // Set the signal strength icon at the bottom right + icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT); + icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize); + icons.setTintList(Utils.getColorAttr(context, android.R.attr.textColorTertiary)); + return icons; + } + + private boolean shouldInflateSignalStrength(int subId) { + return SignalStrengthUtil.shouldInflateSignalStrength(mContext, subId); + } + + private CharSequence getUniqueSubscriptionDisplayName(int subscriptionId, Context context) { + final Map<Integer, CharSequence> displayNames = getUniqueSubscriptionDisplayNames(context); + return displayNames.getOrDefault(subscriptionId, ""); + } + + private Map<Integer, CharSequence> getUniqueSubscriptionDisplayNames(Context context) { + class DisplayInfo { + public SubscriptionInfo subscriptionInfo; + public CharSequence originalName; + public CharSequence uniqueName; + } + + // Map of SubscriptionId to DisplayName + final Supplier<Stream<DisplayInfo>> originalInfos = + () -> getSubscriptionInfo() + .stream() + .filter(i -> { + // Filter out null values. + return (i != null && i.getDisplayName() != null); + }) + .map(i -> { + DisplayInfo info = new DisplayInfo(); + info.subscriptionInfo = i; + info.originalName = i.getDisplayName().toString().trim(); + return info; + }); + + // A Unique set of display names + Set<CharSequence> uniqueNames = new HashSet<>(); + // Return the set of duplicate names + final Set<CharSequence> duplicateOriginalNames = originalInfos.get() + .filter(info -> !uniqueNames.add(info.originalName)) + .map(info -> info.originalName) + .collect(Collectors.toSet()); + + // If a display name is duplicate, append the final 4 digits of the phone number. + // Creates a mapping of Subscription id to original display name + phone number display name + final Supplier<Stream<DisplayInfo>> uniqueInfos = () -> originalInfos.get().map(info -> { + if (duplicateOriginalNames.contains(info.originalName)) { + // This may return null, if the user cannot view the phone number itself. + final String phoneNumber = DeviceInfoUtils.getBidiFormattedPhoneNumber(context, + info.subscriptionInfo); + String lastFourDigits = ""; + if (phoneNumber != null) { + lastFourDigits = (phoneNumber.length() > 4) + ? phoneNumber.substring(phoneNumber.length() - 4) : phoneNumber; + } + + if (TextUtils.isEmpty(lastFourDigits)) { + info.uniqueName = info.originalName; + } else { + info.uniqueName = info.originalName + " " + lastFourDigits; + } + + } else { + info.uniqueName = info.originalName; + } + return info; + }); + + // Check uniqueness a second time. + // We might not have had permission to view the phone numbers. + // There might also be multiple phone numbers whose last 4 digits the same. + uniqueNames.clear(); + final Set<CharSequence> duplicatePhoneNames = uniqueInfos.get() + .filter(info -> !uniqueNames.add(info.uniqueName)) + .map(info -> info.uniqueName) + .collect(Collectors.toSet()); + + return uniqueInfos.get().map(info -> { + if (duplicatePhoneNames.contains(info.uniqueName)) { + info.uniqueName = info.originalName + " " + + info.subscriptionInfo.getSubscriptionId(); + } + return info; + }).collect(Collectors.toMap( + info -> info.subscriptionInfo.getSubscriptionId(), + info -> info.uniqueName)); + } + + CharSequence getMobileNetworkTitle() { + return getUniqueSubscriptionDisplayName(mDefaultDataSubId, mContext); + } + + String getMobileNetworkSummary() { + String description = getNetworkTypeDescription(mContext, mConfig, + mTelephonyDisplayInfo, mDefaultDataSubId); + return getMobileSummary(mContext, description); + } + + /** + * Get currently description of mobile network type. + */ + private String getNetworkTypeDescription(Context context, MobileMappings.Config config, + TelephonyDisplayInfo telephonyDisplayInfo, int subId) { + String iconKey = getIconKey(telephonyDisplayInfo); + + if (mapIconSets(config) == null || mapIconSets(config).get(iconKey) == null) { + if (DEBUG) { + Log.d(TAG, "The description of network type is empty."); + } + return ""; + } + + int resId = mapIconSets(config).get(iconKey).dataContentDescription; + if (isCarrierNetworkActive()) { + SignalIcon.MobileIconGroup carrierMergedWifiIconGroup = + TelephonyIcons.CARRIER_MERGED_WIFI; + resId = carrierMergedWifiIconGroup.dataContentDescription; + } + + return resId != 0 + ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : ""; + } + + private String getMobileSummary(Context context, String networkTypeDescription) { + if (!isMobileDataEnabled()) { + return context.getString(R.string.mobile_data_off_summary); + } + if (!isDataStateInService()) { + return context.getString(R.string.mobile_data_no_connection); + } + String summary = networkTypeDescription; + if (activeNetworkIsCellular() || isCarrierNetworkActive()) { + summary = context.getString(R.string.preference_summary_default_combination, + context.getString(R.string.mobile_data_connection_active), + networkTypeDescription); + } + return summary; + } + + void launchNetworkSetting() { + mCallback.dismissDialog(); + mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0); + } + + void launchWifiNetworkDetailsSetting(String key) { + Intent intent = getWifiDetailsSettingsIntent(key); + if (intent != null) { + mCallback.dismissDialog(); + mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); + } + } + + void launchWifiScanningSetting() { + mCallback.dismissDialog(); + final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); + } + + void connectCarrierNetwork() { + final MergedCarrierEntry mergedCarrierEntry = + mAccessPointController.getMergedCarrierEntry(); + if (mergedCarrierEntry != null && mergedCarrierEntry.canConnect()) { + mergedCarrierEntry.connect(null /* ConnectCallback */, false); + makeOverlayToast(R.string.wifi_wont_autoconnect_for_now); + } + } + + boolean isCarrierNetworkActive() { + final MergedCarrierEntry mergedCarrierEntry = + mAccessPointController.getMergedCarrierEntry(); + return mergedCarrierEntry != null && mergedCarrierEntry.isDefaultNetwork(); + } + + @WorkerThread + void setMergedCarrierWifiEnabledIfNeed(int subId, boolean enabled) { + // If the Carrier Provisions Wi-Fi Merged Networks enabled, do not set the merged carrier + // Wi-Fi state together. + if (mCarrierConfigTracker.getCarrierProvisionsWifiMergedNetworksBool(subId)) { + return; + } + + final MergedCarrierEntry entry = mAccessPointController.getMergedCarrierEntry(); + if (entry == null) { + if (DEBUG) { + Log.d(TAG, "MergedCarrierEntry is null, can not set the status."); + } + return; + } + entry.setEnabled(enabled); + } + + WifiManager getWifiManager() { + return mWifiManager; + } + + TelephonyManager getTelephonyManager() { + return mTelephonyManager; + } + + SubscriptionManager getSubscriptionManager() { + return mSubscriptionManager; + } + + /** + * @return whether there is the carrier item in the slice. + */ + boolean hasCarrier() { + if (mSubscriptionManager == null) { + if (DEBUG) { + Log.d(TAG, "SubscriptionManager is null, can not check carrier."); + } + return false; + } + + if (isAirplaneModeEnabled() || mTelephonyManager == null + || mSubscriptionManager.getActiveSubscriptionIdList().length <= 0) { + return false; + } + return true; + } + + /** + * Return {@code true} if mobile data is enabled + */ + boolean isMobileDataEnabled() { + if (mTelephonyManager == null || !mTelephonyManager.isDataEnabled()) { + return false; + } + return true; + } + + /** + * Set whether to enable data for {@code subId}, also whether to disable data for other + * subscription + */ + void setMobileDataEnabled(Context context, int subId, boolean enabled, + boolean disableOtherSubscriptions) { + if (mTelephonyManager == null) { + if (DEBUG) { + Log.d(TAG, "TelephonyManager is null, can not set mobile data."); + } + return; + } + + if (mSubscriptionManager == null) { + if (DEBUG) { + Log.d(TAG, "SubscriptionManager is null, can not set mobile data."); + } + return; + } + + mTelephonyManager.setDataEnabled(enabled); + if (disableOtherSubscriptions) { + final List<SubscriptionInfo> subInfoList = + mSubscriptionManager.getActiveSubscriptionInfoList(); + if (subInfoList != null) { + for (SubscriptionInfo subInfo : subInfoList) { + // We never disable mobile data for opportunistic subscriptions. + if (subInfo.getSubscriptionId() != subId && !subInfo.isOpportunistic()) { + context.getSystemService(TelephonyManager.class).createForSubscriptionId( + subInfo.getSubscriptionId()).setDataEnabled(false); + } + } + } + } + mWorkerHandler.post(() -> setMergedCarrierWifiEnabledIfNeed(subId, enabled)); + } + + boolean isDataStateInService() { + final ServiceState serviceState = mTelephonyManager.getServiceState(); + NetworkRegistrationInfo regInfo = + (serviceState == null) ? null : serviceState.getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + return (regInfo == null) ? false : regInfo.isRegistered(); + } + + boolean isVoiceStateInService() { + if (mTelephonyManager == null) { + if (DEBUG) { + Log.d(TAG, "TelephonyManager is null, can not detect voice state."); + } + return false; + } + + final ServiceState serviceState = mTelephonyManager.getServiceState(); + return serviceState != null + && serviceState.getState() == serviceState.STATE_IN_SERVICE; + } + + public boolean isDeviceLocked() { + return !mKeyguardStateController.isUnlocked(); + } + + boolean activeNetworkIsCellular() { + if (mConnectivityManager == null) { + if (DEBUG) { + Log.d(TAG, "ConnectivityManager is null, can not check active network."); + } + return false; + } + + final Network activeNetwork = mConnectivityManager.getActiveNetwork(); + if (activeNetwork == null) { + return false; + } + final NetworkCapabilities networkCapabilities = + mConnectivityManager.getNetworkCapabilities(activeNetwork); + if (networkCapabilities == null) { + return false; + } + return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR); + } + + boolean connect(WifiEntry ap) { + if (ap == null) { + if (DEBUG) { + Log.d(TAG, "No Wi-Fi ap to connect."); + } + return false; + } + + if (ap.getWifiConfiguration() != null) { + if (DEBUG) { + Log.d(TAG, "connect networkId=" + ap.getWifiConfiguration().networkId); + } + } else { + if (DEBUG) { + Log.d(TAG, "connect to unsaved network " + ap.getTitle()); + } + } + ap.connect(new WifiEntryConnectCallback(mActivityStarter, ap, this)); + return false; + } + + @WorkerThread + boolean isWifiScanEnabled() { + if (!mLocationController.isLocationEnabled()) { + return false; + } + return mWifiManager.isScanAlwaysAvailable(); + } + + static class WifiEntryConnectCallback implements WifiEntry.ConnectCallback { + final ActivityStarter mActivityStarter; + final WifiEntry mWifiEntry; + final InternetDialogController mInternetDialogController; + + WifiEntryConnectCallback(ActivityStarter activityStarter, WifiEntry connectWifiEntry, + InternetDialogController internetDialogController) { + mActivityStarter = activityStarter; + mWifiEntry = connectWifiEntry; + mInternetDialogController = internetDialogController; + } + + @Override + public void onConnectResult(@ConnectStatus int status) { + if (DEBUG) { + Log.d(TAG, "onConnectResult " + status); + } + + if (status == WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) { + final Intent intent = new Intent("com.android.settings.WIFI_DIALOG") + .putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, mWifiEntry.getKey()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivityStarter.startActivity(intent, false /* dismissShade */); + } else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) { + mInternetDialogController.makeOverlayToast(R.string.wifi_failed_connect_message); + } else { + if (DEBUG) { + Log.d(TAG, "connect failure reason=" + status); + } + } + } + } + + private void scanWifiAccessPoints() { + if (mCanConfigWifi) { + mAccessPointController.scanForAccessPoints(); + } + } + + @Override + @WorkerThread + public void onAccessPointsChanged(List<WifiEntry> accessPoints) { + if (!mCanConfigWifi) { + return; + } + + if (accessPoints == null || accessPoints.size() == 0) { + mConnectedEntry = null; + mWifiEntriesCount = 0; + if (mCallback != null) { + mCallback.onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry */); + } + return; + } + + boolean hasConnectedWifi = false; + final int accessPointSize = accessPoints.size(); + for (int i = 0; i < accessPointSize; i++) { + WifiEntry wifiEntry = accessPoints.get(i); + if (wifiEntry.isDefaultNetwork() && wifiEntry.hasInternetAccess()) { + mConnectedEntry = wifiEntry; + hasConnectedWifi = true; + break; + } + } + if (!hasConnectedWifi) { + mConnectedEntry = null; + } + + int count = MAX_WIFI_ENTRY_COUNT; + if (mHasEthernet) { + count -= 1; + } + if (hasCarrier()) { + count -= 1; + } + if (hasConnectedWifi) { + count -= 1; + } + final List<WifiEntry> wifiEntries = accessPoints.stream() + .filter(wifiEntry -> (!wifiEntry.isDefaultNetwork() + || !wifiEntry.hasInternetAccess())) + .limit(count) + .collect(Collectors.toList()); + mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size(); + + if (mCallback != null) { + mCallback.onAccessPointsChanged(wifiEntries, mConnectedEntry); + } + } + + @Override + public void onSettingsActivityTriggered(Intent settingsIntent) { + } + + @Override + public void onDisconnectResult(int status) { + } + + private class InternetTelephonyCallback extends TelephonyCallback implements + TelephonyCallback.DataConnectionStateListener, + TelephonyCallback.DisplayInfoListener, + TelephonyCallback.ServiceStateListener, + TelephonyCallback.SignalStrengthsListener, + TelephonyCallback.UserMobileDataStateListener { + + @Override + public void onServiceStateChanged(@NonNull ServiceState serviceState) { + mCallback.onServiceStateChanged(serviceState); + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + mCallback.onDataConnectionStateChanged(state, networkType); + } + + @Override + public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength) { + mCallback.onSignalStrengthsChanged(signalStrength); + } + + @Override + public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo) { + mTelephonyDisplayInfo = telephonyDisplayInfo; + mCallback.onDisplayInfoChanged(telephonyDisplayInfo); + } + + @Override + public void onUserMobileDataStateChanged(boolean enabled) { + mCallback.onUserMobileDataStateChanged(enabled); + } + } + + private class InternetOnSubscriptionChangedListener + extends SubscriptionManager.OnSubscriptionsChangedListener { + InternetOnSubscriptionChangedListener() { + super(); + } + + @Override + public void onSubscriptionsChanged() { + updateListener(); + } + } + + private class DataConnectivityListener extends ConnectivityManager.NetworkCallback { + @Override + @WorkerThread + public void onCapabilitiesChanged(@NonNull Network network, + @NonNull NetworkCapabilities capabilities) { + mHasEthernet = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET); + if (mCanConfigWifi && (mHasEthernet || capabilities.hasTransport( + NetworkCapabilities.TRANSPORT_WIFI))) { + scanWifiAccessPoints(); + } + // update UI + mCallback.onCapabilitiesChanged(network, capabilities); + } + + @Override + @WorkerThread + public void onLost(@NonNull Network network) { + mHasEthernet = false; + mCallback.onLost(network); + } + } + + /** + * Return {@code true} If the Ethernet exists + */ + @MainThread + public boolean hasEthernet() { + return mHasEthernet; + } + + private final BroadcastReceiver mConnectionStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) { + if (DEBUG) { + Log.d(TAG, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED"); + } + mConfig = MobileMappings.Config.readConfig(context); + updateListener(); + } else if (WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION.equals(action)) { + updateListener(); + } + } + }; + + private void updateListener() { + int defaultDataSubId = getDefaultDataSubscriptionId(); + if (mDefaultDataSubId == getDefaultDataSubscriptionId()) { + if (DEBUG) { + Log.d(TAG, "DDS: no change"); + } + return; + } + + mDefaultDataSubId = defaultDataSubId; + if (DEBUG) { + Log.d(TAG, "DDS: defaultDataSubId:" + mDefaultDataSubId); + } + if (SubscriptionManager.isUsableSubscriptionId(mDefaultDataSubId)) { + mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback); + mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mTelephonyManager.registerTelephonyCallback(mHandler::post, + mInternetTelephonyCallback); + mCallback.onSubscriptionsChanged(mDefaultDataSubId); + } + } + + public WifiUtils.InternetIconInjector getWifiIconInjector() { + return mWifiIconInjector; + } + + interface InternetDialogCallback { + + void onRefreshCarrierInfo(); + + void onSimStateChanged(); + + void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities); + + void onLost(@NonNull Network network); + + void onSubscriptionsChanged(int defaultDataSubId); + + void onServiceStateChanged(ServiceState serviceState); + + void onDataConnectionStateChanged(int state, int networkType); + + void onSignalStrengthsChanged(SignalStrength signalStrength); + + void onUserMobileDataStateChanged(boolean enabled); + + void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo); + + void dismissDialog(); + + void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries, + @Nullable WifiEntry connectedEntry); + } + + void makeOverlayToast(int stringId) { + final Resources res = mContext.getResources(); + + final SystemUIToast systemUIToast = mToastFactory.createToast(mContext, + res.getString(stringId), mContext.getPackageName(), UserHandle.myUserId(), + res.getConfiguration().orientation); + if (systemUIToast == null) { + return; + } + + View toastView = systemUIToast.getView(); + + final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + params.format = PixelFormat.TRANSLUCENT; + params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; + params.y = systemUIToast.getYOffset(); + + int absGravity = Gravity.getAbsoluteGravity(systemUIToast.getGravity(), + res.getConfiguration().getLayoutDirection()); + params.gravity = absGravity; + if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { + params.horizontalWeight = TOAST_PARAMS_HORIZONTAL_WEIGHT; + } + if ((absGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { + params.verticalWeight = TOAST_PARAMS_VERTICAL_WEIGHT; + } + + mWindowManager.addView(toastView, params); + + Animator inAnimator = systemUIToast.getInAnimation(); + if (inAnimator != null) { + inAnimator.start(); + } + + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + Animator outAnimator = systemUIToast.getOutAnimation(); + if (outAnimator != null) { + outAnimator.start(); + outAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + mWindowManager.removeViewImmediate(toastView); + } + }); + } + } + }, SHORT_DURATION_TIMEOUT); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt new file mode 100644 index 000000000000..ea5df17bca58 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt @@ -0,0 +1,67 @@ +/* + * 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.tiles.dialog + +import android.content.Context +import android.os.Handler +import android.util.Log +import com.android.internal.logging.UiEventLogger +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main +import java.util.concurrent.Executor +import javax.inject.Inject + +private const val TAG = "InternetDialogFactory" +private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) + +/** + * Factory to create [InternetDialog] objects. + */ +@SysUISingleton +class InternetDialogFactory @Inject constructor( + @Main private val handler: Handler, + @Background private val executor: Executor, + private val internetDialogController: InternetDialogController, + private val context: Context, + private val uiEventLogger: UiEventLogger +) { + companion object { + var internetDialog: InternetDialog? = null + } + + /** Creates a [InternetDialog]. */ + fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean, canConfigWifi: Boolean) { + if (internetDialog != null) { + if (DEBUG) { + Log.d(TAG, "InternetDialog is showing, do not create it twice.") + } + return + } else { + internetDialog = InternetDialog(context, this, internetDialogController, + canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler, + executor) + internetDialog?.show() + } + } + + fun destroyDialog() { + if (DEBUG) { + Log.d(TAG, "destroyDialog") + } + internetDialog = null + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogUtil.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogUtil.java new file mode 100644 index 000000000000..6aaba997faad --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogUtil.java @@ -0,0 +1,14 @@ +package com.android.systemui.qs.tiles.dialog; + +import android.content.Context; +import android.util.FeatureFlagUtils; + +public class InternetDialogUtil { + + public static boolean isProviderModelEnabled(Context context) { + if (context == null) { + return false; + } + return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java index 26781f4ccf09..2133cf63d1c3 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java @@ -29,8 +29,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; +import android.media.MediaCodec; import android.media.MediaCodecInfo; -import android.media.MediaCodecList; import android.media.MediaFormat; import android.media.MediaMuxer; import android.media.MediaRecorder; @@ -187,77 +187,63 @@ public class ScreenMediaRecorder { * @param refreshRate Desired refresh rate * @return array with supported width, height, and refresh rate */ - private int[] getSupportedSize(final int screenWidth, final int screenHeight, int refreshRate) { - double maxScale = 0; - - MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - MediaCodecInfo.VideoCapabilities maxInfo = null; - for (MediaCodecInfo codec : codecList.getCodecInfos()) { - String videoType = MediaFormat.MIMETYPE_VIDEO_AVC; - String[] types = codec.getSupportedTypes(); - for (String t : types) { - if (!t.equalsIgnoreCase(videoType)) { - continue; - } - MediaCodecInfo.CodecCapabilities capabilities = - codec.getCapabilitiesForType(videoType); - if (capabilities != null && capabilities.getVideoCapabilities() != null) { - MediaCodecInfo.VideoCapabilities vc = capabilities.getVideoCapabilities(); - - int width = vc.getSupportedWidths().getUpper(); - int height = vc.getSupportedHeights().getUpper(); - - int screenWidthAligned = screenWidth; - if (screenWidthAligned % vc.getWidthAlignment() != 0) { - screenWidthAligned -= (screenWidthAligned % vc.getWidthAlignment()); - } - int screenHeightAligned = screenHeight; - if (screenHeightAligned % vc.getHeightAlignment() != 0) { - screenHeightAligned -= (screenHeightAligned % vc.getHeightAlignment()); - } - - if (width >= screenWidthAligned && height >= screenHeightAligned - && vc.isSizeSupported(screenWidthAligned, screenHeightAligned)) { - // Desired size is supported, now get the rate - int maxRate = vc.getSupportedFrameRatesFor(screenWidthAligned, - screenHeightAligned).getUpper().intValue(); - - if (maxRate < refreshRate) { - refreshRate = maxRate; - } - Log.d(TAG, "Screen size supported at rate " + refreshRate); - return new int[]{screenWidthAligned, screenHeightAligned, refreshRate}; - } - - // Otherwise, continue searching - double scale = Math.min(((double) width / screenWidth), - ((double) height / screenHeight)); - if (scale > maxScale) { - maxScale = Math.min(1, scale); - maxInfo = vc; - } - } + private int[] getSupportedSize(final int screenWidth, final int screenHeight, int refreshRate) + throws IOException { + String videoType = MediaFormat.MIMETYPE_VIDEO_AVC; + + // Get max size from the decoder, to ensure recordings will be playable on device + MediaCodec decoder = MediaCodec.createDecoderByType(videoType); + MediaCodecInfo.VideoCapabilities vc = decoder.getCodecInfo() + .getCapabilitiesForType(videoType).getVideoCapabilities(); + decoder.release(); + + // Check if we can support screen size as-is + int width = vc.getSupportedWidths().getUpper(); + int height = vc.getSupportedHeights().getUpper(); + + int screenWidthAligned = screenWidth; + if (screenWidthAligned % vc.getWidthAlignment() != 0) { + screenWidthAligned -= (screenWidthAligned % vc.getWidthAlignment()); + } + int screenHeightAligned = screenHeight; + if (screenHeightAligned % vc.getHeightAlignment() != 0) { + screenHeightAligned -= (screenHeightAligned % vc.getHeightAlignment()); + } + + if (width >= screenWidthAligned && height >= screenHeightAligned + && vc.isSizeSupported(screenWidthAligned, screenHeightAligned)) { + // Desired size is supported, now get the rate + int maxRate = vc.getSupportedFrameRatesFor(screenWidthAligned, + screenHeightAligned).getUpper().intValue(); + + if (maxRate < refreshRate) { + refreshRate = maxRate; } + Log.d(TAG, "Screen size supported at rate " + refreshRate); + return new int[]{screenWidthAligned, screenHeightAligned, refreshRate}; } - // Resize for max supported size - int scaledWidth = (int) (screenWidth * maxScale); - int scaledHeight = (int) (screenHeight * maxScale); - if (scaledWidth % maxInfo.getWidthAlignment() != 0) { - scaledWidth -= (scaledWidth % maxInfo.getWidthAlignment()); + // Otherwise, resize for max supported size + double scale = Math.min(((double) width / screenWidth), + ((double) height / screenHeight)); + + int scaledWidth = (int) (screenWidth * scale); + int scaledHeight = (int) (screenHeight * scale); + if (scaledWidth % vc.getWidthAlignment() != 0) { + scaledWidth -= (scaledWidth % vc.getWidthAlignment()); } - if (scaledHeight % maxInfo.getHeightAlignment() != 0) { - scaledHeight -= (scaledHeight % maxInfo.getHeightAlignment()); + if (scaledHeight % vc.getHeightAlignment() != 0) { + scaledHeight -= (scaledHeight % vc.getHeightAlignment()); } // Find max supported rate for size - int maxRate = maxInfo.getSupportedFrameRatesFor(scaledWidth, scaledHeight) + int maxRate = vc.getSupportedFrameRatesFor(scaledWidth, scaledHeight) .getUpper().intValue(); if (maxRate < refreshRate) { refreshRate = maxRate; } - Log.d(TAG, "Resized by " + maxScale + ": " + scaledWidth + ", " + scaledHeight + Log.d(TAG, "Resized by " + scale + ": " + scaledWidth + ", " + scaledHeight + ", " + refreshRate); return new int[]{scaledWidth, scaledHeight, refreshRate}; } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java index 0eaef72ae29b..31d51f1d1a60 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java @@ -154,6 +154,7 @@ public class LongScreenshotActivity extends Activity { @Override public void onStart() { super.onStart(); + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_STARTED); if (mPreview.getDrawable() != null) { // We already have an image, so no need to try to load again. @@ -245,6 +246,8 @@ public class LongScreenshotActivity extends Activity { } private void onCachedImageLoaded(ImageLoader.Result imageResult) { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_CACHED_IMAGE_LOADED); + BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap); mPreview.setImageDrawable(drawable); mPreview.setAlpha(1f); @@ -282,6 +285,8 @@ public class LongScreenshotActivity extends Activity { finish(); } if (isFinishing()) { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_FINISHED); + if (mScrollCaptureResponse != null) { mScrollCaptureResponse.close(); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 16872b08b9c8..8def475c192c 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -33,6 +33,7 @@ import static java.util.Objects.requireNonNull; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.annotation.MainThread; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -261,6 +262,7 @@ public class ScreenshotController { private Bitmap mScreenBitmap; private SaveImageInBackgroundTask mSaveInBgTask; private boolean mScreenshotTakenInPortrait; + private boolean mBlockAttach; private Animator mScreenshotAnimation; private RequestCallback mCurrentRequestCallback; @@ -559,8 +561,8 @@ public class ScreenshotController { mScreenshotView.reset(); } - mScreenshotView.updateOrientation(mWindowManager.getCurrentWindowMetrics() - .getWindowInsets().getDisplayCutout()); + mScreenshotView.updateOrientation( + mWindowManager.getCurrentWindowMetrics().getWindowInsets()); mScreenBitmap = screenshot; @@ -594,9 +596,8 @@ public class ScreenshotController { // Delay scroll capture eval a bit to allow the underlying activity // to set up in the new orientation. mScreenshotHandler.postDelayed(this::requestScrollCapture, 150); - mScreenshotView.updateDisplayCutoutMargins( - mWindowManager.getCurrentWindowMetrics().getWindowInsets() - .getDisplayCutout()); + mScreenshotView.updateInsets( + mWindowManager.getCurrentWindowMetrics().getWindowInsets()); // screenshot animation calculations won't be valid anymore, so just end if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) { mScreenshotAnimation.end(); @@ -660,7 +661,7 @@ public class ScreenshotController { + mLastScrollCaptureResponse.getWindowTitle() + "]"); final ScrollCaptureResponse response = mLastScrollCaptureResponse; - mScreenshotView.showScrollChip(/* onClick */ () -> { + mScreenshotView.showScrollChip(response.getPackageName(), /* onClick */ () -> { DisplayMetrics displayMetrics = new DisplayMetrics(); getDefaultDisplay().getRealMetrics(displayMetrics); Bitmap newScreenshot = captureScreenshot( @@ -732,6 +733,7 @@ public class ScreenshotController { new ViewTreeObserver.OnWindowAttachListener() { @Override public void onWindowAttached() { + mBlockAttach = false; decorView.getViewTreeObserver().removeOnWindowAttachListener(this); action.run(); } @@ -748,14 +750,16 @@ public class ScreenshotController { mWindow.setContentView(contentView); } + @MainThread private void attachWindow() { View decorView = mWindow.getDecorView(); - if (decorView.isAttachedToWindow()) { + if (decorView.isAttachedToWindow() || mBlockAttach) { return; } if (DEBUG_WINDOW) { Log.d(TAG, "attachWindow"); } + mBlockAttach = true; mWindowManager.addView(decorView, mWindowLayoutParams); decorView.requestApplyInsets(); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java index 5cf018813133..169b28c6b373 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java @@ -71,7 +71,19 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum { @UiEvent(doc = "User has shared a long screenshot") SCREENSHOT_LONG_SCREENSHOT_SHARE(689), @UiEvent(doc = "User has sent a long screenshot to the editor") - SCREENSHOT_LONG_SCREENSHOT_EDIT(690); + SCREENSHOT_LONG_SCREENSHOT_EDIT(690), + @UiEvent(doc = "A long screenshot capture has started") + SCREENSHOT_LONG_SCREENSHOT_STARTED(880), + @UiEvent(doc = "The long screenshot capture failed") + SCREENSHOT_LONG_SCREENSHOT_FAILURE(881), + @UiEvent(doc = "The long screenshot capture completed successfully") + SCREENSHOT_LONG_SCREENSHOT_COMPLETED(882), + @UiEvent(doc = "Long screenshot editor activity started") + SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_STARTED(889), + @UiEvent(doc = "Long screenshot editor activity loaded a previously saved screenshot") + SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_CACHED_IMAGE_LOADED(890), + @UiEvent(doc = "Long screenshot editor activity finished") + SCREENSHOT_LONG_SCREENSHOT_ACTIVITY_FINISHED(891); private final int mId; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index e9e62f26a10e..dfb39e300450 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -118,8 +118,8 @@ public class ScreenshotView extends FrameLayout implements private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234; private static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400; private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100; - private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350; - private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183; + private static final long SCREENSHOT_DISMISS_X_DURATION_MS = 350; + private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 350; private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f; private static final float ROUNDED_CORNER_RADIUS = .25f; @@ -242,19 +242,21 @@ public class ScreenshotView extends FrameLayout implements /** * Called to display the scroll action chip when support is detected. * + * @param packageName the owning package of the window to be captured * @param onClick the action to take when the chip is clicked. */ - public void showScrollChip(Runnable onClick) { + public void showScrollChip(String packageName, Runnable onClick) { if (DEBUG_SCROLL) { Log.d(TAG, "Showing Scroll option"); } - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION); + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION, 0, packageName); mScrollChip.setVisibility(VISIBLE); mScrollChip.setOnClickListener((v) -> { if (DEBUG_INPUT) { Log.d(TAG, "scroll chip tapped"); } - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED); + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED, 0, + packageName); onClick.run(); }); } @@ -414,21 +416,30 @@ public class ScreenshotView extends FrameLayout implements mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets)); } - void updateDisplayCutoutMargins(DisplayCutout cutout) { + void updateInsets(WindowInsets insets) { int orientation = mContext.getResources().getConfiguration().orientation; mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT); FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) mScreenshotStatic.getLayoutParams(); + DisplayCutout cutout = insets.getDisplayCutout(); + Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars()); if (cutout == null) { - p.setMargins(0, 0, 0, 0); + p.setMargins(0, 0, 0, navBarInsets.bottom); } else { Insets waterfall = cutout.getWaterfallInsets(); if (mOrientationPortrait) { - p.setMargins(waterfall.left, Math.max(cutout.getSafeInsetTop(), waterfall.top), - waterfall.right, Math.max(cutout.getSafeInsetBottom(), waterfall.bottom)); + p.setMargins( + waterfall.left, + Math.max(cutout.getSafeInsetTop(), waterfall.top), + waterfall.right, + Math.max(cutout.getSafeInsetBottom(), + Math.max(navBarInsets.bottom, waterfall.bottom))); } else { - p.setMargins(Math.max(cutout.getSafeInsetLeft(), waterfall.left), waterfall.top, - Math.max(cutout.getSafeInsetRight(), waterfall.right), waterfall.bottom); + p.setMargins( + Math.max(cutout.getSafeInsetLeft(), waterfall.left), + waterfall.top, + Math.max(cutout.getSafeInsetRight(), waterfall.right), + Math.max(navBarInsets.bottom, waterfall.bottom)); } } mStaticLeftMargin = p.leftMargin; @@ -436,10 +447,10 @@ public class ScreenshotView extends FrameLayout implements mScreenshotStatic.requestLayout(); } - void updateOrientation(DisplayCutout cutout) { + void updateOrientation(WindowInsets insets) { int orientation = mContext.getResources().getConfiguration().orientation; mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT); - updateDisplayCutoutMargins(cutout); + updateInsets(insets); int screenshotFixedSize = mContext.getResources().getDimensionPixelSize(R.dimen.global_screenshot_x_scale); ViewGroup.LayoutParams params = mScreenshotPreview.getLayoutParams(); @@ -978,7 +989,6 @@ public class ScreenshotView extends FrameLayout implements mScrollingScrim.setVisibility(View.GONE); mScrollablePreview.setVisibility(View.GONE); mScreenshotStatic.setTranslationX(0); - mScreenshotPreview.setTranslationY(0); mScreenshotPreview.setContentDescription( mContext.getResources().getString(R.string.screenshot_preview_description)); mScreenshotPreview.setOnClickListener(null); @@ -994,9 +1004,6 @@ public class ScreenshotView extends FrameLayout implements mSmartChips.clear(); mQuickShareChip = null; setAlpha(1); - mDismissButton.setTranslationY(0); - mActionsContainer.setTranslationY(0); - mActionsContainerBackground.setTranslationY(0); mScreenshotSelectorView.stop(); } @@ -1024,22 +1031,19 @@ public class ScreenshotView extends FrameLayout implements setAlpha(1 - animation.getAnimatedFraction()); }); - ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1); - yAnim.setInterpolator(mAccelerateInterpolator); - yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS); - float screenshotStartY = mScreenshotPreview.getTranslationY(); - float dismissStartY = mDismissButton.getTranslationY(); - yAnim.addUpdateListener(animation -> { - float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction()); - mScreenshotPreview.setTranslationY(screenshotStartY + yDelta); - mScreenshotPreviewBorder.setTranslationY(screenshotStartY + yDelta); - mDismissButton.setTranslationY(dismissStartY + yDelta); - mActionsContainer.setTranslationY(yDelta); - mActionsContainerBackground.setTranslationY(yDelta); + ValueAnimator xAnim = ValueAnimator.ofFloat(0, 1); + xAnim.setInterpolator(mAccelerateInterpolator); + xAnim.setDuration(SCREENSHOT_DISMISS_X_DURATION_MS); + float deltaX = mDirectionLTR + ? -1 * (mScreenshotPreviewBorder.getX() + mScreenshotPreviewBorder.getWidth()) + : (mDisplayMetrics.widthPixels - mScreenshotPreviewBorder.getX()); + xAnim.addUpdateListener(animation -> { + float currXDelta = MathUtils.lerp(0, deltaX, animation.getAnimatedFraction()); + mScreenshotStatic.setTranslationX(currXDelta); }); AnimatorSet animSet = new AnimatorSet(); - animSet.play(yAnim).with(alphaAnim); + animSet.play(xAnim).with(alphaAnim); return animSet; } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java index 6dc68746e3ec..ef7355a09fbf 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java @@ -28,6 +28,7 @@ import androidx.concurrent.futures.CallbackToFutureAdapter; import androidx.concurrent.futures.CallbackToFutureAdapter.Completer; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.screenshot.ScrollCaptureClient.CaptureResult; import com.android.systemui.screenshot.ScrollCaptureClient.Session; @@ -61,6 +62,7 @@ public class ScrollCaptureController { private final Context mContext; private final Executor mBgExecutor; private final ImageTileSet mImageTileSet; + private final UiEventLogger mEventLogger; private final ScrollCaptureClient mClient; private Completer<LongScreenshot> mCaptureCompleter; @@ -69,6 +71,7 @@ public class ScrollCaptureController { private Session mSession; private ListenableFuture<CaptureResult> mTileFuture; private ListenableFuture<Void> mEndFuture; + private String mWindowOwner; static class LongScreenshot { private final ImageTileSet mImageTileSet; @@ -135,11 +138,12 @@ public class ScrollCaptureController { @Inject ScrollCaptureController(Context context, @Background Executor bgExecutor, - ScrollCaptureClient client, ImageTileSet imageTileSet) { + ScrollCaptureClient client, ImageTileSet imageTileSet, UiEventLogger logger) { mContext = context; mBgExecutor = bgExecutor; mClient = client; mImageTileSet = imageTileSet; + mEventLogger = logger; } @VisibleForTesting @@ -157,6 +161,7 @@ public class ScrollCaptureController { ListenableFuture<LongScreenshot> run(ScrollCaptureResponse response) { return CallbackToFutureAdapter.getFuture(completer -> { mCaptureCompleter = completer; + mWindowOwner = response.getPackageName(); mBgExecutor.execute(() -> { float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(), SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT); @@ -173,11 +178,13 @@ public class ScrollCaptureController { if (LogConfig.DEBUG_SCROLL) { Log.d(TAG, "got session " + mSession); } + mEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_STARTED, 0, mWindowOwner); requestNextTile(0); } catch (InterruptedException | ExecutionException e) { // Failure to start, propagate to caller Log.e(TAG, "session start failed!"); mCaptureCompleter.setException(e); + mEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_FAILURE, 0, mWindowOwner); } } @@ -297,6 +304,11 @@ public class ScrollCaptureController { if (LogConfig.DEBUG_SCROLL) { Log.d(TAG, "finishCapture()"); } + if (mImageTileSet.getHeight() > 0) { + mEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_COMPLETED, 0, mWindowOwner); + } else { + mEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_FAILURE, 0, mWindowOwner); + } mEndFuture = mSession.end(); mEndFuture.addListener(() -> { if (LogConfig.DEBUG_SCROLL) { diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt new file mode 100644 index 000000000000..c50365f1bf38 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt @@ -0,0 +1,74 @@ +package com.android.systemui.sensorprivacy + +import android.content.Context +import android.content.DialogInterface +import android.content.res.Resources +import android.text.Html +import android.view.LayoutInflater +import android.view.View +import android.view.WindowManager +import android.widget.ImageView +import com.android.internal.widget.DialogTitle +import com.android.systemui.R +import com.android.systemui.statusbar.phone.SystemUIDialog + +class SensorUseDialog( + context: Context, + val sensor: Int, + val clickListener: DialogInterface.OnClickListener +) : SystemUIDialog(context) { + + // TODO move to onCreate (b/200815309) + init { + window!!.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) + window!!.addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) + + val layoutInflater = LayoutInflater.from(context) + val customTitleView = layoutInflater.inflate(R.layout.sensor_use_started_title, null) + customTitleView.requireViewById<DialogTitle>(R.id.sensor_use_started_title_message) + .setText(when (sensor) { + SensorUseStartedActivity.MICROPHONE -> + R.string.sensor_privacy_start_use_mic_dialog_title + SensorUseStartedActivity.CAMERA -> + R.string.sensor_privacy_start_use_camera_dialog_title + SensorUseStartedActivity.ALL_SENSORS -> + R.string.sensor_privacy_start_use_mic_camera_dialog_title + else -> Resources.ID_NULL + }) + customTitleView.requireViewById<ImageView>(R.id.sensor_use_microphone_icon).visibility = + if (sensor == SensorUseStartedActivity.MICROPHONE || + sensor == SensorUseStartedActivity.ALL_SENSORS) { + View.VISIBLE + } else { + View.GONE + } + customTitleView.requireViewById<ImageView>(R.id.sensor_use_camera_icon).visibility = + if (sensor == SensorUseStartedActivity.CAMERA || + sensor == SensorUseStartedActivity.ALL_SENSORS) { + View.VISIBLE + } else { + View.GONE + } + + setCustomTitle(customTitleView) + setMessage(Html.fromHtml(context.getString(when (sensor) { + SensorUseStartedActivity.MICROPHONE -> + R.string.sensor_privacy_start_use_mic_dialog_content + SensorUseStartedActivity.CAMERA -> + R.string.sensor_privacy_start_use_camera_dialog_content + SensorUseStartedActivity.ALL_SENSORS -> + R.string.sensor_privacy_start_use_mic_camera_dialog_content + else -> Resources.ID_NULL + }), 0)) + + setButton(BUTTON_POSITIVE, + context.getString(com.android.internal.R.string + .sensor_privacy_start_use_dialog_turn_on_button), clickListener) + setButton(BUTTON_NEGATIVE, + context.getString(com.android.internal.R.string + .cancel), clickListener) + + setCancelable(false) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt index f0fb5ebf9e1d..b0071d92481d 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt @@ -16,33 +16,28 @@ package com.android.systemui.sensorprivacy +import android.app.Activity +import android.app.AlertDialog import android.content.DialogInterface +import android.content.DialogInterface.BUTTON_NEGATIVE +import android.content.DialogInterface.BUTTON_POSITIVE import android.content.Intent import android.content.Intent.EXTRA_PACKAGE_NAME -import android.content.pm.PackageManager -import android.content.res.Resources import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS import android.hardware.SensorPrivacyManager.EXTRA_SENSOR import android.hardware.SensorPrivacyManager.Sources.DIALOG import android.os.Bundle import android.os.Handler -import android.text.Html -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.ImageView -import com.android.internal.app.AlertActivity -import com.android.internal.widget.DialogTitle -import com.android.systemui.R +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE +import com.android.internal.util.FrameworkStatsLog.write import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.phone.KeyguardDismissUtil import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController import com.android.systemui.statusbar.policy.KeyguardStateController import javax.inject.Inject -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL -import com.android.internal.util.FrameworkStatsLog.write /** * Dialog to be shown on top of apps that are attempting to use a sensor (e.g. microphone) which is @@ -55,7 +50,7 @@ class SensorUseStartedActivity @Inject constructor( private val keyguardStateController: KeyguardStateController, private val keyguardDismissUtil: KeyguardDismissUtil, @Background private val bgHandler: Handler -) : AlertActivity(), DialogInterface.OnClickListener { +) : Activity(), DialogInterface.OnClickListener { companion object { private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName @@ -63,9 +58,9 @@ class SensorUseStartedActivity @Inject constructor( private const val SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS = 2000L private const val UNLOCK_DELAY_MILLIS = 200L - private const val CAMERA = SensorPrivacyManager.Sensors.CAMERA - private const val MICROPHONE = SensorPrivacyManager.Sensors.MICROPHONE - private const val ALL_SENSORS = Integer.MAX_VALUE + internal const val CAMERA = SensorPrivacyManager.Sensors.CAMERA + internal const val MICROPHONE = SensorPrivacyManager.Sensors.MICROPHONE + internal const val ALL_SENSORS = Integer.MAX_VALUE } private var sensor = -1 @@ -74,6 +69,8 @@ class SensorUseStartedActivity @Inject constructor( private lateinit var sensorPrivacyListener: IndividualSensorPrivacyController.Callback + private var mDialog: AlertDialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -91,7 +88,7 @@ class SensorUseStartedActivity @Inject constructor( IndividualSensorPrivacyController.Callback { _, _ -> if (!sensorPrivacyController.isSensorBlocked(MICROPHONE) && !sensorPrivacyController.isSensorBlocked(CAMERA)) { - dismiss() + finish() } } @@ -109,71 +106,22 @@ class SensorUseStartedActivity @Inject constructor( } } sensorPrivacyListener = - IndividualSensorPrivacyController.Callback { - whichSensor: Int, isBlocked: Boolean -> + IndividualSensorPrivacyController.Callback { whichSensor: Int, + isBlocked: Boolean -> if (whichSensor == sensor && !isBlocked) { - dismiss() + finish() } } sensorPrivacyController.addCallback(sensorPrivacyListener) - sensorPrivacyController.addCallback { _, isBlocked -> - if (!isBlocked) { - dismiss() - } - } - } - - mAlertParams.apply { - try { - mCustomTitleView = mInflater.inflate(R.layout.sensor_use_started_title, null) - mCustomTitleView.findViewById<DialogTitle>(R.id.sensor_use_started_title_message)!! - .setText(when (sensor) { - MICROPHONE -> - R.string.sensor_privacy_start_use_mic_dialog_title - CAMERA -> - R.string.sensor_privacy_start_use_camera_dialog_title - ALL_SENSORS -> - R.string.sensor_privacy_start_use_mic_camera_dialog_title - else -> Resources.ID_NULL - }) - - mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_microphone_icon)!! - .visibility = if (sensor == MICROPHONE || sensor == ALL_SENSORS) { - VISIBLE - } else { - GONE - } - mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_camera_icon)!! - .visibility = if (sensor == CAMERA || sensor == ALL_SENSORS) { - VISIBLE - } else { - GONE - } - - mMessage = Html.fromHtml(getString(when (sensor) { - MICROPHONE -> - R.string.sensor_privacy_start_use_mic_dialog_content - CAMERA -> - R.string.sensor_privacy_start_use_camera_dialog_content - ALL_SENSORS -> - R.string.sensor_privacy_start_use_mic_camera_dialog_content - else -> Resources.ID_NULL - }, packageManager.getApplicationInfo(sensorUsePackageName, 0) - .loadLabel(packageManager)), 0) - } catch (e: PackageManager.NameNotFoundException) { + if (!sensorPrivacyController.isSensorBlocked(sensor)) { finish() return } - - mPositiveButtonText = getString( - com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button) - mNegativeButtonText = getString(android.R.string.cancel) - mPositiveButtonListener = this@SensorUseStartedActivity - mNegativeButtonListener = this@SensorUseStartedActivity } - setupAlert() + mDialog = SensorUseDialog(this, sensor, this) + mDialog!!.show() } override fun onStart() { @@ -212,7 +160,7 @@ class SensorUseStartedActivity @Inject constructor( } } - dismiss() + finish() } override fun onStop() { @@ -229,6 +177,7 @@ class SensorUseStartedActivity @Inject constructor( override fun onDestroy() { super.onDestroy() + mDialog?.dismiss() sensorPrivacyController.removeCallback(sensorPrivacyListener) } @@ -263,4 +212,4 @@ class SensorUseStartedActivity @Inject constructor( .suppressSensorPrivacyReminders(sensor, suppressed) } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java index 8cd3632b65ba..cc5cf4b63f99 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java @@ -24,6 +24,7 @@ import android.hardware.SensorPrivacyManager; import android.os.Bundle; import android.util.Log; import android.view.View; +import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; @@ -57,6 +58,8 @@ public class TvUnblockSensorActivity extends TvBottomSheetActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 8e52b0da54ef..50911d162113 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -290,8 +290,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< default void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, - boolean requireConfirmation, int userId, String opPackageName, - long operationId, @BiometricMultiSensorMode int multiSensorConfig) { + boolean requireConfirmation, int userId, long operationId, String opPackageName, + long requestId, @BiometricMultiSensorMode int multiSensorConfig) { } /** @see IStatusBar#onBiometricAuthenticated() */ @@ -843,7 +843,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< @Override public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, - int userId, String opPackageName, long operationId, + int userId, long operationId, String opPackageName, long requestId, @BiometricMultiSensorMode int multiSensorConfig) { synchronized (mLock) { SomeArgs args = SomeArgs.obtain(); @@ -855,6 +855,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< args.argi1 = userId; args.arg6 = opPackageName; args.arg7 = operationId; + args.arg8 = requestId; args.argi2 = multiSensorConfig; mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args) .sendToTarget(); @@ -1312,8 +1313,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< (boolean) someArgs.arg4 /* credentialAllowed */, (boolean) someArgs.arg5 /* requireConfirmation */, someArgs.argi1 /* userId */, - (String) someArgs.arg6 /* opPackageName */, (long) someArgs.arg7 /* operationId */, + (String) someArgs.arg6 /* opPackageName */, + (long) someArgs.arg8 /* requestId */, someArgs.argi2 /* multiSensorConfig */); } someArgs.recycle(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 1c933505172f..8a397199dc84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -66,6 +66,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.ViewClippingUtil; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.settingslib.Utils; import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; @@ -334,7 +335,7 @@ public class KeyguardIndicationController { info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser()); } } - if (info != null) { + if (!TextUtils.isEmpty(info)) { mRotateTextViewController.updateIndication( INDICATION_TYPE_OWNER_INFO, new KeyguardIndication.Builder() @@ -432,7 +433,7 @@ public class KeyguardIndicationController { } private void updateResting() { - if (mRestingIndication != null + if (!TextUtils.isEmpty(mRestingIndication) && !mRotateTextViewController.hasIndications()) { mRotateTextViewController.updateIndication( INDICATION_TYPE_RESTING, @@ -455,7 +456,8 @@ public class KeyguardIndicationController { new KeyguardIndication.Builder() .setMessage(mContext.getResources().getString( com.android.internal.R.string.global_action_logout)) - .setTextColor(mInitialTextColorState) + .setTextColor(Utils.getColorAttr( + mContext, com.android.internal.R.attr.textColorOnAccent)) .setBackground(mContext.getDrawable( com.android.systemui.R.drawable.logout_button_background)) .setClickListener((view) -> { @@ -723,15 +725,13 @@ public class KeyguardIndicationController { } protected String computePowerIndication() { - if (mPowerCharged) { - return mContext.getResources().getString(R.string.keyguard_charged); - } - int chargingId; - String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); if (mBatteryOverheated) { chargingId = R.string.keyguard_plugged_in_charging_limited; + String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); return mContext.getResources().getString(chargingId, percentage); + } else if (mPowerCharged) { + return mContext.getResources().getString(R.string.keyguard_charged); } final boolean hasChargingTime = mChargingTimeRemaining > 0; @@ -759,6 +759,7 @@ public class KeyguardIndicationController { : R.string.keyguard_plugged_in_wireless; } + String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); if (hasChargingTime) { String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes( mContext, mChargingTimeRemaining); @@ -799,7 +800,9 @@ public class KeyguardIndicationController { * Show message on the keyguard for how the user can unlock/enter their device. */ public void showActionToUnlock() { - if (mDozing) { + if (mDozing + && !mKeyguardUpdateMonitor.getUserCanSkipBouncer( + KeyguardUpdateMonitor.getCurrentUser())) { return; } @@ -810,13 +813,13 @@ public class KeyguardIndicationController { String message = mContext.getString(R.string.keyguard_retry); mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState); } - } else if (mKeyguardUpdateMonitor.isScreenOn()) { + } else { showTransientIndication(mContext.getString(R.string.keyguard_unlock), false /* isError */, true /* hideOnScreenOff */); } } - 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 @@ -828,6 +831,11 @@ public class KeyguardIndicationController { } 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) { @@ -908,7 +916,7 @@ public class KeyguardIndicationController { } else if (mKeyguardUpdateMonitor.isScreenOn()) { if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) { - showTryFingerprintMsg(); + showTryFingerprintMsg(helpString); return; } showTransientIndication(helpString, false /* isError */, showActionToUnlock); @@ -928,7 +936,7 @@ public class KeyguardIndicationController { && shouldSuppressFaceMsgAndShowTryFingerprintMsg() && !mStatusBarKeyguardViewManager.isBouncerShowing() && mKeyguardUpdateMonitor.isScreenOn()) { - showTryFingerprintMsg(); + showTryFingerprintMsg(errString); return; } if (msgId == FaceManager.FACE_ERROR_TIMEOUT) { @@ -937,7 +945,7 @@ public class KeyguardIndicationController { 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 538db6168408..21ed9da896a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt @@ -149,7 +149,10 @@ class PowerButtonReveal( */ 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 @@ -161,7 +164,7 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, field = value revealEffect.setRevealAmountOnScrim(value, this) - revealAmountListener.accept(value) + updateScrimOpaque() invalidate() } } @@ -201,6 +204,31 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, } /** + * 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 b8334272c157..2a8771e96e7b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -78,7 +78,8 @@ class NotificationShadeDepthController @Inject constructor( private var keyguardAnimator: Animator? = null private var notificationAnimator: Animator? = null private var updateScheduled: Boolean = false - private var shadeExpansion = 0f + @VisibleForTesting + var shadeExpansion = 0f private var isClosed: Boolean = true private var isOpen: Boolean = false private var isBlurred: Boolean = false @@ -92,6 +93,9 @@ class NotificationShadeDepthController @Inject constructor( // Only for dumpsys private var lastAppliedBlur = 0 + // Shade expansion offset that happens when pulling down on a HUN. + var panelPullDownMinFraction = 0f + var shadeAnimation = DepthAnimation() @VisibleForTesting @@ -181,7 +185,8 @@ class NotificationShadeDepthController @Inject constructor( if (shouldApplyShadeBlur()) shadeExpansion else 0f, false)) var combinedBlur = (expansionRadius * INTERACTION_BLUR_FRACTION + animationRadius * ANIMATION_BLUR_FRACTION) - val qsExpandedRatio = qsPanelExpansion * shadeExpansion + val qsExpandedRatio = Interpolators.getNotificationScrimAlpha(qsPanelExpansion, + false /* notification */) * shadeExpansion combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio)) combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress)) var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius) @@ -311,8 +316,10 @@ class NotificationShadeDepthController @Inject constructor( /** * Update blurs when pulling down the shade */ - override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) { + override fun onPanelExpansionChanged(rawExpansion: Float, tracking: Boolean) { val timestamp = SystemClock.elapsedRealtimeNanos() + val expansion = MathUtils.saturate( + (rawExpansion - panelPullDownMinFraction) / (1f - panelPullDownMinFraction)) if (shadeExpansion == expansion && prevTracking == tracking) { prevTimestamp = timestamp diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index f0d779ce1e0f..6ea79af8b9ad 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 @@ public interface NotificationShadeWindowController extends RemoteInputController 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/charging/ChargingRippleView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt index 4a467ce3c987..d01fc93ee84c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt @@ -104,7 +104,7 @@ class ChargingRippleView(context: Context?, attrs: AttributeSet?) : View(context // the active effect area. Values here should be kept in sync with the // animation implementation in the ripple shader. val maskRadius = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) * - (1 - rippleShader.progress)) * radius * 1.5f + (1 - rippleShader.progress)) * radius * 2 canvas?.drawCircle(origin.x, origin.y, maskRadius, ripplePaint) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt index 71546ae07ffc..0773460ecf67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt @@ -24,7 +24,6 @@ import android.app.smartspace.SmartspaceTarget import android.content.ContentResolver import android.content.Context import android.content.Intent -import android.content.pm.UserInfo import android.database.ContentObserver import android.net.Uri import android.os.Handler @@ -45,6 +44,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.util.concurrency.Execution import com.android.systemui.util.settings.SecureSettings import java.lang.RuntimeException @@ -67,6 +67,7 @@ class LockscreenSmartspaceController @Inject constructor( private val contentResolver: ContentResolver, private val configurationController: ConfigurationController, private val statusBarStateController: StatusBarStateController, + private val deviceProvisionedController: DeviceProvisionedController, private val execution: Execution, @Main private val uiExecutor: Executor, @Main private val handler: Handler, @@ -83,6 +84,55 @@ class LockscreenSmartspaceController @Inject constructor( private var showSensitiveContentForManagedUser = false private var managedUserHandle: UserHandle? = null + private val deviceProvisionedListener = + object : DeviceProvisionedController.DeviceProvisionedListener { + override fun onDeviceProvisionedChanged() { + connectSession() + } + + override fun onUserSetupChanged() { + connectSession() + } + } + + private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> + execution.assertIsMainThread() + val filteredTargets = targets.filter(::filterSmartspaceTarget) + plugin?.onTargetsAvailable(filteredTargets) + } + + private val userTrackerCallback = object : UserTracker.Callback { + override fun onUserChanged(newUser: Int, userContext: Context) { + execution.assertIsMainThread() + reloadSmartspace() + } + } + + private val settingsObserver = object : ContentObserver(handler) { + override fun onChange(selfChange: Boolean, uri: Uri?) { + execution.assertIsMainThread() + reloadSmartspace() + } + } + + private val configChangeListener = object : ConfigurationController.ConfigurationListener { + override fun onThemeChanged() { + execution.assertIsMainThread() + updateTextColorFromWallpaper() + } + } + + private val statusBarStateListener = object : StatusBarStateController.StateListener { + override fun onDozeAmountChanged(linear: Float, eased: Float) { + execution.assertIsMainThread() + smartspaceView.setDozeAmount(eased) + } + } + + init { + deviceProvisionedController.addCallback(deviceProvisionedListener) + } + fun isEnabled(): Boolean { execution.assertIsMainThread() @@ -141,13 +191,23 @@ class LockscreenSmartspaceController @Inject constructor( } private fun connectSession() { - if (plugin == null || session != null) { + if (plugin == null || session != null || !this::smartspaceView.isInitialized) { return } - val session = smartspaceManager.createSmartspaceSession( + + // Only connect after the device is fully provisioned to avoid connection caching + // issues + if (!deviceProvisionedController.isDeviceProvisioned() || + !deviceProvisionedController.isCurrentUserSetup()) { + return + } + + val newSession = smartspaceManager.createSmartspaceSession( SmartspaceConfig.Builder(context, "lockscreen").build()) - session.addOnTargetsAvailableListener(uiExecutor, sessionListener) + newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener) + this.session = newSession + deviceProvisionedController.removeCallback(deviceProvisionedListener) userTracker.addCallback(userTrackerCallback, uiExecutor) contentResolver.registerContentObserver( secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), @@ -158,8 +218,6 @@ class LockscreenSmartspaceController @Inject constructor( configurationController.addCallback(configChangeListener) statusBarStateController.addCallback(statusBarStateListener) - this.session = session - reloadSmartspace() } @@ -198,43 +256,6 @@ class LockscreenSmartspaceController @Inject constructor( plugin?.unregisterListener(listener) } - private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> - execution.assertIsMainThread() - val filteredTargets = targets.filter(::filterSmartspaceTarget) - plugin?.onTargetsAvailable(filteredTargets) - } - - private val userTrackerCallback = object : UserTracker.Callback { - override fun onUserChanged(newUser: Int, userContext: Context) { - execution.assertIsMainThread() - reloadSmartspace() - } - - override fun onProfilesChanged(profiles: List<UserInfo>) { - } - } - - private val settingsObserver = object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - execution.assertIsMainThread() - reloadSmartspace() - } - } - - private val configChangeListener = object : ConfigurationController.ConfigurationListener { - override fun onThemeChanged() { - execution.assertIsMainThread() - updateTextColorFromWallpaper() - } - } - - private val statusBarStateListener = object : StatusBarStateController.StateListener { - override fun onDozeAmountChanged(linear: Float, eased: Float) { - execution.assertIsMainThread() - smartspaceView.setDozeAmount(eased) - } - } - private fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean { return when (t.userHandle) { userTracker.userHandle -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java index dba3401cc28e..9c755e970a0f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java @@ -85,23 +85,26 @@ public abstract class StackScrollerDecorView extends ExpandableView { } /** - * Set the content of this view to be visible in an animated way. - * - * @param contentVisible True if the content should be visible or false if it should be hidden. + * @param visible True if we should animate contents visible */ - public void setContentVisible(boolean contentVisible) { - setContentVisible(contentVisible, true /* animate */); + public void setContentVisible(boolean visible) { + setContentVisible(visible, true /* animate */, null /* runAfter */); } + /** - * Set the content of this view to be visible. - * @param contentVisible True if the content should be visible or false if it should be hidden. - * @param animate Should an animation be performed. + * @param visible True if the contents should be visible + * @param animate True if we should fade to new visibility + * @param runAfter Runnable to run after visibility updates */ - private void setContentVisible(boolean contentVisible, boolean animate) { - if (mContentVisible != contentVisible) { + public void setContentVisible(boolean visible, boolean animate, Runnable runAfter) { + if (mContentVisible != visible) { mContentAnimating = animate; - mContentVisible = contentVisible; - setViewVisible(mContent, contentVisible, animate, mContentVisibilityEndRunnable); + mContentVisible = visible; + Runnable endRunnable = runAfter == null ? mContentVisibilityEndRunnable : () -> { + mContentVisibilityEndRunnable.run(); + runAfter.run(); + }; + setViewVisible(mContent, visible, animate, endRunnable); } if (!mContentAnimating) { @@ -113,6 +116,10 @@ public abstract class StackScrollerDecorView extends ExpandableView { return mContentVisible; } + public void setVisible(boolean nowVisible, boolean animate) { + setVisible(nowVisible, animate, null); + } + /** * Make this view visible. If {@code false} is passed, the view will fade out it's content * and set the view Visibility to GONE. If only the content should be changed @@ -121,7 +128,7 @@ public abstract class StackScrollerDecorView extends ExpandableView { * @param nowVisible should the view be visible * @param animate should the change be animated. */ - public void setVisible(boolean nowVisible, boolean animate) { + public void setVisible(boolean nowVisible, boolean animate, Runnable runAfter) { if (mIsVisible != nowVisible) { mIsVisible = nowVisible; if (animate) { @@ -132,10 +139,10 @@ public abstract class StackScrollerDecorView extends ExpandableView { } else { setWillBeGone(true); } - setContentVisible(nowVisible, true /* animate */); + setContentVisible(nowVisible, true /* animate */, runAfter); } else { setVisibility(nowVisible ? VISIBLE : GONE); - setContentVisible(nowVisible, false /* animate */); + setContentVisible(nowVisible, false /* animate */, runAfter); setWillBeGone(false); notifyHeightChanged(false /* needsAnimation */); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index 23aefd9bfd8e..594afceab63a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -46,6 +46,7 @@ public class NotificationRoundnessManager { private Runnable mRoundingChangedCallback; private ExpandableNotificationRow mTrackedHeadsUp; private float mAppearFraction; + private boolean mIsDismissAllInProgress; private ExpandableView mSwipedView = null; private ExpandableView mViewBeforeSwipedView = null; @@ -162,6 +163,10 @@ public class NotificationRoundnessManager { } } + void setDismissAllInProgress(boolean isClearingAll) { + mIsDismissAllInProgress = isClearingAll; + } + private float getRoundness(ExpandableView view, boolean top) { if (view == null) { return 0f; @@ -171,6 +176,11 @@ public class NotificationRoundnessManager { || view == mViewAfterSwipedView) { return 1f; } + if (view instanceof ExpandableNotificationRow + && ((ExpandableNotificationRow) view).canViewBeDismissed() + && mIsDismissAllInProgress) { + return 1.0f; + } if ((view.isPinned() || (view.isHeadsUpAnimatingAway()) && !mExpanded)) { return 1.0f; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 0660daab3720..733c0a92ec09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -144,6 +144,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private static final boolean DEBUG_REMOVE_ANIMATION = SystemProperties.getBoolean( "persist.debug.nssl.dismiss", false /* default */); + // Delay in milli-seconds before shade closes for clear all. + private final int DELAY_BEFORE_SHADE_CLOSE = 200; + private boolean mShadeNeedsToClose = false; + private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f; private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f; private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f; @@ -256,10 +260,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private boolean mExpandedInThisMotion; private boolean mShouldShowShelfOnly; protected boolean mScrollingEnabled; + private boolean mIsCurrentUserSetup; protected FooterView mFooterView; protected EmptyShadeView mEmptyShadeView; private boolean mDismissAllInProgress; - private boolean mFadeNotificationsOnDismiss; private FooterDismissListener mFooterDismissListener; private boolean mFlingAfterUpEvent; @@ -612,6 +616,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll); mGroupMembershipManager = groupMembershipManager; mGroupExpansionManager = groupExpansionManager; + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) { @@ -683,6 +688,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mController.hasActiveClearableNotifications(ROWS_ALL); RemoteInputController remoteInputController = mRemoteInputManager.getController(); boolean showFooterView = (showDismissView || getVisibleNotificationCount() > 0) + && mIsCurrentUserSetup // see: b/193149550 && mStatusBarState != StatusBarState.KEYGUARD && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() && (remoteInputController == null || !remoteInputController.isRemoteInputActive()); @@ -1192,7 +1198,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void clampScrollPosition() { int scrollRange = getScrollRange(); - if (scrollRange < mOwnScrollY) { + if (scrollRange < mOwnScrollY && !mAmbientState.isDismissAllInProgress()) { boolean animateStackY = false; if (scrollRange < getScrollAmountToScrollBoundary() && mAnimateStackYForContentHeightChange) { @@ -1708,6 +1714,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) { + if (child instanceof SectionHeaderView) { + ((StackScrollerDecorView) child).setContentVisible( + false /* visible */, true /* animate */, endRunnable); + return; + } mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration, true /* isDismissAll */); } @@ -4050,6 +4061,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable runAnimationFinishedRunnables(); clearTransient(); clearHeadsUpDisappearRunning(); + + if (mAmbientState.isDismissAllInProgress()) { + setDismissAllInProgress(false); + + if (mShadeNeedsToClose) { + mShadeNeedsToClose = false; + postDelayed( + () -> { + mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); + }, + DELAY_BEFORE_SHADE_CLOSE /* delayMillis */); + } + } } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @@ -4407,6 +4431,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable public void setDismissAllInProgress(boolean dismissAllInProgress) { mDismissAllInProgress = dismissAllInProgress; mAmbientState.setDismissAllInProgress(dismissAllInProgress); + mController.getNoticationRoundessManager().setDismissAllInProgress(dismissAllInProgress); handleDismissAllClipping(); } @@ -4947,129 +4972,137 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mHeadsUpAppearanceController = headsUpAppearanceController; } - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - @VisibleForTesting - void clearNotifications(@SelectedRows int selection, boolean closeShade) { - // animate-swipe all dismissable notifications, then animate the shade closed - int numChildren = getChildCount(); + private boolean isVisible(View child) { + boolean hasClipBounds = child.getClipBounds(mTmpRect); + return child.getVisibility() == View.VISIBLE + && (!hasClipBounds || mTmpRect.height() > 0); + } - final ArrayList<View> viewsToHide = new ArrayList<>(numChildren); - final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren); - for (int i = 0; i < numChildren; i++) { - final View child = getChildAt(i); - if (child instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) child; - boolean parentVisible = false; - boolean hasClipBounds = child.getClipBounds(mTmpRect); - if (includeChildInDismissAll(row, selection)) { - viewsToRemove.add(row); - if (child.getVisibility() == View.VISIBLE - && (!hasClipBounds || mTmpRect.height() > 0)) { - viewsToHide.add(child); - parentVisible = true; - } - } else if (child.getVisibility() == View.VISIBLE - && (!hasClipBounds || mTmpRect.height() > 0)) { - parentVisible = true; - } - List<ExpandableNotificationRow> children = row.getAttachedChildren(); - if (children != null) { - for (ExpandableNotificationRow childRow : children) { - if (includeChildInDismissAll(row, selection)) { - viewsToRemove.add(childRow); - if (parentVisible && row.areChildrenExpanded()) { - hasClipBounds = childRow.getClipBounds(mTmpRect); - if (childRow.getVisibility() == View.VISIBLE - && (!hasClipBounds || mTmpRect.height() > 0)) { - viewsToHide.add(childRow); - } - } - } - } - } + private boolean shouldHideParent(View view, @SelectedRows int selection) { + final boolean silentSectionWillBeGone = + !mController.hasNotifications(ROWS_GENTLE, false /* clearable */); + + // The only SectionHeaderView we have is the silent section header. + if (view instanceof SectionHeaderView && silentSectionWillBeGone) { + return true; + } + if (view instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) view; + if (isVisible(row) && includeChildInDismissAll(row, selection)) { + return true; } } + return false; + } - if (mDismissListener != null) { - mDismissListener.onDismiss(selection); - } + private boolean isChildrenVisible(ExpandableNotificationRow parent) { + List<ExpandableNotificationRow> children = parent.getAttachedChildren(); + return isVisible(parent) + && children != null + && parent.areChildrenExpanded(); + } + + // Similar to #getRowsToDismissInBackend, but filters for visible views. + private ArrayList<View> getVisibleViewsToAnimateAway(@SelectedRows int selection) { + final int viewCount = getChildCount(); + final ArrayList<View> viewsToHide = new ArrayList<>(viewCount); - if (viewsToRemove.isEmpty()) { - if (closeShade && mShadeController != null) { - mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); + for (int i = 0; i < viewCount; i++) { + final View view = getChildAt(i); + + if (shouldHideParent(view, selection)) { + viewsToHide.add(view); } - return; - } + if (view instanceof ExpandableNotificationRow) { + ExpandableNotificationRow parent = (ExpandableNotificationRow) view; - performDismissAllAnimations( - viewsToHide, - closeShade, - () -> onDismissAllAnimationsEnd(viewsToRemove, selection)); + if (isChildrenVisible(parent)) { + for (ExpandableNotificationRow child : parent.getAttachedChildren()) { + if (isVisible(child) && includeChildInDismissAll(child, selection)) { + viewsToHide.add(child); + } + } + } + } + } + return viewsToHide; } - private boolean includeChildInDismissAll( - ExpandableNotificationRow row, + private ArrayList<ExpandableNotificationRow> getRowsToDismissInBackend( @SelectedRows int selection) { - return canChildBeDismissed(row) && matchesSelection(row, selection); + final int childCount = getChildCount(); + final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(childCount); + + for (int i = 0; i < childCount; i++) { + final View view = getChildAt(i); + if (!(view instanceof ExpandableNotificationRow)) { + continue; + } + ExpandableNotificationRow parent = (ExpandableNotificationRow) view; + if (includeChildInDismissAll(parent, selection)) { + viewsToRemove.add(parent); + } + List<ExpandableNotificationRow> children = parent.getAttachedChildren(); + if (isVisible(parent) && children != null) { + for (ExpandableNotificationRow child : children) { + if (includeChildInDismissAll(parent, selection)) { + viewsToRemove.add(child); + } + } + } + } + return viewsToRemove; } /** - * Given a list of rows, animates them away in a staggered fashion as if they were dismissed. - * Doesn't actually dismiss them, though -- that must be done in the onAnimationComplete - * handler. - * - * @param hideAnimatedList List of rows to animated away. Should only be views that are - * currently visible, or else the stagger will look funky. - * @param closeShade Whether to close the shade after the stagger animation completes. - * @param onAnimationComplete Called after the entire animation completes (including the shade - * closing if appropriate). The rows must be dismissed for real here. + * Collects a list of visible rows, and animates them away in a staggered fashion as if they + * were dismissed. Notifications are dismissed in the backend via onDismissAllAnimationsEnd. */ @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void performDismissAllAnimations( - final ArrayList<View> hideAnimatedList, - final boolean closeShade, - final Runnable onAnimationComplete) { - - final Runnable onSlideAwayAnimationComplete = () -> { - if (closeShade) { - mShadeController.addPostCollapseAction(() -> { - setDismissAllInProgress(false); - onAnimationComplete.run(); - }); - mShadeController.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_NONE); - } else { - setDismissAllInProgress(false); - onAnimationComplete.run(); - } + @VisibleForTesting + void clearNotifications(@SelectedRows int selection, boolean closeShade) { + // Animate-swipe all dismissable notifications, then animate the shade closed + final ArrayList<View> viewsToAnimateAway = getVisibleViewsToAnimateAway(selection); + final ArrayList<ExpandableNotificationRow> rowsToDismissInBackend = + getRowsToDismissInBackend(selection); + if (mDismissListener != null) { + mDismissListener.onDismiss(selection); + } + final Runnable dismissInBackend = () -> { + onDismissAllAnimationsEnd(rowsToDismissInBackend, selection); }; - - if (hideAnimatedList.isEmpty()) { - onSlideAwayAnimationComplete.run(); + if (viewsToAnimateAway.isEmpty()) { + dismissInBackend.run(); return; } - - // let's disable our normal animations + // Disable normal animations setDismissAllInProgress(true); + mShadeNeedsToClose = closeShade; // Decrease the delay for every row we animate to give the sense of // accelerating the swipes - int rowDelayDecrement = 10; - int currentDelay = 140; - int totalDelay = 180; - int numItems = hideAnimatedList.size(); + final int rowDelayDecrement = 5; + int currentDelay = 60; + int totalDelay = 0; + final int numItems = viewsToAnimateAway.size(); for (int i = numItems - 1; i >= 0; i--) { - View view = hideAnimatedList.get(i); + View view = viewsToAnimateAway.get(i); Runnable endRunnable = null; if (i == 0) { - endRunnable = onSlideAwayAnimationComplete; + endRunnable = dismissInBackend; } dismissViewAnimated(view, endRunnable, totalDelay, ANIMATION_DURATION_SWIPE); - currentDelay = Math.max(50, currentDelay - rowDelayDecrement); + currentDelay = Math.max(30, currentDelay - rowDelayDecrement); totalDelay += currentDelay; } } + private boolean includeChildInDismissAll( + ExpandableNotificationRow row, + @SelectedRows int selection) { + return canChildBeDismissed(row) && matchesSelection(row, selection); + } + public void setNotificationActivityStarter( NotificationActivityStarter notificationActivityStarter) { mNotificationActivityStarter = notificationActivityStarter; @@ -5085,6 +5118,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mFooterDismissListener.onDismiss(); } clearNotifications(ROWS_ALL, true /* closeShade */); + footerView.setSecondaryVisible(false /* visible */, true /* animate */); }); footerView.setManageButtonClickListener(v -> { mNotificationActivityStarter.startHistoryIntent(v, mFooterView.isHistoryShown()); @@ -5567,6 +5601,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** + * Sets whether the current user is set up, which is required to show the footer (b/193149550) + */ + public void setCurrentUserSetup(boolean isCurrentUserSetup) { + if (mIsCurrentUserSetup != isCurrentUserSetup) { + mIsCurrentUserSetup = isCurrentUserSetup; + updateFooter(); + } + } + + /** * A listener that is notified when the empty space below the notifications is clicked on */ @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 9e4adce47e0c..1e92ca9862f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -117,6 +117,8 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; @@ -144,6 +146,7 @@ public class NotificationStackScrollLayoutController { private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationRoundnessManager mNotificationRoundnessManager; private final TunerService mTunerService; + private final DeviceProvisionedController mDeviceProvisionedController; private final DynamicPrivacyController mDynamicPrivacyController; private final ConfigurationController mConfigurationController; private final ZenModeController mZenModeController; @@ -171,6 +174,7 @@ public class NotificationStackScrollLayoutController { private final NotificationLockscreenUserManager mLockscreenUserManager; // TODO: StatusBar should be encapsulated behind a Controller private final StatusBar mStatusBar; + private final NotificationGroupManagerLegacy mLegacyGroupManager; private final SectionHeaderController mSilentHeaderController; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; @@ -218,6 +222,28 @@ public class NotificationStackScrollLayoutController { } }; + private final DeviceProvisionedListener mDeviceProvisionedListener = + new DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSwitched() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSetupChanged() { + updateCurrentUserIsSetup(); + } + + private void updateCurrentUserIsSetup() { + mView.setCurrentUserSetup(mDeviceProvisionedController.isCurrentUserSetup()); + } + }; + private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> { if (mView.isExpanded()) { // The bottom might change because we're using the final actual height of the view @@ -587,6 +613,7 @@ public class NotificationStackScrollLayoutController { HeadsUpManagerPhone headsUpManager, NotificationRoundnessManager notificationRoundnessManager, TunerService tunerService, + DeviceProvisionedController deviceProvisionedController, DynamicPrivacyController dynamicPrivacyController, ConfigurationController configurationController, SysuiStatusBarStateController statusBarStateController, @@ -623,6 +650,7 @@ public class NotificationStackScrollLayoutController { mHeadsUpManager = headsUpManager; mNotificationRoundnessManager = notificationRoundnessManager; mTunerService = tunerService; + mDeviceProvisionedController = deviceProvisionedController; mDynamicPrivacyController = dynamicPrivacyController; mConfigurationController = configurationController; mStatusBarStateController = statusBarStateController; @@ -651,6 +679,8 @@ public class NotificationStackScrollLayoutController { mStatusBar.requestNotificationUpdate("onGroupsChanged"); } }); + mLegacyGroupManager = featureFlags.isNewNotifPipelineRenderingEnabled() + ? null : legacyGroupManager; mSilentHeaderController = silentHeaderController; mFeatureFlags = featureFlags; mNotifPipeline = notifPipeline; @@ -759,6 +789,9 @@ public class NotificationStackScrollLayoutController { return Unit.INSTANCE; }); + // callback is invoked synchronously, updating mView immediately + mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); + if (mView.isAttachedToWindow()) { mOnAttachStateChangeListener.onViewAttachedToWindow(mView); } @@ -1122,6 +1155,10 @@ public class NotificationStackScrollLayoutController { mZenModeController.areNotificationsHiddenInShade()); } + public boolean areNotificationsHiddenInShade() { + return mZenModeController.areNotificationsHiddenInShade(); + } + public boolean isShowingEmptyShadeView() { return mShowEmptyShadeView; } @@ -1170,6 +1207,10 @@ public class NotificationStackScrollLayoutController { * Return whether there are any clearable notifications */ public boolean hasActiveClearableNotifications(@SelectedRows int selection) { + return hasNotifications(selection, true /* clearable */); + } + + public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) { if (mDynamicPrivacyController.isInLockedDownShade()) { return false; } @@ -1180,9 +1221,16 @@ public class NotificationStackScrollLayoutController { continue; } final ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (row.canViewBeDismissed() && - NotificationStackScrollLayout.matchesSelection(row, selection)) { - return true; + final boolean matchClearable = + isClearable ? row.canViewBeDismissed() : !row.canViewBeDismissed(); + final boolean inSection = + NotificationStackScrollLayout.matchesSelection(row, selection); + if (matchClearable && inSection) { + if (mLegacyGroupManager == null + || !mLegacyGroupManager.isSummaryOfSuppressedGroup( + row.getEntry().getSbn())) { + return true; + } } } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 2c810c93b2ee..8be5de7ae56e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -366,6 +366,20 @@ public class StackScrollAlgorithm { return stackHeight / stackEndHeight; } + public boolean hasOngoingNotifs(StackScrollAlgorithmState algorithmState) { + for (int i = 0; i < algorithmState.visibleChildren.size(); i++) { + View child = algorithmState.visibleChildren.get(i); + if (!(child instanceof ExpandableNotificationRow)) { + continue; + } + final ExpandableNotificationRow row = (ExpandableNotificationRow) child; + if (!row.canViewBeDismissed()) { + return true; + } + } + return false; + } + // TODO(b/172289889) polish shade open from HUN /** * Populates the {@link ExpandableViewState} for a single child. @@ -430,7 +444,9 @@ public class StackScrollAlgorithm { + view.getIntrinsicHeight(); final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight(); ((FooterView.FooterViewState) viewState).hideContent = - isShelfShowing || noSpaceForFooter; + isShelfShowing || noSpaceForFooter + || (ambientState.isDismissAllInProgress() + && !hasOngoingNotifs(algorithmState)); } } else { if (view != ambientState.getTrackedHeadsUpRow()) { @@ -467,7 +483,6 @@ public class StackScrollAlgorithm { } } } - // Clip height of view right before shelf. viewState.height = (int) (getMaxAllowedChildHeight(view) * expansionFraction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index ee12b4b2d728..4466cfe99fe1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -46,7 +46,7 @@ public class StackStateAnimator { public static final int ANIMATION_DURATION_WAKEUP = 500; public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448; public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464; - public static final int ANIMATION_DURATION_SWIPE = 260; + public static final int ANIMATION_DURATION_SWIPE = 200; public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220; public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150; public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 5a6db213d87f..e67c6ac3a7c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -291,6 +291,7 @@ public class DozeParameters implements TunerService.Tunable, @Override public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + pw.print("getAlwaysOn(): "); pw.println(getAlwaysOn()); pw.print("getDisplayStateSupported(): "); pw.println(getDisplayStateSupported()); pw.print("getPulseDuration(): "); pw.println(getPulseDuration()); pw.print("getPulseInDuration(): "); pw.println(getPulseInDuration()); 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 b2cf72aca864..21c3e5e0a8d0 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 @@ public class DozeScrimController implements StateListener { 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 bb48d1aba4d4..ecf3e0a953a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -206,13 +206,15 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private ControlsListingController.ControlsListingCallback mListingCallback = new ControlsListingController.ControlsListingCallback() { public void onServicesUpdated(List<ControlsServiceInfo> serviceInfos) { - boolean available = !serviceInfos.isEmpty(); + post(() -> { + boolean available = !serviceInfos.isEmpty(); - if (available != mControlServicesAvailable) { - mControlServicesAvailable = available; - updateControlsVisibility(); - updateAffordanceColors(); - } + if (available != mControlServicesAvailable) { + mControlServicesAvailable = available; + updateControlsVisibility(); + updateAffordanceColors(); + } + }); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index f77c0520cdb1..b58cab4f1ea4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -83,8 +83,7 @@ public class KeyguardClockPositionAlgorithm { private int mNotificationStackHeight; /** - * Minimum top margin to avoid overlap with status bar, lock icon, or multi-user switcher - * avatar. + * Minimum top margin to avoid overlap with status bar, or multi-user switcher avatar. */ private int mMinTopMargin; @@ -150,6 +149,25 @@ public class KeyguardClockPositionAlgorithm { private boolean mIsSplitShade; /** + * Top location of the udfps icon. This includes the worst case (highest) burn-in + * offset that would make the top physically highest on the screen. + * + * Set to -1 if udfps is not enrolled on the device. + */ + private float mUdfpsTop; + + /** + * Bottom y-position of the currently visible clock + */ + private float mClockBottom; + + /** + * If true, try to keep clock aligned to the top of the display. Else, assume the clock + * is center aligned. + */ + private boolean mIsClockTopAligned; + + /** * Refreshes the dimension values. */ public void loadDimens(Resources res) { @@ -157,7 +175,7 @@ public class KeyguardClockPositionAlgorithm { R.dimen.keyguard_status_view_bottom_margin); mContainerTopPadding = - res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) / 2; + res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); mBurnInPreventionOffsetX = res.getDimensionPixelSize( R.dimen.burn_in_prevention_offset_x); mBurnInPreventionOffsetY = res.getDimensionPixelSize( @@ -174,7 +192,8 @@ public class KeyguardClockPositionAlgorithm { int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding, - float qsExpansion, int cutoutTopInset, boolean isSplitShade) { + float qsExpansion, int cutoutTopInset, boolean isSplitShade, float udfpsTop, + float clockBottom, boolean isClockTopAligned) { mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding, userSwitchHeight); mMaxShadeBottom = maxShadeBottom; @@ -193,6 +212,9 @@ public class KeyguardClockPositionAlgorithm { mQsExpansion = qsExpansion; mCutoutTopInset = cutoutTopInset; mIsSplitShade = isSplitShade; + mUdfpsTop = udfpsTop; + mClockBottom = clockBottom; + mIsClockTopAligned = isClockTopAligned; } public void run(Result result) { @@ -247,8 +269,34 @@ public class KeyguardClockPositionAlgorithm { if (clockY - mBurnInPreventionOffsetYLargeClock < mCutoutTopInset) { shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYLargeClock); } - float clockYDark = clockY + burnInPreventionOffsetY() + shift; + int burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock; // requested offset + final boolean hasUdfps = mUdfpsTop > -1; + if (hasUdfps && !mIsClockTopAligned) { + // ensure clock doesn't overlap with the udfps icon + if (mUdfpsTop < mClockBottom) { + // sometimes the clock textView extends beyond udfps, so let's just use the + // space above the KeyguardStatusView/clock as our burn-in offset + burnInPreventionOffsetY = (int) (clockY - mCutoutTopInset) / 2; + if (mBurnInPreventionOffsetYLargeClock < burnInPreventionOffsetY) { + burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock; + } + shift = -burnInPreventionOffsetY; + } else { + float upperSpace = clockY - mCutoutTopInset; + float lowerSpace = mUdfpsTop - mClockBottom; + // center the burn-in offset within the upper + lower space + burnInPreventionOffsetY = (int) (lowerSpace + upperSpace) / 2; + if (mBurnInPreventionOffsetYLargeClock < burnInPreventionOffsetY) { + burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock; + } + shift = (lowerSpace - upperSpace) / 2; + } + } + + float clockYDark = clockY + + burnInPreventionOffsetY(burnInPreventionOffsetY) + + shift; return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount); } @@ -280,9 +328,7 @@ public class KeyguardClockPositionAlgorithm { return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount); } - private float burnInPreventionOffsetY() { - int offset = mBurnInPreventionOffsetYLargeClock; - + private float burnInPreventionOffsetY(int offset) { return getBurnInOffset(offset * 2, false /* xAxis */) - offset; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java index f1cde8a9be7a..a5b5f1cbf1e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java @@ -28,7 +28,10 @@ import android.util.AttributeSet; import android.view.View; import android.widget.TextView; +import androidx.annotation.StyleRes; + import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.keyguard.KeyguardIndication; @@ -39,6 +42,12 @@ import java.util.LinkedList; */ public class KeyguardIndicationTextView extends TextView { private static final long MSG_MIN_DURATION_MILLIS_DEFAULT = 1500; + + @StyleRes + private static int sStyleId = R.style.TextAppearance_Keyguard_BottomArea; + @StyleRes + private static int sButtonStyleId = R.style.TextAppearance_Keyguard_BottomArea_Button; + private long mNextAnimationTime = 0; private boolean mAnimationsEnabled = true; private LinkedList<CharSequence> mMessages = new LinkedList<>(); @@ -136,6 +145,14 @@ public class KeyguardIndicationTextView extends TextView { public void onAnimationEnd(Animator animator) { KeyguardIndication info = mKeyguardIndicationInfo.poll(); if (info != null) { + // First, update the style. + // If a background is set on the text, we don't want shadow on the text + if (info.getBackground() != null) { + setTextAppearance(sButtonStyleId); + } else { + setTextAppearance(sStyleId); + } + setBackground(info.getBackground()); setTextColor(info.getTextColor()); setOnClickListener(info.getClickListener()); setClickable(info.getClickListener() != null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index e272d2713e2a..55e0c9b979c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -96,7 +96,8 @@ public class KeyguardStatusBarView extends RelativeLayout implements private final UserManager mUserManager; private int mSystemIconsSwitcherHiddenExpandedMargin; - private int mSystemIconsBaseMargin; + private int mStatusBarPaddingEnd; + private int mMinDotWidth; private View mSystemIconsContainer; private TintedIconManager mIconManager; private List<String> mBlockedIcons = new ArrayList<>(); @@ -157,14 +158,7 @@ public class KeyguardStatusBarView extends RelativeLayout implements mMultiUserAvatar.setLayoutParams(lp); // System icons - lp = (MarginLayoutParams) mSystemIconsContainer.getLayoutParams(); - lp.setMarginStart(getResources().getDimensionPixelSize( - R.dimen.system_icons_super_container_margin_start)); - mSystemIconsContainer.setLayoutParams(lp); - mSystemIconsContainer.setPaddingRelative(mSystemIconsContainer.getPaddingStart(), - mSystemIconsContainer.getPaddingTop(), - getResources().getDimensionPixelSize(R.dimen.system_icons_keyguard_padding_end), - mSystemIconsContainer.getPaddingBottom()); + updateSystemIconsLayoutParams(); // Respect font size setting. mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, @@ -194,8 +188,10 @@ public class KeyguardStatusBarView extends RelativeLayout implements Resources res = getResources(); mSystemIconsSwitcherHiddenExpandedMargin = res.getDimensionPixelSize( R.dimen.system_icons_switcher_hidden_expanded_margin); - mSystemIconsBaseMargin = res.getDimensionPixelSize( - R.dimen.system_icons_super_container_avatarless_margin_end); + mStatusBarPaddingEnd = res.getDimensionPixelSize( + R.dimen.status_bar_padding_end); + mMinDotWidth = res.getDimensionPixelSize( + R.dimen.ongoing_appops_dot_min_padding); mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); mShowPercentAvailable = getContext().getResources().getBoolean( @@ -243,16 +239,24 @@ public class KeyguardStatusBarView extends RelativeLayout implements private void updateSystemIconsLayoutParams() { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams(); - // If the avatar icon is gone, we need to have some end margin to display the system icons - // correctly. - int baseMarginEnd = mMultiUserAvatar.getVisibility() == View.GONE - ? mSystemIconsBaseMargin - : 0; + + int marginStart = getResources().getDimensionPixelSize( + R.dimen.system_icons_super_container_margin_start); + + // Use status_bar_padding_end to replace original + // system_icons_super_container_avatarless_margin_end to prevent different end alignment + // between PhoneStatusBarView and KeyguardStatusBarView + int baseMarginEnd = mStatusBarPaddingEnd; int marginEnd = mKeyguardUserSwitcherEnabled ? mSystemIconsSwitcherHiddenExpandedMargin : baseMarginEnd; - marginEnd = calculateMargin(marginEnd, mPadding.second); - if (marginEnd != lp.getMarginEnd()) { + + // Align PhoneStatusBar right margin/padding, only use + // 1. status bar layout: mPadding(consider round_corner + privacy dot) + // 2. icon container: R.dimen.status_bar_padding_end + + if (marginEnd != lp.getMarginEnd() || marginStart != lp.getMarginStart()) { + lp.setMarginStart(marginStart); lp.setMarginEnd(marginEnd); mSystemIconsContainer.setLayoutParams(lp); } @@ -287,7 +291,13 @@ public class KeyguardStatusBarView extends RelativeLayout implements mPadding = StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner( mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding); - setPadding(mPadding.first, waterfallTop, mPadding.second, 0); + + // consider privacy dot space + final int minLeft = isLayoutRtl() ? Math.max(mMinDotWidth, mPadding.first) : mPadding.first; + final int minRight = isLayoutRtl() ? mPadding.second : + Math.max(mMinDotWidth, mPadding.second); + + setPadding(minLeft, waterfallTop, minRight, 0); } private boolean updateLayoutParamsNoCutout() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 373a276e5326..7af289fb4094 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -51,6 +51,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.drawable.Drawable; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; @@ -626,6 +627,8 @@ public class NotificationPanelViewController extends PanelViewController { */ private float mKeyguardOnlyContentAlpha = 1.0f; + private float mUdfpsMaxYBurnInOffset; + /** * Are we currently in gesture navigation */ @@ -640,6 +643,7 @@ public class NotificationPanelViewController extends PanelViewController { private int mQsClipBottom; private boolean mQsVisible; private final ContentResolver mContentResolver; + private float mMinFraction; private final Executor mUiExecutor; private final SecureSettings mSecureSettings; @@ -859,13 +863,13 @@ public class NotificationPanelViewController extends PanelViewController { mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header); mBigClockContainer = mView.findViewById(R.id.big_clock_container); - UserAvatarView userAvatarView = null; + FrameLayout userAvatarContainer = null; KeyguardUserSwitcherView keyguardUserSwitcherView = null; if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) { if (mKeyguardQsUserSwitchEnabled) { ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub); - userAvatarView = (UserAvatarView) stub.inflate(); + userAvatarContainer = (FrameLayout) stub.inflate(); } else { ViewStub stub = mView.findViewById(R.id.keyguard_user_switcher_stub); keyguardUserSwitcherView = (KeyguardUserSwitcherView) stub.inflate(); @@ -874,7 +878,7 @@ public class NotificationPanelViewController extends PanelViewController { updateViewControllers( mView.findViewById(R.id.keyguard_status_view), - userAvatarView, + userAvatarContainer, mKeyguardStatusBar, keyguardUserSwitcherView); mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent); @@ -963,10 +967,11 @@ public class NotificationPanelViewController extends PanelViewController { mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources); mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize( R.dimen.notification_side_paddings); + mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); } private void updateViewControllers(KeyguardStatusView keyguardStatusView, - UserAvatarView userAvatarView, + FrameLayout userAvatarView, KeyguardStatusBarView keyguardStatusBarView, KeyguardUserSwitcherView keyguardUserSwitcherView) { // Re-associate the KeyguardStatusViewController @@ -1118,7 +1123,7 @@ public class NotificationPanelViewController extends PanelViewController { !mKeyguardQsUserSwitchEnabled && mKeyguardUserSwitcherEnabled && isUserSwitcherEnabled; - UserAvatarView userAvatarView = (UserAvatarView) reInflateStub( + FrameLayout userAvatarView = (FrameLayout) reInflateStub( R.id.keyguard_qs_user_switch_view /* viewId */, R.id.keyguard_qs_user_switch_stub /* stubId */, R.layout.keyguard_qs_user_switch /* layoutId */, @@ -1311,7 +1316,16 @@ public class NotificationPanelViewController extends PanelViewController { float darkamount = mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() ? 1.0f : mInterpolatedDarkAmount; - mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard, + + float udfpsAodTopLocation = -1f; + if (mUpdateMonitor.isUdfpsEnrolled() && mAuthController.getUdfpsProps().size() > 0) { + FingerprintSensorPropertiesInternal props = mAuthController.getUdfpsProps().get(0); + udfpsAodTopLocation = props.sensorLocationY - props.sensorRadius + - mUdfpsMaxYBurnInOffset; + } + + mClockPositionAlgorithm.setup( + mStatusBarHeaderHeightKeyguard, totalHeight - bottomPadding, mNotificationStackScrollLayoutController.getIntrinsicContentHeight(), expandedFraction, @@ -1323,7 +1337,10 @@ public class NotificationPanelViewController extends PanelViewController { bypassEnabled, getUnlockedStackScrollerPadding(), computeQsExpansionFraction(), mDisplayTopInset, - mShouldUseSplitNotificationShade); + mShouldUseSplitNotificationShade, + udfpsAodTopLocation, + mKeyguardStatusViewController.getClockBottom(mStatusBarHeaderHeightKeyguard), + mKeyguardStatusViewController.isClockTopAligned()); mClockPositionAlgorithm.run(mClockPositionResult); boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending(); boolean animateClock = animate || mAnimateNextPositionUpdate; @@ -1806,6 +1823,15 @@ public class NotificationPanelViewController extends PanelViewController { return !mQsTouchAboveFalsingThreshold; } + /** + * Percentage of panel expansion offset, caused by pulling down on a heads-up. + */ + @Override + public void setMinFraction(float minFraction) { + mMinFraction = minFraction; + mDepthController.setPanelPullDownMinFraction(mMinFraction); + } + private float computeQsExpansionFraction() { if (mQSAnimatingHiddenFromCollapsed) { // When hiding QS from collapsed state, the expansion can sometimes temporarily @@ -2320,6 +2346,12 @@ public class NotificationPanelViewController extends PanelViewController { } } top += mOverStretchAmount; + // Correction for instant expansion caused by HUN pull down/ + if (mMinFraction > 0f && mMinFraction < 1f) { + float realFraction = + (getExpandedFraction() - mMinFraction) / (1f - mMinFraction); + top *= MathUtils.saturate(realFraction / mMinFraction); + } bottom = getView().getBottom(); // notification bounds should take full screen width regardless of insets left = 0; @@ -3450,7 +3482,7 @@ public class NotificationPanelViewController extends PanelViewController { } public void setPanelScrimMinFraction(float minFraction) { - mBar.panelScrimMinFractionChanged(minFraction); + mBar.onPanelMinFractionChanged(minFraction); } public void clearNotificationEffects() { 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 246810a2d70b..c26782b017c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -605,12 +605,11 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } @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 66a6e723ede2..3807b4647fe1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -325,6 +325,12 @@ public class NotificationShadeWindowViewController { // 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() @@ -352,6 +358,12 @@ public class NotificationShadeWindowViewController { 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/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index f1b6c7c3ad19..eca91a3f6fb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import static java.lang.Float.isNaN; +import android.annotation.CallSuper; import android.content.Context; import android.os.Bundle; import android.os.Parcelable; @@ -162,7 +163,13 @@ public abstract class PanelBar extends FrameLayout { return mPanel == null || mPanel.getView().dispatchTouchEvent(event); } - public abstract void panelScrimMinFractionChanged(float minFraction); + /** + * Percentage of panel expansion offset, caused by pulling down on a heads-up. + */ + @CallSuper + public void onPanelMinFractionChanged(float minFraction) { + mPanel.setMinFraction(minFraction); + } /** * @param frac the fraction from the expansion in [0, 1] 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 4de042fc4c10..30a4d69c8c24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -346,6 +346,13 @@ public abstract class PanelViewController { protected abstract float getOpeningHeight(); /** + * Minimum fraction from where expansion should start. This is set when pulling down on a + * heads-up notification. + * @param minFraction Fraction from 0 to 1. + */ + public abstract void setMinFraction(float minFraction); + + /** * @return whether the swiping direction is upwards and above a 45 degree angle compared to the * horizontal direction */ @@ -1229,10 +1236,14 @@ public abstract class PanelViewController { 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); @@ -1245,10 +1256,7 @@ public abstract class PanelViewController { 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/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index c300b11b9a34..2ca36b648b76 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -269,10 +269,11 @@ public class PhoneStatusBarView extends PanelBar { } @Override - public void panelScrimMinFractionChanged(float minFraction) { + public void onPanelMinFractionChanged(float minFraction) { if (isNaN(minFraction)) { throw new IllegalArgumentException("minFraction cannot be NaN"); } + super.onPanelMinFractionChanged(minFraction); if (mMinFraction != minFraction) { mMinFraction = minFraction; updateScrimFraction(); 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 7d25aeef6f98..27c129ad34c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -587,6 +587,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump if (isNaN(expansionFraction)) { return; } + expansionFraction = Interpolators + .getNotificationScrimAlpha(expansionFraction, false /* notification */); boolean qsBottomVisible = qsPanelBottomY > 0; if (mQsExpansion != expansionFraction || mQsBottomVisible != qsBottomVisible) { mQsExpansion = expansionFraction; @@ -1262,6 +1264,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump pw.println(mDefaultScrimAlpha); pw.print(" mExpansionFraction="); pw.println(mPanelExpansion); + pw.print(" mExpansionAffectsAlpha="); + pw.println(mExpansionAffectsAlpha); pw.print(" mState.getMaxLightRevealScrimAlpha="); pw.println(mState.getMaxLightRevealScrimAlpha()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 2c0de629de8a..15b8c67fd4ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -279,15 +279,41 @@ public enum ScrimState { BUBBLE_EXPANDED { @Override public void prepare(ScrimState previousState) { + mBehindAlpha = mClipQsScrim ? 1 : 0; + mNotifAlpha = 0; + mFrontAlpha = 0; + + mAnimationDuration = mKeyguardFadingAway + ? mKeyguardFadingAwayDuration + : StatusBar.FADE_KEYGUARD_DURATION; + + mAnimateChange = !mLaunchingAffordanceWithPreview; + mFrontTint = Color.TRANSPARENT; - mBehindTint = Color.TRANSPARENT; + mBehindTint = Color.BLACK; mBubbleTint = Color.BLACK; + mBlankScreen = false; - mFrontAlpha = 0f; - mBehindAlpha = mDefaultScrimAlpha; + if (previousState == ScrimState.AOD) { + // Set all scrims black, before they fade transparent. + updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */); + updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */); + if (mScrimForBubble != null) { + updateScrimColor(mScrimForBubble, 1f /* alpha */, Color.BLACK /* tint */); + } + + // Scrims should still be black at the end of the transition. + mFrontTint = Color.BLACK; + mBehindTint = Color.BLACK; + mBubbleTint = Color.BLACK; + mBlankScreen = true; + } + + if (mClipQsScrim) { + updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); + } mAnimationDuration = ScrimController.ANIMATION_DURATION; - mBlankScreen = false; } }; 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 e2194ad61b45..98c4af42daaa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1045,7 +1045,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationShadeWindowViewController, mNotificationPanelViewController, mAmbientIndicationContainer); - mDozeParameters.addCallback(this::updateLightRevealScrimVisibility); + updateLightRevealScrimVisibility(); mConfigurationController.addCallback(this); @@ -1262,8 +1262,19 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront, scrimForBubble); 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(); @@ -4456,8 +4467,11 @@ public class StatusBar extends SystemUI implements DemoMode, || mKeyguardStateController.isKeyguardFadingAway(); // Do not animate the scrim expansion when triggered by the fingerprint sensor. - mScrimController.setExpansionAffectsAlpha( - !mBiometricUnlockController.isBiometricUnlock()); + boolean onKeyguardOrHidingIt = mKeyguardStateController.isShowing() + || mKeyguardStateController.isKeyguardFadingAway() + || mKeyguardStateController.isKeyguardGoingAway(); + mScrimController.setExpansionAffectsAlpha(!(mBiometricUnlockController.isBiometricUnlock() + && onKeyguardOrHidingIt)); boolean launchingAffordanceWithPreview = mNotificationPanelViewController.isLaunchingAffordanceWithPreview(); @@ -4959,11 +4973,5 @@ public class StatusBar extends SystemUI implements DemoMode, } mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha()); - if (mFeatureFlags.useNewLockscreenAnimations() - && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) { - mLightRevealScrim.setVisibility(View.VISIBLE); - } else { - mLightRevealScrim.setVisibility(View.GONE); - } } } 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 3188a522dfad..df445cbeb9e1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -53,6 +53,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.FaceAuthScreenBrightnessController; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; @@ -92,7 +93,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb // with the appear animations of the PIN/pattern/password views. private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320; - private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200; + // The duration to fade the nav bar content in/out when the device starts to sleep + private static final long NAV_BAR_CONTENT_FADE_DURATION = 125; // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to // make everything a bit slower to bridge a gap until the user is unlocked and home screen has @@ -194,10 +196,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private boolean mLastGesturalNav; private boolean mLastIsDocked; private boolean mLastPulsing; - private boolean mLastAnimatedToSleep; private int mLastBiometricMode; private boolean mQsExpanded; - private boolean mAnimatedToSleep; private OnDismissAction mAfterKeyguardGoneAction; private Runnable mKeyguardGoneCancelAction; @@ -304,8 +304,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb * Sets a new alt auth interceptor. */ public void setAlternateAuthInterceptor(@NonNull AlternateAuthInterceptor authInterceptor) { - mAlternateAuthInterceptor = authInterceptor; - resetAlternateAuth(false); + if (!Objects.equals(mAlternateAuthInterceptor, authInterceptor)) { + mAlternateAuthInterceptor = authInterceptor; + resetAlternateAuth(false); + } } private void registerListeners() { @@ -318,20 +320,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mDockManager.addListener(mDockEventListener); mIsDocked = mDockManager.isDocked(); } - mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() { - @Override - public void onFinishedWakingUp() { - mAnimatedToSleep = false; - updateStates(); - } - - @Override - public void onFinishedGoingToSleep() { - mAnimatedToSleep = - mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying(); - updateStates(); - } - }); } @Override @@ -564,12 +552,26 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onStartedWakingUp() { mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() .setAnimationsDisabled(false); + View currentView = getCurrentNavBarView(); + if (currentView != null) { + currentView.animate() + .alpha(1f) + .setDuration(NAV_BAR_CONTENT_FADE_DURATION) + .start(); + } } @Override public void onStartedGoingToSleep() { mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() .setAnimationsDisabled(true); + View currentView = getCurrentNavBarView(); + if (currentView != null) { + currentView.animate() + .alpha(0f) + .setDuration(NAV_BAR_CONTENT_FADE_DURATION) + .start(); + } } @Override @@ -897,7 +899,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public boolean bouncerIsOrWillBeShowing() { - return mBouncer.isShowing() || mBouncer.getShowingSoon(); + return isBouncerShowing() || mBouncer.getShowingSoon(); } public boolean isFullscreenBouncer() { @@ -991,10 +993,28 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mLastBiometricMode = mBiometricUnlockController.getMode(); mLastGesturalNav = mGesturalNav; mLastIsDocked = mIsDocked; - mLastAnimatedToSleep = mAnimatedToSleep; mStatusBar.onKeyguardViewManagerStatesUpdated(); } + /** + * Updates the visibility of the nav bar content views. + */ + private void updateNavigationBarContentVisibility(boolean navBarContentVisible) { + final NavigationBarView navBarView = mStatusBar.getNavigationBarView(); + if (navBarView != null && navBarView.getCurrentView() != null) { + final View currentView = navBarView.getCurrentView(); + currentView.setVisibility(navBarContentVisible ? View.VISIBLE : View.INVISIBLE); + } + } + + private View getCurrentNavBarView() { + final NavigationBarView navBarView = mStatusBar.getNavigationBarView(); + return navBarView != null ? navBarView.getCurrentView() : null; + } + + /** + * Updates the visibility of the nav bar window (which will cause insets changes). + */ protected void updateNavigationBarVisibility(boolean navBarVisible) { if (mStatusBar.getNavigationBarView() != null) { if (navBarVisible) { @@ -1022,7 +1042,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb boolean hideWhileDozing = mDozing && biometricMode != MODE_WAKE_AND_UNLOCK_PULSING; boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked) && mGesturalNav; - return (!mAnimatedToSleep && !keyguardShowing && !hideWhileDozing || mBouncer.isShowing() + return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing() || mRemoteInputActive || keyguardWithGestureNav || mGlobalActionsVisible); } @@ -1032,12 +1052,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb */ protected boolean getLastNavBarVisible() { boolean keyguardShowing = mLastShowing && !mLastOccluded; - boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING; - boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing - || mLastPulsing && !mLastIsDocked) && mLastGesturalNav; - return (!mLastAnimatedToSleep && !keyguardShowing && !hideWhileDozing || mLastBouncerShowing - || mLastRemoteInputActive || keyguardWithGestureNav - || mLastGlobalActionsVisible); + boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING; + boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing + || mLastPulsing && !mLastIsDocked) && mLastGesturalNav; + return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing + || mLastRemoteInputActive || keyguardWithGestureNav + || mLastGlobalActionsVisible); } public boolean shouldDismissOnMenuPressed() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index 47deb1f0084b..8821de077ec3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -310,17 +310,11 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, private void onNotificationRemoved(String key, StatusBarNotification old, int reason) { if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); - if (old != null) { - if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() - && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) { - if (mStatusBarStateController.getState() == StatusBarState.SHADE - && reason != NotificationListenerService.REASON_CLICK) { - mCommandQueue.animateCollapsePanels(); - } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED + if (old != null && CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() + && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded() + && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED && !isCollapsing()) { - mStatusBarStateController.setState(StatusBarState.KEYGUARD); - } - } + mStatusBarStateController.setState(StatusBarState.KEYGUARD); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index 6b52dca42eda..e3f4b03dc4f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -5,7 +5,9 @@ import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.content.Context import android.content.res.Configuration +import android.database.ContentObserver import android.os.Handler +import android.provider.Settings import android.view.View import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton @@ -19,6 +21,7 @@ import com.android.systemui.statusbar.notification.PropertyAnimator import com.android.systemui.statusbar.notification.stack.AnimationProperties import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.settings.GlobalSettings import javax.inject.Inject /** @@ -46,15 +49,19 @@ class UnlockedScreenOffAnimationController @Inject constructor( private val statusBarStateControllerImpl: StatusBarStateControllerImpl, private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>, private val keyguardStateController: KeyguardStateController, - private val dozeParameters: dagger.Lazy<DozeParameters> + private val dozeParameters: dagger.Lazy<DozeParameters>, + private val globalSettings: GlobalSettings ) : WakefulnessLifecycle.Observer { private val handler = Handler() private lateinit var statusBar: StatusBar private lateinit var lightRevealScrim: LightRevealScrim + private var animatorDurationScale = 1f + private var shouldAnimateInKeyguard = false private var lightRevealAnimationPlaying = false private var aodUiAnimationPlaying = false + private var callbacks = HashSet<Callback>() /** * The result of our decision whether to play the screen off animation in @@ -66,11 +73,17 @@ class UnlockedScreenOffAnimationController @Inject constructor( private val lightRevealAnimator = ValueAnimator.ofFloat(1f, 0f).apply { duration = LIGHT_REVEAL_ANIMATION_DURATION interpolator = Interpolators.LINEAR - addUpdateListener { lightRevealScrim.revealAmount = it.animatedValue as Float } + addUpdateListener { + lightRevealScrim.revealAmount = it.animatedValue as Float + sendUnlockedScreenOffProgressUpdate( + 1f - (it.animatedFraction as Float), + 1f - (it.animatedValue as Float)) + } addListener(object : AnimatorListenerAdapter() { override fun onAnimationCancel(animation: Animator?) { lightRevealScrim.revealAmount = 1f lightRevealAnimationPlaying = false + sendUnlockedScreenOffProgressUpdate(0f, 0f) } override fun onAnimationEnd(animation: Animator?) { @@ -79,6 +92,12 @@ class UnlockedScreenOffAnimationController @Inject constructor( }) } + val animatorDurationScaleObserver = object : ContentObserver(null) { + override fun onChange(selfChange: Boolean) { + updateAnimatorDurationScale() + } + } + fun initialize( statusBar: StatusBar, lightRevealScrim: LightRevealScrim @@ -86,14 +105,25 @@ class UnlockedScreenOffAnimationController @Inject constructor( this.lightRevealScrim = lightRevealScrim this.statusBar = statusBar + updateAnimatorDurationScale() + globalSettings.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE), + /* notify for descendants */ false, + animatorDurationScaleObserver) wakefulnessLifecycle.addObserver(this) } + fun updateAnimatorDurationScale() { + animatorDurationScale = + globalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) + } + /** * Animates in the provided keyguard view, ending in the same position that it will be in on * AOD. */ fun animateInKeyguard(keyguardView: View, after: Runnable) { + shouldAnimateInKeyguard = false keyguardView.alpha = 0f keyguardView.visibility = View.VISIBLE @@ -115,22 +145,27 @@ class UnlockedScreenOffAnimationController @Inject constructor( .setDuration(duration.toLong()) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .alpha(1f) - .withEndAction { - aodUiAnimationPlaying = false + .setListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + aodUiAnimationPlaying = false - // Lock the keyguard if it was waiting for the screen off animation to end. - keyguardViewMediatorLazy.get().maybeHandlePendingLock() + // Lock the keyguard if it was waiting for the screen off animation to end. + keyguardViewMediatorLazy.get().maybeHandlePendingLock() - // Tell the StatusBar to become keyguard for real - we waited on that since it - // is slow and would have caused the animation to jank. - statusBar.updateIsKeyguard() + // Tell the StatusBar to become keyguard for real - we waited on that since + // it is slow and would have caused the animation to jank. + statusBar.updateIsKeyguard() - // Run the callback given to us by the KeyguardVisibilityHelper. - after.run() + // Run the callback given to us by the KeyguardVisibilityHelper. + after.run() - // Done going to sleep, reset this flag. - decidedToAnimateGoingToSleep = null - } + // Done going to sleep, reset this flag. + decidedToAnimateGoingToSleep = null + + // We need to unset the listener. These are persistent for future animators + keyguardView.animate().setListener(null) + } + }) .start() } @@ -138,6 +173,7 @@ class UnlockedScreenOffAnimationController @Inject constructor( // Waking up, so reset this flag. decidedToAnimateGoingToSleep = null + shouldAnimateInKeyguard = false lightRevealAnimator.cancel() handler.removeCallbacksAndMessages(null) } @@ -146,7 +182,6 @@ class UnlockedScreenOffAnimationController @Inject constructor( // Set this to false in onFinishedWakingUp rather than onStartedWakingUp so that other // observers (such as StatusBar) can ask us whether we were playing the screen off animation // and reset accordingly. - lightRevealAnimationPlaying = false aodUiAnimationPlaying = false // If we can't control the screen off animation, we shouldn't mess with the StatusBar's @@ -167,15 +202,15 @@ class UnlockedScreenOffAnimationController @Inject constructor( if (dozeParameters.get().shouldControlUnlockedScreenOff()) { decidedToAnimateGoingToSleep = true + shouldAnimateInKeyguard = true lightRevealAnimationPlaying = true lightRevealAnimator.start() - handler.postDelayed({ aodUiAnimationPlaying = true // Show AOD. That'll cause the KeyguardVisibilityHelper to call #animateInKeyguard. statusBar.notificationPanelViewController.showAodUi() - }, ANIMATE_IN_KEYGUARD_DELAY) + }, (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong()) } else { decidedToAnimateGoingToSleep = false } @@ -220,7 +255,21 @@ class UnlockedScreenOffAnimationController @Inject constructor( return true } - /** + fun addCallback(callback: Callback) { + callbacks.add(callback) + } + + fun removeCallback(callback: Callback) { + callbacks.remove(callback) + } + + fun sendUnlockedScreenOffProgressUpdate(linear: Float, eased: Float) { + callbacks.forEach { + it.onUnlockedScreenOffProgressUpdate(linear, eased) + } + } + +/** * Whether we're doing the light reveal animation or we're done with that and animating in the * AOD UI. */ @@ -228,6 +277,10 @@ class UnlockedScreenOffAnimationController @Inject constructor( return lightRevealAnimationPlaying || aodUiAnimationPlaying } + fun shouldAnimateInKeyguard(): Boolean { + return shouldAnimateInKeyguard + } + /** * Whether the light reveal animation is playing. The second part of the screen off animation, * where AOD animates in, might still be playing if this returns false. @@ -235,4 +288,8 @@ class UnlockedScreenOffAnimationController @Inject constructor( fun isScreenOffLightRevealAnimationPlaying(): Boolean { return lightRevealAnimationPlaying } -}
\ No newline at end of file + + interface Callback { + fun onUnlockedScreenOffProgressUpdate(linear: Float, eased: Float) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index 6982631766f7..80a0a9824589 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -104,7 +104,16 @@ class OngoingCallController @Inject constructor( } } + // Fix for b/199600334 + override fun onEntryCleanUp(entry: NotificationEntry) { + removeChipIfNeeded(entry) + } + override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { + removeChipIfNeeded(entry) + } + + private fun removeChipIfNeeded(entry: NotificationEntry) { if (entry.sbn.key == callNotificationInfo?.key) { removeChip() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java index ab58286859cc..6d6320e6962d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java @@ -40,6 +40,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.settings.UserTracker; +import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; import com.android.wifitrackerlib.WifiPickerTracker; @@ -68,6 +69,7 @@ public class AccessPointControllerImpl private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>(); private final UserManager mUserManager; + private final UserTracker mUserTracker; private final Executor mMainExecutor; private @Nullable WifiPickerTracker mWifiPickerTracker; @@ -84,6 +86,7 @@ public class AccessPointControllerImpl WifiPickerTrackerFactory wifiPickerTrackerFactory ) { mUserManager = userManager; + mUserTracker = userTracker; mCurrentUser = userTracker.getUserId(); mMainExecutor = mainExecutor; mWifiPickerTrackerFactory = wifiPickerTrackerFactory; @@ -118,6 +121,11 @@ public class AccessPointControllerImpl new UserHandle(mCurrentUser)); } + public boolean canConfigMobileData() { + return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, + UserHandle.of(mCurrentUser)) && mUserTracker.getUserInfo().isAdmin(); + } + public void onUserSwitched(int newUserId) { mCurrentUser = newUserId; } @@ -157,6 +165,15 @@ public class AccessPointControllerImpl } @Override + public MergedCarrierEntry getMergedCarrierEntry() { + if (mWifiPickerTracker == null) { + fireAcccessPointsCallback(Collections.emptyList()); + return null; + } + return mWifiPickerTracker.getMergedCarrierEntry(); + } + + @Override public int getIcon(WifiEntry ap) { int level = ap.getLevel(); return ICONS[Math.max(0, level)]; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java index a0edc7c494bc..1e5251196379 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java @@ -149,7 +149,7 @@ public class BrightnessMirrorController private void reinflate() { int index = mStatusBarWindow.indexOfChild(mBrightnessMirror); mStatusBarWindow.removeView(mBrightnessMirror); - mBrightnessMirror = (FrameLayout) LayoutInflater.from(mBrightnessMirror.getContext()) + mBrightnessMirror = (FrameLayout) LayoutInflater.from(mStatusBarWindow.getContext()) .inflate(R.layout.brightness_mirror_container, mStatusBarWindow, false); mToggleSliderController = setMirrorLayout(); mStatusBarWindow.addView(mBrightnessMirror, index); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java index 5e70d0dbc418..d838a05135e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java @@ -27,6 +27,7 @@ import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardVisibilityHelper; @@ -56,7 +57,7 @@ import javax.inject.Provider; * Manages the user switch on the Keyguard that is used for opening the QS user panel. */ @KeyguardUserSwitcherScope -public class KeyguardQsUserSwitchController extends ViewController<UserAvatarView> { +public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> { private static final String TAG = "KeyguardQsUserSwitchController"; private static final boolean DEBUG = KeyguardConstants.DEBUG; @@ -76,6 +77,7 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; private final KeyguardUserDetailAdapter mUserDetailAdapter; private NotificationPanelViewController mNotificationPanelViewController; + private UserAvatarView mUserAvatarView; UserSwitcherController.UserRecord mCurrentUser; // State info for the user switch and keyguard @@ -111,7 +113,7 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie @Inject public KeyguardQsUserSwitchController( - UserAvatarView view, + FrameLayout view, Context context, @Main Resources resources, ScreenLifecycle screenLifecycle, @@ -143,6 +145,7 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie protected void onInit() { super.onInit(); if (DEBUG) Log.d(TAG, "onInit"); + mUserAvatarView = mView.findViewById(R.id.kg_multi_user_avatar); mAdapter = new UserSwitcherController.BaseUserAdapter(mUserSwitcherController) { @Override public View getView(int position, View convertView, ViewGroup parent) { @@ -150,11 +153,10 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie } }; - mView.setOnClickListener(v -> { + mUserAvatarView.setOnClickListener(v -> { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return; } - if (isListAnimating()) { return; } @@ -163,7 +165,7 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie openQsUserPanel(); }); - mView.setAccessibilityDelegate(new View.AccessibilityDelegate() { + mUserAvatarView.setAccessibilityDelegate(new View.AccessibilityDelegate() { public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); info.addAction(new AccessibilityNodeInfo.AccessibilityAction( @@ -237,12 +239,12 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie R.string.accessibility_multi_user_switch_switcher); } - if (!TextUtils.equals(mView.getContentDescription(), contentDescription)) { - mView.setContentDescription(contentDescription); + if (!TextUtils.equals(mUserAvatarView.getContentDescription(), contentDescription)) { + mUserAvatarView.setContentDescription(contentDescription); } int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL; - mView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); + mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); } Drawable getCurrentUserIcon() { @@ -269,7 +271,7 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie * Get the height of the keyguard user switcher view when closed. */ public int getUserIconHeight() { - return mView.getHeight(); + return mUserAvatarView.getHeight(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java index 20b66f03192e..cd8894cae684 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java @@ -103,7 +103,7 @@ public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout { } } - if (animate) { + if (animate && userItemViews.length > 1) { // AnimationUtils will immediately hide/show the first item in the array. Since the // first view is the current user, we want to manage its visibility separately. // Set first item to null so AnimationUtils ignores it. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index dc5ecd3f1cca..be2bf0750d92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -23,6 +23,7 @@ import android.telephony.SubscriptionInfo; import com.android.settingslib.net.DataUsageController; import com.android.systemui.demomode.DemoMode; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; +import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; import java.util.List; @@ -226,9 +227,11 @@ public interface NetworkController extends CallbackController<SignalCallback>, D void addAccessPointCallback(AccessPointCallback callback); void removeAccessPointCallback(AccessPointCallback callback); void scanForAccessPoints(); + MergedCarrierEntry getMergedCarrierEntry(); int getIcon(WifiEntry ap); boolean connect(WifiEntry ap); boolean canConfigWifi(); + boolean canConfigMobileData(); public interface AccessPointCallback { void onAccessPointsChanged(List<WifiEntry> accessPoints); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index d0eef85458c0..ec8a68f914dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -70,9 +70,12 @@ import com.android.systemui.R; 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.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; +import com.android.systemui.qs.tiles.dialog.InternetDialogUtil; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -193,6 +196,8 @@ public class NetworkControllerImpl extends BroadcastReceiver private boolean mUserSetup; private boolean mSimDetected; private boolean mForceCellularValidated; + private InternetDialogFactory mInternetDialogFactory; + private Handler mMainHandler; @VisibleForTesting FiveGServiceClient mFiveGServiceClient; @@ -226,7 +231,9 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, - DumpManager dumpManager) { + DumpManager dumpManager, + @Main Handler handler, + InternetDialogFactory internetDialogFactory) { this(context, connectivityManager, telephonyManager, telephonyListenerManager, @@ -247,6 +254,8 @@ public class NetworkControllerImpl extends BroadcastReceiver featureFlags, dumpManager); mReceiverHandler.post(mRegisterListeners); + mMainHandler = handler; + mInternetDialogFactory = internetDialogFactory; } @VisibleForTesting @@ -488,6 +497,9 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + if (InternetDialogUtil.isProviderModelEnabled(mContext)) { + filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); + } filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; @@ -798,6 +810,10 @@ public class NetworkControllerImpl extends BroadcastReceiver mConfig = Config.readConfig(mContext); mReceiverHandler.post(this::handleConfigurationChanged); break; + case Settings.Panel.ACTION_INTERNET_CONNECTIVITY: + mMainHandler.post(() -> mInternetDialogFactory.create(true, + mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi())); + break; default: int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java index 22fd93ed10ed..2d47c8f0b577 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java @@ -71,7 +71,11 @@ public class NextAlarmControllerImpl extends BroadcastReceiver if (mNextAlarm != null) { pw.println(new Date(mNextAlarm.getTriggerTime())); pw.print(" PendingIntentPkg="); - pw.println(mNextAlarm.getShowIntent().getCreatorPackage()); + if (mNextAlarm.getShowIntent() != null) { + pw.println(mNextAlarm.getShowIntent().getCreatorPackage()); + } else { + pw.println("showIntent=null"); + } } else { pw.println("null"); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 84d7c05ddc14..5d7d4809dd57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -77,7 +77,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto; -import com.android.internal.util.ContrastColorUtil; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -204,7 +203,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene final int stroke = colorized ? mContext.getResources().getDimensionPixelSize( R.dimen.remote_input_view_text_stroke) : 0; if (colorized) { - final boolean dark = !ContrastColorUtil.isColorLight(backgroundColor); + final boolean dark = Notification.Builder.isColorDark(backgroundColor); final int foregroundColor = dark ? Color.WHITE : Color.BLACK; final int inverseColor = dark ? Color.BLACK : Color.WHITE; editBgColor = backgroundColor; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java index f258fb19ff7d..1158324567ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java @@ -23,6 +23,7 @@ public interface RotationLockController extends Listenable, int getRotationLockOrientation(); boolean isRotationLockAffordanceVisible(); boolean isRotationLocked(); + boolean isCameraRotationEnabled(); void setRotationLocked(boolean locked); void setRotationLockedAtAngle(boolean locked, int rotation); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java index 53d68d0ff0ac..c185928998c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java @@ -18,11 +18,13 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.os.UserHandle; +import android.provider.Settings.Secure; import androidx.annotation.NonNull; import com.android.internal.view.RotationPolicy; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.util.settings.SecureSettings; import java.util.concurrent.CopyOnWriteArrayList; @@ -32,20 +34,22 @@ import javax.inject.Inject; @SysUISingleton public final class RotationLockControllerImpl implements RotationLockController { private final Context mContext; + private final SecureSettings mSecureSettings; private final CopyOnWriteArrayList<RotationLockControllerCallback> mCallbacks = new CopyOnWriteArrayList<RotationLockControllerCallback>(); private final RotationPolicy.RotationPolicyListener mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() { - @Override - public void onChange() { - notifyChanged(); - } - }; + @Override + public void onChange() { + notifyChanged(); + } + }; @Inject - public RotationLockControllerImpl(Context context) { + public RotationLockControllerImpl(Context context, SecureSettings secureSettings) { mContext = context; + mSecureSettings = secureSettings; setListening(true); } @@ -68,11 +72,16 @@ public final class RotationLockControllerImpl implements RotationLockController return RotationPolicy.isRotationLocked(mContext); } + public boolean isCameraRotationEnabled() { + return mSecureSettings.getIntForUser(Secure.CAMERA_AUTOROTATE, 0, UserHandle.USER_CURRENT) + == 1; + } + public void setRotationLocked(boolean locked) { RotationPolicy.setRotationLock(mContext, locked); } - public void setRotationLockedAtAngle(boolean locked, int rotation){ + public void setRotationLockedAtAngle(boolean locked, int rotation) { RotationPolicy.setRotationLockAtAngle(mContext, locked, rotation); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 41b1dd12639a..4e33529f3c36 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -628,7 +628,7 @@ public class SmartReplyView extends ViewGroup { mCurrentBackgroundColor = backgroundColor; mCurrentColorized = colorized; - final boolean dark = !ContrastColorUtil.isColorLight(backgroundColor); + final boolean dark = Notification.Builder.isColorDark(backgroundColor); mCurrentTextColor = ContrastColorUtil.ensureTextContrast( dark ? mDefaultTextColorDarkBg : mDefaultTextColor, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt new file mode 100644 index 000000000000..ae9d9ee445f2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt @@ -0,0 +1,79 @@ +/* + * 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.statusbar.policy + +import android.content.Context +import android.text.StaticLayout +import android.util.AttributeSet +import android.widget.TextView +import com.android.systemui.R + +/** + * View for showing a date that can toggle between two different formats depending on size. + * + * If no pattern can fit, it will display empty. + * + * @see R.styleable.VariableDateView_longDatePattern + * @see R.styleable.VariableDateView_shortDatePattern + */ +class VariableDateView(context: Context, attrs: AttributeSet) : TextView(context, attrs) { + + val longerPattern: String + val shorterPattern: String + + init { + val a = context.theme.obtainStyledAttributes( + attrs, + R.styleable.VariableDateView, + 0, 0) + longerPattern = a.getString(R.styleable.VariableDateView_longDatePattern) + ?: context.getString(R.string.system_ui_date_pattern) + shorterPattern = a.getString(R.styleable.VariableDateView_shortDatePattern) + ?: context.getString(R.string.abbrev_month_day_no_year) + + a.recycle() + } + + /** + * Freeze the pattern switching + * + * Use during animations if the container will change its size but this view should not change + */ + var freezeSwitching = false + + private var onMeasureListener: OnMeasureListener? = null + + fun onAttach(listener: OnMeasureListener?) { + onMeasureListener = listener + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val availableWidth = MeasureSpec.getSize(widthMeasureSpec) - paddingStart - paddingEnd + if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED && !freezeSwitching) { + onMeasureListener?.onMeasureAction(availableWidth) + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + } + + fun getDesiredWidthForText(text: CharSequence): Float { + return StaticLayout.getDesiredWidth(text, paint) + } + + interface OnMeasureListener { + fun onMeasureAction(availableWidth: Int) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt new file mode 100644 index 000000000000..99d84c4d0ced --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt @@ -0,0 +1,221 @@ +/* + * 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.statusbar.policy + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.icu.text.DateFormat +import android.icu.text.DisplayContext +import android.icu.util.Calendar +import android.os.Handler +import android.os.HandlerExecutor +import android.os.UserHandle +import android.text.TextUtils +import android.util.Log +import androidx.annotation.VisibleForTesting +import com.android.systemui.Dependency +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.util.ViewController +import com.android.systemui.util.time.SystemClock +import java.text.FieldPosition +import java.text.ParsePosition +import java.util.Date +import java.util.Locale +import javax.inject.Inject +import javax.inject.Named + +@VisibleForTesting +internal fun getTextForFormat(date: Date?, format: DateFormat): String { + return if (format === EMPTY_FORMAT) { // Check if same object + "" + } else format.format(date) +} + +@VisibleForTesting +internal fun getFormatFromPattern(pattern: String?): DateFormat { + if (TextUtils.equals(pattern, "")) { + return EMPTY_FORMAT + } + val l = Locale.getDefault() + val format = DateFormat.getInstanceForSkeleton(pattern, l) + format.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE) + return format +} + +private val EMPTY_FORMAT: DateFormat = object : DateFormat() { + override fun format( + cal: Calendar, + toAppendTo: StringBuffer, + fieldPosition: FieldPosition + ): StringBuffer? { + return null + } + + override fun parse(text: String, cal: Calendar, pos: ParsePosition) {} +} + +private const val DEBUG = false +private const val TAG = "VariableDateViewController" + +class VariableDateViewController( + private val systemClock: SystemClock, + private val broadcastDispatcher: BroadcastDispatcher, + private val timeTickHandler: Handler, + view: VariableDateView +) : ViewController<VariableDateView>(view) { + + private var dateFormat: DateFormat? = null + private var datePattern = view.longerPattern + set(value) { + if (field == value) return + field = value + dateFormat = null + if (isAttachedToWindow) { + post(::updateClock) + } + } + private var lastWidth = Integer.MAX_VALUE + private var lastText = "" + private var currentTime = Date() + + // View class easy accessors + private val longerPattern: String + get() = mView.longerPattern + private val shorterPattern: String + get() = mView.shorterPattern + private fun post(block: () -> Unit) = mView.handler?.post(block) + + private val intentReceiver: BroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + // If the handler is null, it means we received a broadcast while the view has not + // finished being attached or in the process of being detached. + // In that case, do not post anything. + val handler = mView.handler ?: return + val action = intent.action + if ( + Intent.ACTION_TIME_TICK == action || + Intent.ACTION_TIME_CHANGED == action || + Intent.ACTION_TIMEZONE_CHANGED == action || + Intent.ACTION_LOCALE_CHANGED == action + ) { + if ( + Intent.ACTION_LOCALE_CHANGED == action || + Intent.ACTION_TIMEZONE_CHANGED == action + ) { + // need to get a fresh date format + handler.post { dateFormat = null } + } + handler.post(::updateClock) + } + } + } + + private val onMeasureListener = object : VariableDateView.OnMeasureListener { + override fun onMeasureAction(availableWidth: Int) { + if (availableWidth != lastWidth) { + // maybeChangeFormat will post if the pattern needs to change. + maybeChangeFormat(availableWidth) + lastWidth = availableWidth + } + } + } + + override fun onViewAttached() { + val filter = IntentFilter().apply { + addAction(Intent.ACTION_TIME_TICK) + addAction(Intent.ACTION_TIME_CHANGED) + addAction(Intent.ACTION_TIMEZONE_CHANGED) + addAction(Intent.ACTION_LOCALE_CHANGED) + } + + broadcastDispatcher.registerReceiver(intentReceiver, filter, + HandlerExecutor(timeTickHandler), UserHandle.SYSTEM) + + post(::updateClock) + mView.onAttach(onMeasureListener) + } + + override fun onViewDetached() { + dateFormat = null + mView.onAttach(null) + broadcastDispatcher.unregisterReceiver(intentReceiver) + } + + private fun updateClock() { + if (dateFormat == null) { + dateFormat = getFormatFromPattern(datePattern) + } + + currentTime.time = systemClock.currentTimeMillis() + + val text = getTextForFormat(currentTime, dateFormat!!) + if (text != lastText) { + mView.setText(text) + lastText = text + } + } + + private fun maybeChangeFormat(availableWidth: Int) { + if (mView.freezeSwitching || + availableWidth > lastWidth && datePattern == longerPattern || + availableWidth < lastWidth && datePattern == "" + ) { + // Nothing to do + return + } + if (DEBUG) Log.d(TAG, "Width changed. Maybe changing pattern") + // Start with longer pattern and see what fits + var text = getTextForFormat(currentTime, getFormatFromPattern(longerPattern)) + var length = mView.getDesiredWidthForText(text) + if (length <= availableWidth) { + changePattern(longerPattern) + return + } + + text = getTextForFormat(currentTime, getFormatFromPattern(shorterPattern)) + length = mView.getDesiredWidthForText(text) + if (length <= availableWidth) { + changePattern(shorterPattern) + return + } + + changePattern("") + } + + private fun changePattern(newPattern: String) { + if (newPattern.equals(datePattern)) return + if (DEBUG) Log.d(TAG, "Changing pattern to $newPattern") + datePattern = newPattern + } + + class Factory @Inject constructor( + private val systemClock: SystemClock, + private val broadcastDispatcher: BroadcastDispatcher, + @Named(Dependency.TIME_TICK_HANDLER_NAME) private val handler: Handler + ) { + fun create(view: VariableDateView): VariableDateViewController { + return VariableDateViewController( + systemClock, + broadcastDispatcher, + handler, + view + ) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java index c3b4fbe9a13d..e2d0bb9991ed 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java @@ -132,14 +132,18 @@ public class ThemeOverlayApplier implements Dumpable { /* Target package for each overlay category. */ private final Map<String, String> mCategoryToTargetPackage = new ArrayMap<>(); private final OverlayManager mOverlayManager; - private final Executor mExecutor; + private final Executor mBgExecutor; + private final Executor mMainExecutor; private final String mLauncherPackage; private final String mThemePickerPackage; - public ThemeOverlayApplier(OverlayManager overlayManager, Executor executor, + public ThemeOverlayApplier(OverlayManager overlayManager, + Executor bgExecutor, + Executor mainExecutor, String launcherPackage, String themePickerPackage, DumpManager dumpManager) { mOverlayManager = overlayManager; - mExecutor = executor; + mBgExecutor = bgExecutor; + mMainExecutor = mainExecutor; mLauncherPackage = launcherPackage; mThemePickerPackage = themePickerPackage; mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet( @@ -170,12 +174,12 @@ public class ThemeOverlayApplier implements Dumpable { * Apply the set of overlay packages to the set of {@code UserHandle}s provided. Overlays that * affect sysui will also be applied to the system user. */ - void applyCurrentUserOverlays( + public void applyCurrentUserOverlays( Map<String, OverlayIdentifier> categoryToPackage, FabricatedOverlay[] pendingCreation, int currentUser, Set<UserHandle> managedProfiles) { - mExecutor.execute(() -> { + mBgExecutor.execute(() -> { // Disable all overlays that have not been specified in the user setting. final Set<String> overlayCategoriesToDisable = new HashSet<>(THEME_CATEGORIES); diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java index 98b4209ede00..bfa50bcee270 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java @@ -36,6 +36,7 @@ import android.os.UserHandle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.WindowManager; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.TextView; @@ -63,6 +64,8 @@ public class UsbPermissionActivity extends AlertActivity public void onCreate(Bundle icicle) { super.onCreate(icicle); + getWindow().addPrivateFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java index de5a3637fe9f..14190fa752c3 100644 --- a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java +++ b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java @@ -23,8 +23,9 @@ import android.content.IntentFilter; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; -import android.util.SparseArray; +import android.util.SparseBooleanArray; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; @@ -34,39 +35,54 @@ import javax.inject.Inject; */ @SysUISingleton public class CarrierConfigTracker extends BroadcastReceiver { - private final SparseArray<Boolean> mCallStrengthConfigs = new SparseArray<>(); - private final SparseArray<Boolean> mNoCallingConfigs = new SparseArray<>(); + private final SparseBooleanArray mCallStrengthConfigs = new SparseBooleanArray(); + private final SparseBooleanArray mNoCallingConfigs = new SparseBooleanArray(); + private final SparseBooleanArray mCarrierProvisionsWifiMergedNetworks = + new SparseBooleanArray(); private final CarrierConfigManager mCarrierConfigManager; private boolean mDefaultCallStrengthConfigLoaded; private boolean mDefaultCallStrengthConfig; private boolean mDefaultNoCallingConfigLoaded; private boolean mDefaultNoCallingConfig; + private boolean mDefaultCarrierProvisionsWifiMergedNetworksLoaded; + private boolean mDefaultCarrierProvisionsWifiMergedNetworks; @Inject - public CarrierConfigTracker(Context context) { + public CarrierConfigTracker(Context context, BroadcastDispatcher broadcastDispatcher) { mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); - context.registerReceiver( + broadcastDispatcher.registerReceiver( this, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); } @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction() == CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED) { - int subId = intent.getIntExtra( - CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, - SubscriptionManager.INVALID_SUBSCRIPTION_ID); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return; - } - PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId); - if (b != null) { - boolean hideNoCallingConfig = b.getBoolean( - CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL); - boolean displayCallStrengthIcon = b.getBoolean( - CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL); - mCallStrengthConfigs.put(subId, displayCallStrengthIcon); - mNoCallingConfigs.put(subId, hideNoCallingConfig); - } + if (!CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { + return; + } + + final int subId = intent.getIntExtra( + CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (!SubscriptionManager.isValidSubscriptionId(subId)) { + return; + } + + final PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId); + if (config == null) { + return; + } + + synchronized (mCallStrengthConfigs) { + mCallStrengthConfigs.put(subId, config.getBoolean( + CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL)); + } + synchronized (mNoCallingConfigs) { + mNoCallingConfigs.put(subId, config.getBoolean( + CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL)); + } + synchronized (mCarrierProvisionsWifiMergedNetworks) { + mCarrierProvisionsWifiMergedNetworks.put(subId, config.getBoolean( + CarrierConfigManager.KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL)); } } @@ -74,8 +90,10 @@ public class CarrierConfigTracker extends BroadcastReceiver { * Returns the KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL value for the given subId. */ public boolean getCallStrengthConfig(int subId) { - if (mCallStrengthConfigs.indexOfKey(subId) >= 0) { - return mCallStrengthConfigs.get(subId); + synchronized (mCallStrengthConfigs) { + if (mCallStrengthConfigs.indexOfKey(subId) >= 0) { + return mCallStrengthConfigs.get(subId); + } } if (!mDefaultCallStrengthConfigLoaded) { mDefaultCallStrengthConfig = @@ -90,8 +108,10 @@ public class CarrierConfigTracker extends BroadcastReceiver { * Returns the KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL value for the given subId. */ public boolean getNoCallingConfig(int subId) { - if (mNoCallingConfigs.indexOfKey(subId) >= 0) { - return mNoCallingConfigs.get(subId); + synchronized (mNoCallingConfigs) { + if (mNoCallingConfigs.indexOfKey(subId) >= 0) { + return mNoCallingConfigs.get(subId); + } } if (!mDefaultNoCallingConfigLoaded) { mDefaultNoCallingConfig = @@ -101,4 +121,22 @@ public class CarrierConfigTracker extends BroadcastReceiver { } return mDefaultNoCallingConfig; } + + /** + * Returns the KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL value for the given subId. + */ + public boolean getCarrierProvisionsWifiMergedNetworksBool(int subId) { + synchronized (mCarrierProvisionsWifiMergedNetworks) { + if (mCarrierProvisionsWifiMergedNetworks.indexOfKey(subId) >= 0) { + return mCarrierProvisionsWifiMergedNetworks.get(subId); + } + } + if (!mDefaultCarrierProvisionsWifiMergedNetworksLoaded) { + mDefaultCarrierProvisionsWifiMergedNetworks = + CarrierConfigManager.getDefaultConfig().getBoolean( + CarrierConfigManager.KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL); + mDefaultCarrierProvisionsWifiMergedNetworksLoaded = true; + } + return mDefaultCarrierProvisionsWifiMergedNetworks; + } } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index 90e022a52d7a..bd1103982017 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -87,15 +87,23 @@ public class ProximitySensor implements ThresholdSensor { && (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow() || !event.getBelow())) { - mSecondaryThresholdSensor.pause(); + chooseSensor(); if (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow()) { // Only check the secondary as long as the primary thinks we're near. - mCancelSecondaryRunnable = null; + if (mCancelSecondaryRunnable != null) { + mCancelSecondaryRunnable.run(); + mCancelSecondaryRunnable = null; + } return; } else { // Check this sensor again in a moment. - mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed( - mSecondaryThresholdSensor::resume, SECONDARY_PING_INTERVAL_MS); + mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(() -> { + // This is safe because we know that mSecondaryThresholdSensor + // is loaded, otherwise we wouldn't be here. + mPrimaryThresholdSensor.pause(); + mSecondaryThresholdSensor.resume(); + }, + SECONDARY_PING_INTERVAL_MS); } } logDebug("Secondary sensor event: " + event.getBelow() + "."); @@ -159,12 +167,8 @@ public class ProximitySensor implements ThresholdSensor { * of what is reported by the primary sensor. */ public void setSecondarySafe(boolean safe) { - mSecondarySafe = safe; - if (!mSecondarySafe) { - mSecondaryThresholdSensor.pause(); - } else { - mSecondaryThresholdSensor.resume(); - } + mSecondarySafe = mSecondaryThresholdSensor.isLoaded() && safe; + chooseSensor(); } /** @@ -209,16 +213,30 @@ public class ProximitySensor implements ThresholdSensor { return; } if (!mInitializedListeners) { + mPrimaryThresholdSensor.pause(); + mSecondaryThresholdSensor.pause(); mPrimaryThresholdSensor.register(mPrimaryEventListener); - if (!mSecondarySafe) { - mSecondaryThresholdSensor.pause(); - } mSecondaryThresholdSensor.register(mSecondaryEventListener); mInitializedListeners = true; } logDebug("Registering sensor listener"); - mPrimaryThresholdSensor.resume(); + mRegistered = true; + chooseSensor(); + } + + private void chooseSensor() { + mExecution.assertIsMainThread(); + if (!mRegistered || mPaused || mListeners.isEmpty()) { + return; + } + if (mSecondarySafe) { + mSecondaryThresholdSensor.resume(); + mPrimaryThresholdSensor.pause(); + } else { + mPrimaryThresholdSensor.resume(); + mSecondaryThresholdSensor.pause(); + } } /** @@ -312,7 +330,7 @@ public class ProximitySensor implements ThresholdSensor { } if (!mSecondarySafe && !event.getBelow()) { - mSecondaryThresholdSensor.pause(); + chooseSensor(); } mLastEvent = event; diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java index 2b4b49b82df1..99177778310d 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java @@ -116,7 +116,7 @@ public class WalletActivity extends LifecycleActivity implements if (toolbar != null) { setActionBar(toolbar); } - setTitle(""); + getActionBar().setDisplayShowTitleEnabled(false); getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeAsUpIndicator(getHomeIndicatorDrawable()); getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close); @@ -220,6 +220,12 @@ public class WalletActivity extends LifecycleActivity implements } @Override + protected void onStop() { + super.onStop(); + finish(); + } + + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.wallet_activity_options_menu, menu); return super.onCreateOptionsMenu(menu); diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index 62070422cc48..df670cf16477 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -94,6 +94,13 @@ <activity android:name="com.android.systemui.screenshot.RecyclerViewActivity" android:exported="false" /> + <!-- started from UsbDeviceSettingsManager --> + <activity android:name=".usb.UsbPermissionActivityTest$UsbPermissionActivityTestable" + android:exported="false" + android:theme="@style/Theme.SystemUI.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true" /> + <provider android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer" tools:replace="android:authorities" diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 06b0bb25e01c..8077deaf5fda 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -119,6 +119,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { when(mNotificationIcons.getLayoutParams()).thenReturn( mock(RelativeLayout.LayoutParams.class)); when(mView.getContext()).thenReturn(getContext()); + when(mView.getResources()).thenReturn(mResources); when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView); when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView); @@ -127,7 +128,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { when(mLargeClockView.getContext()).thenReturn(getContext()); when(mView.isAttachedToWindow()).thenReturn(true); - when(mResources.getString(anyInt())).thenReturn("h:mm"); when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView); mController = new KeyguardClockSwitchController( mView, @@ -142,7 +142,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mBypassController, mSmartspaceController, mKeyguardUnlockAnimationController, - mSmartSpaceTransitionController + mSmartSpaceTransitionController, + mResources ); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index 39d5314107ee..8dd5d6c01394 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -565,8 +565,9 @@ public class AuthControllerTest extends SysuiTestCase { credentialAllowed, true /* requireConfirmation */, 0 /* userId */, - "testPackage", 0 /* operationId */, + "testPackage", + 1 /* requestId */, BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT); } @@ -612,7 +613,7 @@ public class AuthControllerTest extends SysuiTestCase { @Override protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds, boolean credentialAllowed, - String opPackageName, boolean skipIntro, long operationId, + String opPackageName, boolean skipIntro, long operationId, long requestId, @BiometricManager.BiometricMultiSensorMode int multiSensorConfig) { mLastBiometricPromptInfo = promptInfo; 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 1a390170c736..04ebee8913c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.biometrics; +import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY; + import static junit.framework.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -55,7 +57,6 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -63,12 +64,14 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.Execution; 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; @@ -120,8 +123,6 @@ public class UdfpsControllerTest extends SysuiTestCase { @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock - private KeyguardViewMediator mKeyguardViewMediator; - @Mock private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback; @Mock private FalsingManager mFalsingManager; @@ -147,6 +148,10 @@ public class UdfpsControllerTest extends SysuiTestCase { private Handler mHandler; @Mock private ConfigurationController mConfigurationController; + @Mock + private SystemClock mSystemClock; + @Mock + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private FakeExecutor mFgExecutor; @@ -186,6 +191,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mLayoutInflater.inflate(R.layout.udfps_keyguard_view, null)) .thenReturn(mKeyguardView); // for showOverlay REASON_AUTH_FPM_KEYGUARD when(mEnrollView.getContext()).thenReturn(mContext); + when(mKeyguardStateController.isOccluded()).thenReturn(false); final List<FingerprintSensorPropertiesInternal> props = new ArrayList<>(); final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); @@ -216,7 +222,6 @@ public class UdfpsControllerTest extends SysuiTestCase { mStatusBarKeyguardViewManager, mDumpManager, mKeyguardUpdateMonitor, - mKeyguardViewMediator, mFalsingManager, mPowerManager, mAccessibilityManager, @@ -229,7 +234,9 @@ public class UdfpsControllerTest extends SysuiTestCase { mKeyguardBypassController, mDisplayManager, mHandler, - mConfigurationController); + mConfigurationController, + mSystemClock, + mUnlockedScreenOffAnimationController); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -413,6 +420,21 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test + public void hideUdfpsOverlay_resetsAltAuthBouncerWhenShowing() throws RemoteException { + // GIVEN overlay was showing and the udfps bouncer is showing + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); + when(mStatusBarKeyguardViewManager.isShowingAlternateAuth()).thenReturn(true); + + // WHEN the overlay is hidden + mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID); + mFgExecutor.runAllReady(); + + // THEN the udfps bouncer is reset + verify(mStatusBarKeyguardViewManager).resetAlternateAuth(eq(true)); + } + + @Test public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception { mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); @@ -564,5 +586,10 @@ public class UdfpsControllerTest extends SysuiTestCase { eq(mUdfpsController.EFFECT_CLICK), eq("udfps-onStart"), eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES)); + + // THEN make sure vibration attributes has so that it always will play the haptic, + // even in battery saver mode + assertEquals(USAGE_ASSISTANCE_ACCESSIBILITY, + UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES.getUsage()); } } 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 0fbf9af159a6..4b35de15147b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java @@ -18,9 +18,9 @@ package com.android.systemui.biometrics; 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.reset; @@ -43,9 +43,11 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; @@ -88,7 +90,10 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { @Mock private ConfigurationController mConfigurationController; @Mock + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Mock private UdfpsController mUdfpsController; + private FakeSystemClock mSystemClock = new FakeSystemClock(); private UdfpsKeyguardViewController mController; @@ -119,12 +124,12 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { mStatusBar, mStatusBarKeyguardViewManager, mKeyguardUpdateMonitor, - mExecutor, mDumpManager, - mKeyguardViewMediator, mLockscreenShadeTransitionController, mConfigurationController, + mSystemClock, mKeyguardStateController, + mUnlockedScreenOffAnimationController, mUdfpsController); } @@ -299,6 +304,59 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { } @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()); + } + + @Test public void testFadeInWithStatusBarExpansion() { // GIVEN view is attached mController.onViewAttached(); @@ -395,6 +453,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { mAltAuthInterceptor = mAltAuthInterceptorCaptor.getValue(); } + + private void captureKeyguardStateControllerCallback() { verify(mKeyguardStateController).addCallback( mKeyguardStateControllerCallbackCaptor.capture()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 81bae0bd6dd1..b8d465a8c881 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -18,6 +18,7 @@ package com.android.systemui.doze; import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; +import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING; import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE; @@ -29,6 +30,7 @@ import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -42,11 +44,11 @@ import android.os.PowerManager; import android.os.UserHandle; import android.provider.Settings; import android.testing.AndroidTestingRunner; -import android.view.Display; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; @@ -84,6 +86,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { @Mock DozeParameters mDozeParameters; @Mock + DockManager mDockManager; + @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor); @@ -112,9 +116,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor = fakeSensorManager.getFakeLightSensor(); mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.of(mSensor.getSensor()), mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, mUnlockedScreenOffAnimationController); - mScreen.onScreenState(Display.STATE_ON); } @Test @@ -126,18 +129,9 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void testAod_usesLightSensor() { - mScreen.onScreenState(Display.STATE_DOZE); - waitForSensorManager(); - - mSensor.sendSensorEvent(3); - - assertEquals(3, mServiceFake.screenBrightness); - } - - @Test public void testAod_usesDebugValue() throws Exception { - mScreen.onScreenState(Display.STATE_DOZE); + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); waitForSensorManager(); Intent intent = new Intent(DozeScreenBrightness.ACTION_AOD_BRIGHTNESS); @@ -160,10 +154,53 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test + public void doze_doesNotUseLightSensor() { + // GIVEN the device is docked and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is NOT changed, it's set to the default brightness + assertNotSame(3, mServiceFake.screenBrightness); + assertEquals(DEFAULT_BRIGHTNESS, mServiceFake.screenBrightness); + } + + @Test + public void aod_usesLightSensor() { + // GIVEN the device is docked and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is updated + assertEquals(3, mServiceFake.screenBrightness); + } + + @Test + public void docked_usesLightSensor() { + // GIVEN the device is docked and the display state changes to ON + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_DOCKED); + waitForSensorManager(); + + // WHEN new sensor event sent + mSensor.sendSensorEvent(3); + + // THEN brightness is updated + assertEquals(3, mServiceFake.screenBrightness); + } + + @Test public void testPausingAod_doesNotResetBrightness() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); waitForSensorManager(); mSensor.sendSensorEvent(1); @@ -178,7 +215,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -205,37 +242,22 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void testOnScreenStateSetBeforeTransition_stillRegistersSensor() { - mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.onScreenState(Display.STATE_DOZE); - mScreen.transitionTo(INITIALIZED, DOZE_AOD); - waitForSensorManager(); - - mSensor.sendSensorEvent(1); - - assertEquals(1, mServiceFake.screenBrightness); - } - - @Test public void testNullSensor() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING); mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED); - mScreen.onScreenState(Display.STATE_DOZE); - mScreen.onScreenState(Display.STATE_OFF); } @Test public void testNoBrightnessDeliveredAfterFinish() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); mScreen.transitionTo(DOZE_AOD, FINISH); waitForSensorManager(); @@ -248,7 +270,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); waitForSensorManager(); mSensor.sendSensorEvent(1); @@ -262,7 +283,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void pausingAod_unblanksAfterSensor() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); waitForSensorManager(); mSensor.sendSensorEvent(2); @@ -274,7 +294,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { reset(mDozeHost); mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); waitForSensorManager(); mSensor.sendSensorEvent(2); verify(mDozeHost).setAodDimmingScrim(eq(0f)); @@ -284,7 +303,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void pausingAod_unblanksIfSensorWasAlwaysReady() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mScreen.onScreenState(Display.STATE_DOZE); waitForSensorManager(); mSensor.sendSensorEvent(2); @@ -301,13 +319,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); // If we're dozing after a timeout, and playing the unlocked screen animation, we should - // stay at dim brightness, because the screen dims just before timeout. - assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS); + // stay at or below dim brightness, because the screen dims just before timeout. + assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); } @Test @@ -315,6 +334,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -329,6 +349,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 0c94f09c8572..5c4c27ccc4ca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -88,7 +88,7 @@ public class DozeSensorsTest extends SysuiTestCase { private FakeSettings mFakeSettings = new FakeSettings(); private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener; private TestableLooper mTestableLooper; - private DozeSensors mDozeSensors; + private TestableDozeSensors mDozeSensors; private TriggerSensor mSensorTap; @Before @@ -170,6 +170,94 @@ public class DozeSensorsTest extends SysuiTestCase { assertTrue(mSensorTap.mRequested); } + @Test + public void testDozeSensorSetListening() { + // GIVEN doze sensors enabled + when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true); + + // GIVEN a trigger sensor + Sensor mockSensor = mock(Sensor.class); + TriggerSensor triggerSensor = mDozeSensors.createDozeSensor( + mockSensor, + /* settingEnabled */ true, + /* requiresTouchScreen */ true); + when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor))) + .thenReturn(true); + + // WHEN we want to listen for the trigger sensor + triggerSensor.setListening(true); + + // THEN the sensor is registered + assertTrue(triggerSensor.mRegistered); + } + + @Test + public void testDozeSensorSettingDisabled() { + // GIVEN doze sensors enabled + when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true); + + // GIVEN a trigger sensor + Sensor mockSensor = mock(Sensor.class); + TriggerSensor triggerSensor = mDozeSensors.createDozeSensor( + mockSensor, + /* settingEnabled*/ false, + /* requiresTouchScreen */ true); + when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor))) + .thenReturn(true); + + // WHEN setListening is called + triggerSensor.setListening(true); + + // THEN the sensor is not registered + assertFalse(triggerSensor.mRegistered); + } + + @Test + public void testDozeSensorIgnoreSetting() { + // GIVEN doze sensors enabled + when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true); + + // GIVEN a trigger sensor that's + Sensor mockSensor = mock(Sensor.class); + TriggerSensor triggerSensor = mDozeSensors.createDozeSensor( + mockSensor, + /* settingEnabled*/ false, + /* requiresTouchScreen */ true); + when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor))) + .thenReturn(true); + + // GIVEN sensor is listening + triggerSensor.setListening(true); + + // WHEN ignoreSetting is called + triggerSensor.ignoreSetting(true); + + // THEN the sensor is registered + assertTrue(triggerSensor.mRegistered); + } + + @Test + public void testUpdateListeningAfterAlreadyRegistered() { + // GIVEN doze sensors enabled + when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true); + + // GIVEN a trigger sensor + Sensor mockSensor = mock(Sensor.class); + TriggerSensor triggerSensor = mDozeSensors.createDozeSensor( + mockSensor, + /* settingEnabled*/ true, + /* requiresTouchScreen */ true); + when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor))) + .thenReturn(true); + + // WHEN setListening is called AND updateListening is called + triggerSensor.setListening(true); + triggerSensor.updateListening(); + + // THEN the sensor is still registered + assertTrue(triggerSensor.mRegistered); + } + private class TestableDozeSensors extends DozeSensors { TestableDozeSensors() { @@ -187,5 +275,17 @@ public class DozeSensorsTest extends SysuiTestCase { } mSensors = new TriggerSensor[] {mTriggerSensor, mSensorTap}; } + + public TriggerSensor createDozeSensor(Sensor sensor, boolean settingEnabled, + boolean requiresTouchScreen) { + return new TriggerSensor(/* sensor */ sensor, + /* setting name */ "test_setting", + /* settingDefault */ settingEnabled, + /* configured */ true, + /* pulseReason*/ 0, + /* reportsTouchCoordinate*/ false, + requiresTouchScreen, + mDozeLog); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 10997fab081f..9577c7a2d6fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -45,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeThreadFactory; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -83,6 +84,8 @@ public class DozeTriggersTest extends SysuiTestCase { private AuthController mAuthController; @Mock private UiEventLogger mUiEventLogger; + @Mock + private KeyguardStateController mKeyguardStateController; private DozeTriggers mTriggers; private FakeSensorManager mSensors; @@ -114,7 +117,7 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters, asyncSensorManager, wakeLock, mDockManager, mProximitySensor, mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(), - mAuthController, mExecutor, mUiEventLogger); + mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController); mTriggers.setDozeMachine(mMachine); waitForSensorManager(); } @@ -217,6 +220,32 @@ public class DozeTriggersTest extends SysuiTestCase { } @Test + public void testPickupGesture() { + // GIVEN device is in doze (screen blank, but running doze sensors) + when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE); + + // WHEN the pick up gesture is triggered and keyguard isn't occluded + when(mKeyguardStateController.isOccluded()).thenReturn(false); + mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null); + + // THEN wakeup + verify(mMachine).wakeUp(); + } + + @Test + public void testPickupGestureDroppedKeyguardOccluded() { + // GIVEN device is in doze (screen blank, but running doze sensors) + when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE); + + // WHEN the pick up gesture is triggered and keyguard IS occluded + when(mKeyguardStateController.isOccluded()).thenReturn(true); + mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null); + + // THEN never wakeup + verify(mMachine, never()).wakeUp(); + } + + @Test public void testOnSensor_Fingerprint() { // GIVEN dozing state when(mMachine.getState()).thenReturn(DOZE_AOD); 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 578c2d976cce..509ef82ee426 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 com.google.common.truth.Truth.assertThat; 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.MetricsLogger; 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 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { @Mock private Handler mHandler; @Mock private UserContextProvider mUserContextProvider; @Mock private StatusBar mStatusBar; + @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private TestableLooper mTestableLooper; @@ -156,7 +159,8 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { mSysUiState, mHandler, mPackageManager, - mStatusBar + mStatusBar, + mKeyguardUpdateMonitor ); mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting(); @@ -422,4 +426,31 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { 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 = { + GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY, + GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN, + GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER, + GlobalActionsDialog.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 2fa67cc0be60..338bb3037331 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.MetricsLogger; 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; @@ -126,6 +127,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase { @Mock private PackageManager mPackageManager; @Mock private SecureSettings mSecureSettings; @Mock private StatusBar mStatusBar; + @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private TestableLooper mTestableLooper; @@ -169,7 +171,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase { mSysUiState, mHandler, mPackageManager, - mStatusBar + mStatusBar, + mKeyguardUpdateMonitor ); mGlobalActionsDialog.setZeroDialogPressDelayForTesting(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java new file mode 100644 index 000000000000..df112840ed87 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java @@ -0,0 +1,144 @@ +/* + * 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.keyguard; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.res.Resources; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.View; + +import androidx.test.filters.SmallTest; + +import com.android.keyguard.AnimatableClockController; +import com.android.keyguard.AnimatableClockView; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.settingslib.Utils; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.policy.BatteryController; + +import org.junit.After; +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; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class AnimatableClockControllerTest extends SysuiTestCase { + @Mock + private AnimatableClockView mClockView; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; + @Mock + private BatteryController mBatteryController; + @Mock + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock + private KeyguardBypassController mBypassController; + @Mock + private Resources mResources; + + private MockitoSession mStaticMockSession; + private AnimatableClockController mAnimatableClockController; + + // Capture listeners so that they can be used to send events + @Captor private ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor = + ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class); + private View.OnAttachStateChangeListener mAttachListener; + + @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateCaptor; + private StatusBarStateController.StateListener mStatusBarStateCallback; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mStaticMockSession = mockitoSession() + .mockStatic(Utils.class) + .strictness(Strictness.LENIENT) // it's ok if mocked classes aren't used + .startMocking(); + when(Utils.getColorAttrDefaultColor(anyObject(), anyInt())).thenReturn(0); + + mAnimatableClockController = new AnimatableClockController( + mClockView, + mStatusBarStateController, + mBroadcastDispatcher, + mBatteryController, + mKeyguardUpdateMonitor, + mBypassController, + mResources + ); + mAnimatableClockController.init(); + captureAttachListener(); + } + + @After + public void tearDown() { + mStaticMockSession.finishMocking(); + } + + @Test + public void testOnAttachedUpdatesDozeStateToTrue() { + // GIVEN dozing + when(mStatusBarStateController.isDozing()).thenReturn(true); + when(mStatusBarStateController.getDozeAmount()).thenReturn(1f); + + // WHEN the clock view gets attached + mAttachListener.onViewAttachedToWindow(mClockView); + + // THEN the clock controller updated its dozing state to true + assertTrue(mAnimatableClockController.isDozing()); + } + + @Test + public void testOnAttachedUpdatesDozeStateToFalse() { + // GIVEN not dozing + when(mStatusBarStateController.isDozing()).thenReturn(false); + when(mStatusBarStateController.getDozeAmount()).thenReturn(0f); + + // WHEN the clock view gets attached + mAttachListener.onViewAttachedToWindow(mClockView); + + // THEN the clock controller updated its dozing state to false + assertFalse(mAnimatableClockController.isDozing()); + } + + private void captureAttachListener() { + verify(mClockView).addOnAttachStateChangeListener(mAttachCaptor.capture()); + mAttachListener = mAttachCaptor.getValue(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 1dacc6245d84..31d70f5c811f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; 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.mock; import static org.mockito.Mockito.never; @@ -33,8 +34,9 @@ import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.os.PowerManager; import android.os.PowerManager.WakeLock; +import android.telephony.TelephonyManager; import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper.RunWithLooper; +import android.testing.TestableLooper; import androidx.test.filters.SmallTest; @@ -65,7 +67,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) -@RunWithLooper +@TestableLooper.RunWithLooper @SmallTest public class KeyguardViewMediatorTest extends SysuiTestCase { private KeyguardViewMediator mViewMediator; @@ -160,4 +162,29 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mViewMediator.onDozeAmountChanged(1f, 1f); assertFalse(mViewMediator.isAnimatingScreenOff()); } + + @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void restoreBouncerWhenSimLockedAndKeyguardIsGoingAway() { + // When showing and provisioned + mViewMediator.onSystemReady(); + when(mUpdateMonitor.isDeviceProvisioned()).thenReturn(true); + mViewMediator.setShowingLocked(true); + + // and a SIM becomes locked and requires a PIN + mViewMediator.mUpdateCallback.onSimStateChanged( + 1 /* subId */, + 0 /* slotId */, + TelephonyManager.SIM_STATE_PIN_REQUIRED); + + // and the keyguard goes away + mViewMediator.setShowingLocked(false); + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false); + mViewMediator.mUpdateCallback.onKeyguardVisibilityChanged(false); + + TestableLooper.get(this).processAllMessages(); + + // then make sure it comes back + verify(mStatusBarKeyguardViewManager, atLeast(1)).show(null); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java index 9c3016c57ccf..9356c547db70 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java @@ -31,6 +31,7 @@ import android.os.Vibrator; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.DisplayMetrics; +import android.util.Pair; import android.view.View; import android.view.accessibility.AccessibilityManager; @@ -119,26 +120,15 @@ public class LockIconViewControllerTest extends SysuiTestCase { mAccessibilityManager, mConfigurationController, mDelayableExecutor, - mVibrator + mVibrator, + mAuthRippleController ); } @Test public void testUpdateFingerprintLocationOnInit() { // GIVEN fp sensor location is available pre-attached - final PointF udfpsLocation = new PointF(50, 75); - final int radius = 33; - final FingerprintSensorPropertiesInternal fpProps = - new FingerprintSensorPropertiesInternal( - /* sensorId */ 0, - /* strength */ 0, - /* max enrollments per user */ 5, - /* component info */ new ArrayList<>(), - /* sensorType */ 3, - /* resetLockoutRequiresHwToken */ false, - (int) udfpsLocation.x, (int) udfpsLocation.y, radius); - when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation); - when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps)); + Pair<Integer, PointF> udfps = setupUdfps(); // WHEN lock icon view controller is initialized and attached mLockIconViewController.init(); @@ -146,8 +136,8 @@ public class LockIconViewControllerTest extends SysuiTestCase { mAttachListener.onViewAttachedToWindow(mLockIconView); // THEN lock icon view location is updated with the same coordinates as fpProps - verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(radius)); - assertEquals(udfpsLocation, mPointCaptor.getValue()); + verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(udfps.first)); + assertEquals(udfps.second, mPointCaptor.getValue()); } @Test @@ -161,6 +151,47 @@ public class LockIconViewControllerTest extends SysuiTestCase { // GIVEN fp sensor location is available post-atttached captureAuthControllerCallback(); + Pair<Integer, PointF> udfps = setupUdfps(); + + // WHEN all authenticators are registered + mAuthControllerCallback.onAllAuthenticatorsRegistered(); + + // THEN lock icon view location is updated with the same coordinates as fpProps + verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(udfps.first)); + assertEquals(udfps.second, mPointCaptor.getValue()); + } + + @Test + public void testLockIconViewBackgroundEnabledWhenUdfpsIsAvailable() { + // GIVEN Udpfs sensor location is available + setupUdfps(); + + mLockIconViewController.init(); + captureAttachListener(); + + // WHEN the view is attached + mAttachListener.onViewAttachedToWindow(mLockIconView); + + // THEN the lock icon view background should be enabled + verify(mLockIconView).setUseBackground(true); + } + + @Test + public void testLockIconViewBackgroundDisabledWhenUdfpsIsUnavailable() { + // GIVEN Udfps sensor location is not available + when(mAuthController.getUdfpsSensorLocation()).thenReturn(null); + + mLockIconViewController.init(); + captureAttachListener(); + + // WHEN the view is attached + mAttachListener.onViewAttachedToWindow(mLockIconView); + + // THEN the lock icon view background should be disabled + verify(mLockIconView).setUseBackground(false); + } + + private Pair<Integer, PointF> setupUdfps() { final PointF udfpsLocation = new PointF(50, 75); final int radius = 33; final FingerprintSensorPropertiesInternal fpProps = @@ -175,12 +206,7 @@ public class LockIconViewControllerTest extends SysuiTestCase { when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation); when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps)); - // WHEN all authenticators are registered - mAuthControllerCallback.onAllAuthenticatorsRegistered(); - - // THEN lock icon view location is updated with the same coordinates as fpProps - verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(radius)); - assertEquals(udfpsLocation, mPointCaptor.getValue()); + return new Pair(radius, udfpsLocation); } private void captureAuthControllerCallback() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index b129fdd0d844..42629f545559 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -37,6 +37,7 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.LiveData import androidx.test.filters.SmallTest +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.media.dialog.MediaOutputDialogFactory import com.android.systemui.plugins.ActivityStarter @@ -101,7 +102,6 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var seamless: ViewGroup private lateinit var seamlessIcon: ImageView private lateinit var seamlessText: TextView - private lateinit var seamlessFallback: ImageView private lateinit var seekBar: SeekBar private lateinit var elapsedTimeView: TextView private lateinit var totalTimeView: TextView @@ -154,8 +154,6 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(holder.seamlessIcon).thenReturn(seamlessIcon) seamlessText = TextView(context) whenever(holder.seamlessText).thenReturn(seamlessText) - seamlessFallback = ImageView(context) - whenever(holder.seamlessFallback).thenReturn(seamlessFallback) seekBar = SeekBar(context) whenever(holder.seekBar).thenReturn(seekBar) elapsedTimeView = TextView(context) @@ -239,21 +237,19 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindDisabledDevice() { seamless.id = 1 - seamlessFallback.id = 2 + val fallbackString = context.getString(R.string.media_seamless_other_device) player.attachPlayer(holder) val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(), emptyList(), PACKAGE, session.getSessionToken(), null, disabledDevice, true, null) player.bindPlayer(state, PACKAGE) - verify(expandedSet).setVisibility(seamless.id, View.GONE) - verify(expandedSet).setVisibility(seamlessFallback.id, View.VISIBLE) - verify(collapsedSet).setVisibility(seamless.id, View.GONE) - verify(collapsedSet).setVisibility(seamlessFallback.id, View.VISIBLE) + assertThat(seamless.isEnabled()).isFalse() + assertThat(seamlessText.getText()).isEqualTo(fallbackString) + assertThat(seamless.contentDescription).isEqualTo(fallbackString) } @Test fun bindNullDevice() { - val fallbackString = context.getResources().getString( - com.android.internal.R.string.ext_media_seamless_action) + val fallbackString = context.getResources().getString(R.string.media_seamless_other_device) player.attachPlayer(holder) val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(), emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index d8791867cb45..28aed2085528 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -86,7 +86,7 @@ class MediaDataFilterTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - mediaDataFilter = MediaDataFilter(broadcastDispatcher, mediaResumeListener, + mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, mediaResumeListener, lockscreenUserManager, executor, clock) mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index ba6dfd3c453a..47c5545ab587 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -4,6 +4,7 @@ import android.app.Notification.MediaStyle import android.app.PendingIntent import android.app.smartspace.SmartspaceAction import android.app.smartspace.SmartspaceTarget +import android.content.Intent import android.graphics.Bitmap import android.media.MediaDescription import android.media.MediaMetadata @@ -51,6 +52,7 @@ private const val APP_NAME = "SystemUI" private const val SESSION_ARTIST = "artist" private const val SESSION_TITLE = "title" private const val USER_ID = 0 +private val DISMISS_INTENT = Intent().apply { action = "dismiss" } private fun <T> anyObject(): T { return Mockito.anyObject<T>() @@ -83,6 +85,7 @@ class MediaDataManagerTest : SysuiTestCase() { lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider @Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget @Mock private lateinit var mediaRecommendationItem: SmartspaceAction + @Mock private lateinit var mediaSmartspaceBaseAction: SmartspaceAction lateinit var mediaDataManager: MediaDataManager lateinit var mediaNotification: StatusBarNotification @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData> @@ -146,8 +149,12 @@ class MediaDataManagerTest : SysuiTestCase() { // treat mediaSessionBasedFilter as a listener for testing. listener = mediaSessionBasedFilter - val recommendationExtras = Bundle() - recommendationExtras.putString("package_name", PACKAGE_NAME) + val recommendationExtras = Bundle().apply { + putString("package_name", PACKAGE_NAME) + putParcelable("dismiss_intent", DISMISS_INTENT) + } + whenever(mediaSmartspaceBaseAction.extras).thenReturn(recommendationExtras) + whenever(mediaSmartspaceTarget.baseAction).thenReturn(mediaSmartspaceBaseAction) whenever(mediaRecommendationItem.extras).thenReturn(recommendationExtras) whenever(mediaSmartspaceTarget.smartspaceTargetId).thenReturn(KEY_MEDIA_SMARTSPACE) whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA) @@ -163,7 +170,7 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test - fun testSetTimedOut_deactivatesMedia() { + fun testSetTimedOut_active_deactivatesMedia() { val data = MediaData(userId = USER_ID, initialized = true, backgroundColor = 0, app = null, appIcon = null, artist = null, song = null, artwork = null, actions = emptyList(), actionsToShowInCompact = emptyList(), packageName = "INVALID", token = null, @@ -176,6 +183,25 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test + fun testSetTimedOut_resume_dismissesMedia() { + // WHEN resume controls are present, and time out + val desc = MediaDescription.Builder().run { + setTitle(SESSION_TITLE) + build() + } + mediaDataManager.addResumptionControls(USER_ID, desc, Runnable {}, session.sessionToken, + APP_NAME, pendingIntent, PACKAGE_NAME) + backgroundExecutor.runAllReady() + foregroundExecutor.runAllReady() + mediaDataManager.setTimedOut(PACKAGE_NAME, timedOut = true) + + // THEN it is removed and listeners are informed + foregroundExecutor.advanceClockToLast() + foregroundExecutor.runAllReady() + verify(listener).onMediaDataRemoved(PACKAGE_NAME) + } + + @Test fun testLoadsMetadataOnBackground() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.numPending()).isEqualTo(1) @@ -361,7 +387,8 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener).onSmartspaceMediaDataLoaded( eq(KEY_MEDIA_SMARTSPACE), eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */, - PACKAGE_NAME, null, listOf(mediaRecommendationItem), 0)), + PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem), + DISMISS_INTENT, 0)), eq(false)) } @@ -372,7 +399,8 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener).onSmartspaceMediaDataLoaded( eq(KEY_MEDIA_SMARTSPACE), eq(EMPTY_SMARTSPACE_MEDIA_DATA - .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, isValid = false)), + .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, + isValid = false, dismissIntent = DISMISS_INTENT)), eq(false)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt index 150f4545bd43..359746bca0ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt @@ -91,10 +91,12 @@ class MediaResumeListenerTest : SysuiTestCase() { @Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback> @Captor lateinit var actionCaptor: ArgumentCaptor<Runnable> + @Captor lateinit var componentCaptor: ArgumentCaptor<String> private lateinit var executor: FakeExecutor private lateinit var data: MediaData private lateinit var resumeListener: MediaResumeListener + private val clock = FakeSystemClock() private var originalQsSetting = Settings.Global.getInt(context.contentResolver, Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1) @@ -122,9 +124,9 @@ class MediaResumeListenerTest : SysuiTestCase() { whenever(mockContext.packageManager).thenReturn(context.packageManager) whenever(mockContext.contentResolver).thenReturn(context.contentResolver) - executor = FakeExecutor(FakeSystemClock()) + executor = FakeExecutor(clock) resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor, - tunerService, resumeBrowserFactory, dumpManager) + tunerService, resumeBrowserFactory, dumpManager, clock) resumeListener.setManager(mediaDataManager) mediaDataManager.addListener(resumeListener) @@ -163,7 +165,7 @@ class MediaResumeListenerTest : SysuiTestCase() { // When listener is created, we do NOT register a user change listener val listener = MediaResumeListener(context, broadcastDispatcher, executor, tunerService, - resumeBrowserFactory, dumpManager) + resumeBrowserFactory, dumpManager, clock) listener.setManager(mediaDataManager) verify(broadcastDispatcher, never()).registerReceiver(eq(listener.userChangeReceiver), any(), any(), any()) @@ -328,4 +330,109 @@ class MediaResumeListenerTest : SysuiTestCase() { // Then we call restart verify(resumeBrowser).restart() } + + @Test + fun testOnUserUnlock_missingTime_saves() { + val currentTime = clock.currentTimeMillis() + + // When resume components without a last played time are loaded + testOnUserUnlock_loadsTracks() + + // Then we save an update with the current time + verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor))) + componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex()) + ?.dropLastWhile { it.isEmpty() }.forEach { + val result = it.split("/") + assertThat(result.size).isEqualTo(3) + assertThat(result[2].toLong()).isEqualTo(currentTime) + } + verify(sharedPrefsEditor, times(1)).apply() + } + + @Test + fun testLoadComponents_recentlyPlayed_adds() { + // Set up browser to return successfully + val description = MediaDescription.Builder().setTitle(TITLE).build() + val component = ComponentName(PACKAGE_NAME, CLASS_NAME) + whenever(resumeBrowser.token).thenReturn(token) + whenever(resumeBrowser.appIntent).thenReturn(pendingIntent) + whenever(resumeBrowser.findRecentMedia()).thenAnswer { + callbackCaptor.value.addTrack(description, component, resumeBrowser) + } + + // Set up shared preferences to have a component with a recent lastplayed time + val lastPlayed = clock.currentTimeMillis() + val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:" + whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString) + val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor, + tunerService, resumeBrowserFactory, dumpManager, clock) + resumeListener.setManager(mediaDataManager) + mediaDataManager.addListener(resumeListener) + + // When we load a component that was played recently + val intent = Intent(Intent.ACTION_USER_UNLOCKED) + resumeListener.userChangeReceiver.onReceive(mockContext, intent) + + // We add its resume controls + verify(resumeBrowser, times(1)).findRecentMedia() + verify(mediaDataManager, times(1)).addResumptionControls(anyInt(), + any(), any(), any(), any(), any(), eq(PACKAGE_NAME)) + } + + @Test + fun testLoadComponents_old_ignores() { + // Set up shared preferences to have a component with an old lastplayed time + val lastPlayed = clock.currentTimeMillis() - RESUME_MEDIA_TIMEOUT - 100 + val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:" + whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString) + val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor, + tunerService, resumeBrowserFactory, dumpManager, clock) + resumeListener.setManager(mediaDataManager) + mediaDataManager.addListener(resumeListener) + + // When we load a component that is not recent + val intent = Intent(Intent.ACTION_USER_UNLOCKED) + resumeListener.userChangeReceiver.onReceive(mockContext, intent) + + // We do not try to add resume controls + verify(resumeBrowser, times(0)).findRecentMedia() + verify(mediaDataManager, times(0)).addResumptionControls(anyInt(), + any(), any(), any(), any(), any(), any()) + } + + @Test + fun testOnLoad_hasService_updatesLastPlayed() { + // Set up browser to return successfully + val description = MediaDescription.Builder().setTitle(TITLE).build() + val component = ComponentName(PACKAGE_NAME, CLASS_NAME) + whenever(resumeBrowser.token).thenReturn(token) + whenever(resumeBrowser.appIntent).thenReturn(pendingIntent) + whenever(resumeBrowser.findRecentMedia()).thenAnswer { + callbackCaptor.value.addTrack(description, component, resumeBrowser) + } + + // Set up shared preferences to have a component with a lastplayed time + val currentTime = clock.currentTimeMillis() + val lastPlayed = currentTime - 1000 + val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:" + whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString) + val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor, + tunerService, resumeBrowserFactory, dumpManager, clock) + resumeListener.setManager(mediaDataManager) + mediaDataManager.addListener(resumeListener) + + // When media data is loaded that has not been checked yet, and does have a MBS + val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false) + resumeListener.onMediaDataLoaded(KEY, null, dataCopy) + + // Then we store the new lastPlayed time + verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor))) + componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex()) + ?.dropLastWhile { it.isEmpty() }.forEach { + val result = it.split("/") + assertThat(result.size).isEqualTo(3) + assertThat(result[2].toLong()).isEqualTo(currentTime) + } + verify(sharedPrefsEditor, times(1)).apply() + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt index 0a573cd6020c..de2235dd1c42 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt @@ -71,6 +71,7 @@ class MediaTimeoutListenerTest : SysuiTestCase() { private lateinit var playbackBuilder: PlaybackState.Builder private lateinit var session: MediaSession private lateinit var mediaData: MediaData + private lateinit var resumeData: MediaData private lateinit var mediaTimeoutListener: MediaTimeoutListener @Before @@ -97,6 +98,10 @@ class MediaTimeoutListenerTest : SysuiTestCase() { mediaData = MediaData(USER_ID, true, 0, PACKAGE, null, null, SESSION_TITLE, null, emptyList(), emptyList(), PACKAGE, session.sessionToken, clickIntent = null, device = null, active = true, resumeAction = null) + + resumeData = MediaData(USER_ID, true, 0, PACKAGE, null, null, SESSION_TITLE, null, + emptyList(), emptyList(), PACKAGE, null, clickIntent = null, + device = null, active = false, resumeAction = null, resumption = true) } @Test @@ -120,6 +125,7 @@ class MediaTimeoutListenerTest : SysuiTestCase() { verify(mediaController).registerCallback(capture(mediaCallbackCaptor)) assertThat(executor.numPending()).isEqualTo(1) verify(timeoutCallback, never()).invoke(anyString(), anyBoolean()) + assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT) } @Test @@ -188,6 +194,7 @@ class MediaTimeoutListenerTest : SysuiTestCase() { mediaCallbackCaptor.value.onPlaybackStateChanged(PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()) assertThat(executor.numPending()).isEqualTo(1) + assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT) } @Test @@ -229,7 +236,7 @@ class MediaTimeoutListenerTest : SysuiTestCase() { } @Test - fun testOnSessionDestroyed_clearsTimeout() { + fun testOnSessionDestroyed_active_clearsTimeout() { // GIVEN media that is paused val mediaPaused = mediaData.copy(isPlaying = false) mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPaused) @@ -247,7 +254,7 @@ class MediaTimeoutListenerTest : SysuiTestCase() { @Test fun testSessionDestroyed_thenRestarts_resetsTimeout() { // Assuming we have previously destroyed the session - testOnSessionDestroyed_clearsTimeout() + testOnSessionDestroyed_active_clearsTimeout() // WHEN we get an update with media playing val playingState = mock(android.media.session.PlaybackState::class.java) @@ -264,4 +271,91 @@ class MediaTimeoutListenerTest : SysuiTestCase() { } verify(timeoutCallback).invoke(eq(KEY), eq(false)) } + + @Test + fun testOnSessionDestroyed_resume_continuesTimeout() { + // GIVEN resume media with session info + val resumeWithSession = resumeData.copy(token = session.sessionToken) + mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeWithSession) + verify(mediaController).registerCallback(capture(mediaCallbackCaptor)) + assertThat(executor.numPending()).isEqualTo(1) + + // WHEN the session is destroyed + mediaCallbackCaptor.value.onSessionDestroyed() + + // THEN the controller is unregistered, but the timeout is still scheduled + verify(mediaController).unregisterCallback(anyObject()) + assertThat(executor.numPending()).isEqualTo(1) + } + + @Test + fun testOnMediaDataLoaded_activeToResume_registersTimeout() { + // WHEN a regular media is loaded + mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData) + + // AND it turns into a resume control + mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData) + + // THEN we register a timeout + assertThat(executor.numPending()).isEqualTo(1) + verify(timeoutCallback, never()).invoke(anyString(), anyBoolean()) + assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT) + } + + @Test + fun testOnMediaDataLoaded_pausedToResume_updatesTimeout() { + // WHEN regular media is paused + val pausedState = PlaybackState.Builder() + .setState(PlaybackState.STATE_PAUSED, 0L, 0f) + .build() + `when`(mediaController.playbackState).thenReturn(pausedState) + mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData) + assertThat(executor.numPending()).isEqualTo(1) + + // AND it turns into a resume control + mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData) + + // THEN we update the timeout length + assertThat(executor.numPending()).isEqualTo(1) + verify(timeoutCallback, never()).invoke(anyString(), anyBoolean()) + assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT) + } + + @Test + fun testOnMediaDataLoaded_resumption_registersTimeout() { + // WHEN a resume media is loaded + mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData) + + // THEN we register a timeout + assertThat(executor.numPending()).isEqualTo(1) + verify(timeoutCallback, never()).invoke(anyString(), anyBoolean()) + assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT) + } + + @Test + fun testOnMediaDataLoaded_resumeToActive_updatesTimeout() { + // WHEN we have a resume control + mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData) + + // AND that media is resumed + val playingState = PlaybackState.Builder() + .setState(PlaybackState.STATE_PAUSED, 0L, 0f) + .build() + `when`(mediaController.playbackState).thenReturn(playingState) + mediaTimeoutListener.onMediaDataLoaded(KEY, PACKAGE, mediaData) + + // THEN the timeout length is changed to a regular media control + assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT) + } + + @Test + fun testOnMediaDataRemoved_resume_timeoutCancelled() { + // WHEN we have a resume control + testOnMediaDataLoaded_resumption_registersTimeout() + // AND the media is removed + mediaTimeoutListener.onMediaDataRemoved(PACKAGE) + + // THEN the timeout runnable is cancelled + assertThat(executor.numPending()).isEqualTo(0) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt index 03248f7e3a70..511848d8a3af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt @@ -22,11 +22,13 @@ import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.pm.UserInfo +import android.os.Process.SYSTEM_UID import android.os.UserHandle import android.permission.PermGroupUsage import android.permission.PermissionManager import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest +import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.appops.AppOpsController import com.android.systemui.plugins.ActivityStarter @@ -53,6 +55,7 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.mock import org.mockito.Mockito.never +import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -96,6 +99,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() { private lateinit var activityStartedCaptor: ArgumentCaptor<ActivityStarter.Callback> @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent> + @Mock + private lateinit var uiEventLogger: UiEventLogger private val backgroundExecutor = FakeExecutor(FakeSystemClock()) private val uiExecutor = FakeExecutor(FakeSystemClock()) @@ -136,6 +141,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() { privacyLogger, keyguardStateController, appOpsController, + uiEventLogger, dialogProvider ) } @@ -550,6 +556,49 @@ class PrivacyDialogControllerTest : SysuiTestCase() { verify(dialog, never()).dismiss() } + @Test + fun testCallOnSecondaryUser() { + // Calls happen in + val usage = createMockPermGroupUsage(uid = SYSTEM_UID, isPhoneCall = true) + `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) + `when`(userTracker.userProfiles).thenReturn(listOf( + UserInfo(ENT_USER_ID, "", 0) + )) + + controller.showDialog(context) + exhaustExecutors() + + verify(dialog).show() + } + + @Test + fun testStartActivityLogs() { + val usage = createMockPermGroupUsage() + `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) + controller.showDialog(context) + exhaustExecutors() + + dialogProvider.starter?.invoke(TEST_PACKAGE_NAME, USER_ID) + verify(uiEventLogger).log(PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_APP_SETTINGS, + USER_ID, TEST_PACKAGE_NAME) + } + + @Test + fun testDismissedDialogLogs() { + val usage = createMockPermGroupUsage() + `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) + controller.showDialog(context) + exhaustExecutors() + + verify(dialog).addOnDismissListener(capture(dialogDismissedCaptor)) + + dialogDismissedCaptor.value.onDialogDismissed() + + controller.dismissDialog() + + verify(uiEventLogger, times(1)).log(PrivacyDialogEvent.PRIVACY_DIALOG_DISMISSED) + } + private fun exhaustExecutors() { FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor) } 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 de7abf866f6a..922c6b648aab 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 android.testing.TestableLooper.RunWithLooper; 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 @@ public class AutoAddTrackerTest extends SysuiTestCase { 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); - mAutoTracker.initialize(); + mSecureSettings = new FakeSettings(); - assertTrue(mAutoTracker.isAdded(SAVER)); - assertTrue(mAutoTracker.isAdded(WORK)); - assertFalse(mAutoTracker.isAdded(INVERSION)); + mSecureSettings.putStringForUser(Secure.QS_AUTO_ADDED_TILES, null, USER); - // 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(); + mAutoTracker = createAutoAddTracker(USER); + mAutoTracker.initialize(); } @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 @@ public class AutoAddTrackerTest extends SysuiTestCase { @Test public void testSetAdded() { - mAutoTracker = new AutoAddTracker(mContext, USER); - mAutoTracker.initialize(); - assertFalse(mAutoTracker.isAdded(SAVER)); mAutoTracker.setTileAdded(SAVER); @@ -100,14 +110,12 @@ public class AutoAddTrackerTest extends SysuiTestCase { @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 @@ public class AutoAddTrackerTest extends SysuiTestCase { @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/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java index 65e5f9703d84..faef87069084 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -98,11 +99,11 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { Resources mResources; @Mock Configuration mConfiguration; + @Mock + Runnable mHorizontalLayoutListener; private QSPanelControllerBase<QSPanel> mController; - - /** Implementation needed to ensure we have a reflectively-available class name. */ private class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> { protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host, @@ -242,18 +243,44 @@ public class QSPanelControllerBaseTest extends SysuiTestCase { when(mMediaHost.getVisible()).thenReturn(true); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false); + when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape"); mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost, mQSCustomizerController, mMediaHost, mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mFeatureFlags); + mController.init(); assertThat(mController.shouldUseHorizontalLayout()).isTrue(); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); + when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait"); mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost, mQSCustomizerController, mMediaHost, mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mFeatureFlags); + mController.init(); + + assertThat(mController.shouldUseHorizontalLayout()).isFalse(); + } + + @Test + public void testChangeConfiguration_shouldUseHorizontalLayout() { + when(mMediaHost.getVisible()).thenReturn(true); + mController.setUsingHorizontalLayoutChangeListener(mHorizontalLayoutListener); + + // When device is rotated to landscape + mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE; + mController.mOnConfigurationChangedListener.onConfigurationChange(mConfiguration); + + // Then the layout changes + assertThat(mController.shouldUseHorizontalLayout()).isTrue(); + verify(mHorizontalLayoutListener).run(); // not invoked + + // When it is rotated back to portrait + mConfiguration.orientation = Configuration.ORIENTATION_PORTRAIT; + mController.mOnConfigurationChangedListener.onConfigurationChange(mConfiguration); + // Then the layout changes back assertThat(mController.shouldUseHorizontalLayout()).isFalse(); + verify(mHorizontalLayoutListener, times(2)).run(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java index bf6c981bf05c..35ebacb85203 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java @@ -23,6 +23,8 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.res.Configuration; +import android.content.res.Resources; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -98,6 +100,10 @@ public class QSPanelControllerTest extends SysuiTestCase { FalsingManagerFake mFalsingManager = new FalsingManagerFake(); @Mock FeatureFlags mFeatureFlags; + @Mock + Resources mResources; + @Mock + Configuration mConfiguration; private QSPanelController mController; @@ -109,6 +115,8 @@ public class QSPanelControllerTest extends SysuiTestCase { when(mQSPanel.getDumpableTag()).thenReturn("QSPanel"); when(mQSPanel.getOrCreateTileLayout()).thenReturn(mPagedTileLayout); when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout); + when(mQSPanel.getResources()).thenReturn(mResources); + when(mResources.getConfiguration()).thenReturn(mConfiguration); when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile)); when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView); when(mToggleSliderViewControllerFactory.create(any(), any())) 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 4cbad5f15c5f..0b67c9c51079 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 @@ package com.android.systemui.qs; 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.AutoTileManager; 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 @@ public class QSTileHostTest extends SysuiTestCase { private UiEventLogger mUiEventLogger; @Mock private UserTracker mUserTracker; - @Mock private SecureSettings mSecureSettings; @Mock private CustomTileStatePersister mCustomTileStatePersister; @@ -137,14 +133,16 @@ public class QSTileHostTest extends SysuiTestCase { 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, mFeatureFlags); setUpTileFactory(); when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false); - when(mSecureSettings.getStringForUser(eq(QSTileHost.TILES_SETTING), anyInt())) - .thenReturn(""); } private void setUpTileFactory() { @@ -416,6 +414,16 @@ public class QSTileHostTest extends SysuiTestCase { .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, @@ -442,14 +450,11 @@ public class QSTileHostTest extends SysuiTestCase { @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/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index 35360bd19393..8b7e20ed0e5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -36,6 +36,8 @@ import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.policy.Clock +import com.android.systemui.statusbar.policy.VariableDateView +import com.android.systemui.statusbar.policy.VariableDateViewController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture @@ -87,8 +89,14 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var privacyDialogController: PrivacyDialogController @Mock + private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory + @Mock + private lateinit var variableDateViewController: VariableDateViewController + @Mock private lateinit var clock: Clock @Mock + private lateinit var variableDateView: VariableDateView + @Mock private lateinit var mockView: View @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var context: Context @@ -109,6 +117,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { stubViews() `when`(iconContainer.context).thenReturn(context) `when`(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController) + `when`(variableDateViewControllerFactory.create(any())) + .thenReturn(variableDateViewController) `when`(view.resources).thenReturn(mContext.resources) `when`(view.isAttachedToWindow).thenReturn(true) `when`(view.context).thenReturn(context) @@ -133,7 +143,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { colorExtractor, privacyDialogController, qsExpansionPathInterpolator, - featureFlags + featureFlags, + variableDateViewControllerFactory ) } @@ -274,6 +285,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer) `when`(view.findViewById<OngoingPrivacyChip>(R.id.privacy_chip)).thenReturn(privacyChip) `when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock) + `when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView) + `when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView) } private fun setPrivacyController(micCamera: Boolean, location: Boolean) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java index 63ebe9290f64..23e51687f9e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -74,6 +75,24 @@ public class QSIconViewImplTest extends SysuiTestCase { } @Test + public void testMutateIconDrawable() { + SlashImageView iv = mock(SlashImageView.class); + Drawable originalDrawable = mock(Drawable.class); + Drawable otherDrawable = mock(Drawable.class); + State s = new State(); + s.icon = mock(Icon.class); + when(s.icon.getInvisibleDrawable(eq(mContext))).thenReturn(originalDrawable); + when(s.icon.getDrawable(eq(mContext))).thenReturn(originalDrawable); + when(iv.isShown()).thenReturn(true); + when(originalDrawable.getConstantState()).thenReturn(fakeConstantState(otherDrawable)); + + + mIconView.updateIcon(iv, s, /* allowAnimations= */true); + + verify(iv).setState(any(), eq(otherDrawable)); + } + + @Test public void testNoFirstFade() { ImageView iv = mock(ImageView.class); State s = new State(); @@ -104,4 +123,18 @@ public class QSIconViewImplTest extends SysuiTestCase { public void testIconNotSet_toString() { assertFalse(mIconView.toString().contains("lastIcon")); } + + private static Drawable.ConstantState fakeConstantState(Drawable otherDrawable) { + return new Drawable.ConstantState() { + @Override + public Drawable newDrawable() { + return otherDrawable; + } + + @Override + public int getChangingConfigurations() { + return 1; + } + }; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt index 5e2d8fde84da..b4a662974d22 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt @@ -3,6 +3,7 @@ package com.android.systemui.qs.tiles import android.app.AlarmManager import android.app.PendingIntent import android.os.Handler +import android.provider.AlarmClock import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -98,6 +99,11 @@ class AlarmTileTest : SysuiTestCase() { } @Test + fun testDefaultIntentShowAlarms() { + assertThat(tile.defaultIntent.action).isEqualTo(AlarmClock.ACTION_SHOW_ALARMS) + } + + @Test fun testInactiveByDefault() { assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index d44a52607707..e939411e4a2a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; @@ -327,4 +328,77 @@ public class CastTileTest extends SysuiTestCase { assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state); assertTrue(mCastTile.getState().secondaryLabel.toString().startsWith(connected.name)); } + + @Test + public void testExpandView_wifiNotConnected() { + mCastTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertFalse(mCastTile.getState().forceExpandIcon); + } + + @Test + public void testExpandView_wifiEnabledNotCasting() { + enableWifiAndProcessMessages(); + + assertTrue(mCastTile.getState().forceExpandIcon); + } + + @Test + public void testExpandView_casting_projection() { + CastController.CastDevice device = new CastController.CastDevice(); + device.state = CastController.CastDevice.STATE_CONNECTED; + List<CastDevice> devices = new ArrayList<>(); + devices.add(device); + when(mController.getCastDevices()).thenReturn(devices); + + enableWifiAndProcessMessages(); + + assertFalse(mCastTile.getState().forceExpandIcon); + } + + @Test + public void testExpandView_connecting_projection() { + CastController.CastDevice connecting = new CastController.CastDevice(); + connecting.state = CastDevice.STATE_CONNECTING; + connecting.name = "Test Casting Device"; + + List<CastDevice> devices = new ArrayList<>(); + devices.add(connecting); + when(mController.getCastDevices()).thenReturn(devices); + + enableWifiAndProcessMessages(); + + assertFalse(mCastTile.getState().forceExpandIcon); + } + + @Test + public void testExpandView_casting_mediaRoute() { + CastController.CastDevice device = new CastController.CastDevice(); + device.state = CastDevice.STATE_CONNECTED; + device.tag = mock(MediaRouter.RouteInfo.class); + List<CastDevice> devices = new ArrayList<>(); + devices.add(device); + when(mController.getCastDevices()).thenReturn(devices); + + enableWifiAndProcessMessages(); + + assertTrue(mCastTile.getState().forceExpandIcon); + } + + @Test + public void testExpandView_connecting_mediaRoute() { + CastController.CastDevice connecting = new CastController.CastDevice(); + connecting.state = CastDevice.STATE_CONNECTING; + connecting.tag = mock(RouteInfo.class); + connecting.name = "Test Casting Device"; + + List<CastDevice> devices = new ArrayList<>(); + devices.add(connecting); + when(mController.getCastDevices()).thenReturn(devices); + + enableWifiAndProcessMessages(); + + assertTrue(mCastTile.getState().forceExpandIcon); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java new file mode 100644 index 000000000000..49ab777624e3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java @@ -0,0 +1,209 @@ +/* + * 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.tiles; + +import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; +import static android.provider.Settings.Secure.CAMERA_AUTOROTATE; + +import static junit.framework.TestCase.assertEquals; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.hardware.SensorPrivacyManager; +import android.os.Handler; +import android.os.UserHandle; +import android.provider.Settings; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.text.TextUtils; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.classifier.FalsingManagerFake; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSTileHost; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.RotationLockController; +import com.android.systemui.statusbar.policy.RotationLockControllerImpl; +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.Mock; +import org.mockito.MockitoAnnotations; + + +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +public class RotationLockTileTest extends SysuiTestCase { + + private static final String PACKAGE_NAME = "package_name"; + + @Mock + private PackageManager mPackageManager; + @Mock + private ActivityStarter mActivityStarter; + @Mock + private QSTileHost mHost; + @Mock + private MetricsLogger mMetricsLogger; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private QSLogger mQSLogger; + @Mock + private SensorPrivacyManager mPrivacyManager; + @Mock + private BatteryController mBatteryController; + + private SecureSettings mSecureSettings; + private RotationLockController mController; + private TestableLooper mTestableLooper; + private RotationLockTile mLockTile; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mTestableLooper = TestableLooper.get(this); + + when(mHost.getContext()).thenReturn(mContext); + when(mHost.getUserContext()).thenReturn(mContext); + + mSecureSettings = new FakeSettings(); + mController = new RotationLockControllerImpl(mContext, mSecureSettings); + + mLockTile = new RotationLockTile( + mHost, + mTestableLooper.getLooper(), + new Handler(mTestableLooper.getLooper()), + new FalsingManagerFake(), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger, + mController, + mPrivacyManager, + mBatteryController, + mSecureSettings + ); + + mLockTile.initialize(); + + // We are not setting the mocks to listening, so we trigger a first refresh state to + // set the initial state + mLockTile.refreshState(); + + mTestableLooper.processAllMessages(); + + mContext.setMockPackageManager(mPackageManager); + doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName(); + doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + + when(mBatteryController.isPowerSave()).thenReturn(false); + when(mPrivacyManager.isSensorPrivacyEnabled(CAMERA)).thenReturn(false); + enableAutoRotation(); + enableCameraBasedRotation(); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + } + + @Test + public void testSecondaryString_cameraRotateOn_returnsFaceBased() { + assertEquals("On - Face-based", mLockTile.getState().secondaryLabel); + } + + @Test + public void testSecondaryString_rotateOff_isEmpty() { + disableAutoRotation(); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(TextUtils.isEmpty(mLockTile.getState().secondaryLabel)); + } + + @Test + public void testSecondaryString_cameraRotateOff_isEmpty() { + disableCameraBasedRotation(); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(TextUtils.isEmpty(mLockTile.getState().secondaryLabel)); + } + + @Test + public void testSecondaryString_powerSaveEnabled_isEmpty() { + when(mBatteryController.isPowerSave()).thenReturn(true); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(TextUtils.isEmpty(mLockTile.getState().secondaryLabel)); + } + + @Test + public void testSecondaryString_cameraDisabled_isEmpty() { + when(mPrivacyManager.isSensorPrivacyEnabled(CAMERA)).thenReturn(true); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(TextUtils.isEmpty(mLockTile.getState().secondaryLabel)); + } + + @Test + public void testSecondaryString_noCameraPermission_isEmpty() { + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + + mLockTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(TextUtils.isEmpty(mLockTile.getState().secondaryLabel)); + } + + private void enableAutoRotation() { + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT); + } + + private void disableAutoRotation() { + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT); + } + + private void enableCameraBasedRotation() { + mSecureSettings.putIntForUser( + CAMERA_AUTOROTATE, 1, UserHandle.USER_CURRENT); + } + + private void disableCameraBasedRotation() { + mSecureSettings.putIntForUser( + CAMERA_AUTOROTATE, 0, UserHandle.USER_CURRENT); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java new file mode 100644 index 000000000000..77946cf791aa --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java @@ -0,0 +1,167 @@ +package com.android.systemui.qs.tiles.dialog; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.graphics.drawable.Drawable; +import android.testing.AndroidTestingRunner; +import android.testing.TestableResources; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.test.filters.SmallTest; + +import com.android.settingslib.wifi.WifiUtils; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.wifitrackerlib.WifiEntry; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.Arrays; +import java.util.List; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class InternetAdapterTest extends SysuiTestCase { + + private static final String WIFI_TITLE = "Wi-Fi Title"; + private static final String WIFI_SUMMARY = "Wi-Fi Summary"; + private static final int GEAR_ICON_RES_ID = R.drawable.ic_settings_24dp; + private static final int LOCK_ICON_RES_ID = R.drawable.ic_friction_lock_closed; + + @Rule + public MockitoRule mRule = MockitoJUnit.rule(); + + @Mock + private WifiEntry mInternetWifiEntry; + @Mock + private List<WifiEntry> mWifiEntries; + @Mock + private WifiEntry mWifiEntry; + @Mock + private InternetDialogController mInternetDialogController; + @Mock + private WifiUtils.InternetIconInjector mWifiIconInjector; + @Mock + private Drawable mGearIcon; + @Mock + private Drawable mLockIcon; + + private TestableResources mTestableResources; + private InternetAdapter mInternetAdapter; + private InternetAdapter.InternetViewHolder mViewHolder; + + @Before + public void setUp() { + mTestableResources = mContext.getOrCreateTestableResources(); + when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE); + when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY); + when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true); + when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true); + when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE); + when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY); + + mInternetAdapter = new InternetAdapter(mInternetDialogController); + mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0); + mInternetAdapter.setWifiEntries(Arrays.asList(mWifiEntry), 1 /* wifiEntriesCount */); + mViewHolder.mWifiIconInjector = mWifiIconInjector; + } + + @Test + public void getItemCount_returnWifiEntriesCount() { + for (int i = 0; i < InternetDialogController.MAX_WIFI_ENTRY_COUNT; i++) { + mInternetAdapter.setWifiEntries(mWifiEntries, i /* wifiEntriesCount */); + + assertThat(mInternetAdapter.getItemCount()).isEqualTo(i); + } + } + + @Test + public void onBindViewHolder_bindWithOpenWifiNetwork_verifyView() { + when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_NONE); + mInternetAdapter.onBindViewHolder(mViewHolder, 0); + + assertThat(mViewHolder.mWifiTitleText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiSummaryText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiIcon.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void onBindViewHolder_bindWithSecurityWifiNetwork_verifyView() { + when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_PSK); + mInternetAdapter.onBindViewHolder(mViewHolder, 0); + + assertThat(mViewHolder.mWifiTitleText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiSummaryText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiIcon.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void onBindViewHolder_wifiLevelUnreachable_shouldNotGetWifiIcon() { + reset(mWifiIconInjector); + when(mWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE); + + mInternetAdapter.onBindViewHolder(mViewHolder, 0); + + verify(mWifiIconInjector, never()).getIcon(anyBoolean(), anyInt()); + } + + @Test + public void onBindViewHolder_shouldNotShowXLevelIcon_getIconWithInternet() { + when(mWifiEntry.shouldShowXLevelIcon()).thenReturn(false); + + mInternetAdapter.onBindViewHolder(mViewHolder, 0); + + verify(mWifiIconInjector).getIcon(eq(false) /* noInternet */, anyInt()); + } + + @Test + public void onBindViewHolder_shouldShowXLevelIcon_getIconWithNoInternet() { + when(mWifiEntry.shouldShowXLevelIcon()).thenReturn(true); + + mInternetAdapter.onBindViewHolder(mViewHolder, 0); + + verify(mWifiIconInjector).getIcon(eq(true) /* noInternet */, anyInt()); + } + + @Test + public void viewHolderUpdateEndIcon_wifiConnected_updateGearIcon() { + mTestableResources.addOverride(GEAR_ICON_RES_ID, mGearIcon); + + mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_CONNECTED, WifiEntry.SECURITY_PSK); + + assertThat(mViewHolder.mWifiEndIcon.getDrawable()).isEqualTo(mGearIcon); + } + + @Test + public void viewHolderUpdateEndIcon_wifiDisconnectedAndSecurityPsk_updateLockIcon() { + mTestableResources.addOverride(LOCK_ICON_RES_ID, mLockIcon); + + mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_DISCONNECTED, WifiEntry.SECURITY_PSK); + + assertThat(mViewHolder.mWifiEndIcon.getDrawable()).isEqualTo(mLockIcon); + } + + @Test + public void viewHolderUpdateEndIcon_wifiDisconnectedAndSecurityNone_hideIcon() { + mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_DISCONNECTED, WifiEntry.SECURITY_NONE); + + assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.GONE); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java new file mode 100644 index 000000000000..663edc7b373b --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java @@ -0,0 +1,675 @@ +package com.android.systemui.qs.tiles.dialog; + +import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_HORIZONTAL_WEIGHT; +import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_VERTICAL_WEIGHT; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.animation.Animator; +import android.content.Context; +import android.content.Intent; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableResources; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.test.filters.SmallTest; + +import com.android.internal.logging.UiEventLogger; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.settingslib.wifi.WifiUtils; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.LocationController; +import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; +import com.android.systemui.toast.SystemUIToast; +import com.android.systemui.toast.ToastFactory; +import com.android.systemui.util.CarrierConfigTracker; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.settings.GlobalSettings; +import com.android.systemui.util.time.FakeSystemClock; +import com.android.wifitrackerlib.MergedCarrierEntry; +import com.android.wifitrackerlib.WifiEntry; + +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; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class InternetDialogControllerTest extends SysuiTestCase { + + private static final int SUB_ID = 1; + private static final String CONNECTED_TITLE = "Connected Wi-Fi Title"; + private static final String CONNECTED_SUMMARY = "Connected Wi-Fi Summary"; + + //SystemUIToast + private static final int GRAVITY_FLAGS = Gravity.FILL_HORIZONTAL | Gravity.FILL_VERTICAL; + private static final int TOAST_MESSAGE_STRING_ID = 1; + private static final String TOAST_MESSAGE_STRING = "toast message"; + + @Mock + private WifiManager mWifiManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private Handler mHandler; + @Mock + private Handler mWorkerHandler; + @Mock + private ActivityStarter mActivityStarter; + @Mock + private GlobalSettings mGlobalSettings; + @Mock + private KeyguardStateController mKeyguardStateController; + @Mock + private NetworkController.AccessPointController mAccessPointController; + @Mock + private WifiEntry mConnectedEntry; + @Mock + private WifiEntry mWifiEntry1; + @Mock + private WifiEntry mWifiEntry2; + @Mock + private WifiEntry mWifiEntry3; + @Mock + private WifiEntry mWifiEntry4; + @Mock + private MergedCarrierEntry mMergedCarrierEntry; + @Mock + private ServiceState mServiceState; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; + @Mock + private WifiUtils.InternetIconInjector mWifiIconInjector; + @Mock + InternetDialogController.InternetDialogCallback mInternetDialogCallback; + @Mock + private WindowManager mWindowManager; + @Mock + private ToastFactory mToastFactory; + @Mock + private SystemUIToast mSystemUIToast; + @Mock + private View mToastView; + @Mock + private Animator mAnimator; + @Mock + private CarrierConfigTracker mCarrierConfigTracker; + @Mock + private LocationController mLocationController; + + private TestableResources mTestableResources; + private MockInternetDialogController mInternetDialogController; + private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); + private List<WifiEntry> mAccessPoints = new ArrayList<>(); + private List<WifiEntry> mWifiEntries = new ArrayList<>(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTestableResources = mContext.getOrCreateTestableResources(); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt()); + when(mKeyguardStateController.isUnlocked()).thenReturn(true); + when(mConnectedEntry.isDefaultNetwork()).thenReturn(true); + when(mConnectedEntry.hasInternetAccess()).thenReturn(true); + when(mWifiEntry1.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED); + when(mWifiEntry2.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED); + when(mWifiEntry3.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED); + when(mWifiEntry4.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED); + mAccessPoints.add(mConnectedEntry); + mAccessPoints.add(mWifiEntry1); + when(mAccessPointController.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); + when(mAccessPointController.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry); + when(mToastFactory.createToast(any(), anyString(), anyString(), anyInt(), anyInt())) + .thenReturn(mSystemUIToast); + when(mSystemUIToast.getView()).thenReturn(mToastView); + when(mSystemUIToast.getGravity()).thenReturn(GRAVITY_FLAGS); + when(mSystemUIToast.getInAnimation()).thenReturn(mAnimator); + + mInternetDialogController = new MockInternetDialogController(mContext, + mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController, + mSubscriptionManager, mTelephonyManager, mWifiManager, + mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher, + mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController, + mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker, + mLocationController); + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, + mInternetDialogController.mOnSubscriptionsChangedListener); + mInternetDialogController.onStart(mInternetDialogCallback, true); + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + mInternetDialogController.mActivityStarter = mActivityStarter; + mInternetDialogController.mWifiIconInjector = mWifiIconInjector; + } + + @Test + public void connectCarrierNetwork_mergedCarrierEntryCanConnect_connectAndCreateSysUiToast() { + when(mMergedCarrierEntry.canConnect()).thenReturn(true); + mTestableResources.addOverride(R.string.wifi_wont_autoconnect_for_now, + TOAST_MESSAGE_STRING); + + mInternetDialogController.connectCarrierNetwork(); + + verify(mMergedCarrierEntry).connect(null /* callback */, false /* showToast */); + verify(mToastFactory).createToast(any(), eq(TOAST_MESSAGE_STRING), anyString(), anyInt(), + anyInt()); + } + + @Test + public void makeOverlayToast_withGravityFlags_addViewWithLayoutParams() { + mTestableResources.addOverride(TOAST_MESSAGE_STRING_ID, TOAST_MESSAGE_STRING); + + mInternetDialogController.makeOverlayToast(TOAST_MESSAGE_STRING_ID); + + ArgumentCaptor<WindowManager.LayoutParams> paramsCaptor = ArgumentCaptor.forClass( + WindowManager.LayoutParams.class); + verify(mWindowManager).addView(eq(mToastView), paramsCaptor.capture()); + WindowManager.LayoutParams params = paramsCaptor.getValue(); + assertThat(params.format).isEqualTo(PixelFormat.TRANSLUCENT); + assertThat(params.type).isEqualTo(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); + assertThat(params.horizontalWeight).isEqualTo(TOAST_PARAMS_HORIZONTAL_WEIGHT); + assertThat(params.verticalWeight).isEqualTo(TOAST_PARAMS_VERTICAL_WEIGHT); + } + + @Test + public void makeOverlayToast_withAnimation_verifyAnimatorStart() { + mTestableResources.addOverride(TOAST_MESSAGE_STRING_ID, TOAST_MESSAGE_STRING); + + mInternetDialogController.makeOverlayToast(TOAST_MESSAGE_STRING_ID); + + verify(mAnimator).start(); + } + + @Test + public void getDialogTitleText_withAirplaneModeOn_returnAirplaneMode() { + mInternetDialogController.setAirplaneModeEnabled(true); + + assertTrue(TextUtils.equals(mInternetDialogController.getDialogTitleText(), + getResourcesString("airplane_mode"))); + } + + @Test + public void getDialogTitleText_withAirplaneModeOff_returnInternet() { + mInternetDialogController.setAirplaneModeEnabled(false); + + assertTrue(TextUtils.equals(mInternetDialogController.getDialogTitleText(), + getResourcesString("quick_settings_internet_label"))); + } + + @Test + public void getSubtitleText_withAirplaneModeOn_returnNull() { + mInternetDialogController.setAirplaneModeEnabled(true); + + assertThat(mInternetDialogController.getSubtitleText(false)).isNull(); + } + + @Test + public void getSubtitleText_withWifiOff_returnWifiIsOff() { + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(false); + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isEqualTo(getResourcesString("wifi_is_off")); + + // if the Wi-Fi disallow config, then don't return Wi-Fi related string. + mInternetDialogController.mCanConfigWifi = false; + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isNotEqualTo(getResourcesString("wifi_is_off")); + } + + @Test + public void getSubtitleText_withNoWifiEntry_returnSearchWifi() { + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + + assertThat(mInternetDialogController.getSubtitleText(true)) + .isEqualTo(getResourcesString("wifi_empty_list_wifi_on")); + + // if the Wi-Fi disallow config, then don't return Wi-Fi related string. + mInternetDialogController.mCanConfigWifi = false; + + assertThat(mInternetDialogController.getSubtitleText(true)) + .isNotEqualTo(getResourcesString("wifi_empty_list_wifi_on")); + } + + @Test + public void getSubtitleText_withWifiEntry_returnTapToConnect() { + // The preconditions WiFi Entries is already in setUp() + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isEqualTo(getResourcesString("tap_a_network_to_connect")); + + // if the Wi-Fi disallow config, then don't return Wi-Fi related string. + mInternetDialogController.mCanConfigWifi = false; + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isNotEqualTo(getResourcesString("tap_a_network_to_connect")); + } + + @Test + public void getSubtitleText_deviceLockedWithWifiOn_returnUnlockToViewNetworks() { + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + when(mKeyguardStateController.isUnlocked()).thenReturn(false); + + assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false), + getResourcesString("unlock_to_view_networks"))); + } + + @Test + public void getSubtitleText_withNoService_returnNoNetworksAvailable() { + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + + doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState(); + doReturn(mServiceState).when(mTelephonyManager).getServiceState(); + doReturn(TelephonyManager.DATA_DISCONNECTED).when(mTelephonyManager).getDataState(); + + assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false), + getResourcesString("all_network_unavailable"))); + } + + @Test + public void getSubtitleText_withMobileDataDisabled_returnNoOtherAvailable() { + mInternetDialogController.setAirplaneModeEnabled(false); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + + doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState(); + doReturn(mServiceState).when(mTelephonyManager).getServiceState(); + + when(mTelephonyManager.isDataEnabled()).thenReturn(false); + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isEqualTo(getResourcesString("non_carrier_network_unavailable")); + + // if the Wi-Fi disallow config, then don't return Wi-Fi related string. + mInternetDialogController.mCanConfigWifi = false; + + assertThat(mInternetDialogController.getSubtitleText(false)) + .isNotEqualTo(getResourcesString("non_carrier_network_unavailable")); + } + + @Test + public void getWifiDetailsSettingsIntent_withNoKey_returnNull() { + assertThat(mInternetDialogController.getWifiDetailsSettingsIntent(null)).isNull(); + } + + @Test + public void getWifiDetailsSettingsIntent_withKey_returnIntent() { + assertThat(mInternetDialogController.getWifiDetailsSettingsIntent("test_key")).isNotNull(); + } + + @Test + public void getInternetWifiDrawable_withConnectedEntry_returnIntentIconWithCorrectColor() { + final Drawable drawable = mock(Drawable.class); + when(mWifiIconInjector.getIcon(anyBoolean(), anyInt())).thenReturn(drawable); + + mInternetDialogController.getInternetWifiDrawable(mConnectedEntry); + + verify(mWifiIconInjector).getIcon(eq(false), anyInt()); + verify(drawable).setTint(mContext.getColor(R.color.connected_network_primary_color)); + } + + @Test + public void getInternetWifiDrawable_withWifiLevelUnreachable_returnNull() { + when(mConnectedEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE); + + Drawable drawable = mInternetDialogController.getInternetWifiDrawable(mConnectedEntry); + + assertThat(drawable).isNull(); + } + + @Test + public void launchWifiNetworkDetailsSetting_withNoWifiEntryKey_doNothing() { + mInternetDialogController.launchWifiNetworkDetailsSetting(null /* key */); + + verify(mActivityStarter, never()) + .postStartActivityDismissingKeyguard(any(Intent.class), anyInt()); + } + + @Test + public void launchWifiNetworkDetailsSetting_withWifiEntryKey_startActivity() { + mInternetDialogController.launchWifiNetworkDetailsSetting("wifi_entry_key"); + + verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt()); + } + + @Test + public void isDeviceLocked_keyguardIsUnlocked_returnFalse() { + when(mKeyguardStateController.isUnlocked()).thenReturn(true); + + assertThat(mInternetDialogController.isDeviceLocked()).isFalse(); + } + + @Test + public void isDeviceLocked_keyguardIsLocked_returnTrue() { + when(mKeyguardStateController.isUnlocked()).thenReturn(false); + + assertThat(mInternetDialogController.isDeviceLocked()).isTrue(); + } + + @Test + public void onAccessPointsChanged_canNotConfigWifi_doNothing() { + reset(mInternetDialogCallback); + mInternetDialogController.mCanConfigWifi = false; + + mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + + verify(mInternetDialogCallback, never()).onAccessPointsChanged(any(), any()); + } + + @Test + public void onAccessPointsChanged_nullAccessPoints_callbackBothNull() { + reset(mInternetDialogCallback); + + mInternetDialogController.onAccessPointsChanged(null /* accessPoints */); + + verify(mInternetDialogCallback) + .onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry */); + } + + @Test + public void onAccessPointsChanged_oneConnectedEntry_callbackConnectedEntryOnly() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mConnectedEntry); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + } + + @Test + public void onAccessPointsChanged_noConnectedEntryAndOneOther_callbackWifiEntriesOnly() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mWifiEntry1); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + verify(mInternetDialogCallback) + .onAccessPointsChanged(mWifiEntries, null /* connectedEntry */); + } + + @Test + public void onAccessPointsChanged_oneConnectedEntryAndOneOther_callbackCorrectly() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mConnectedEntry); + mAccessPoints.add(mWifiEntry1); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + } + + @Test + public void onAccessPointsChanged_oneConnectedEntryAndTwoOthers_callbackCorrectly() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mConnectedEntry); + mAccessPoints.add(mWifiEntry1); + mAccessPoints.add(mWifiEntry2); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + mWifiEntries.add(mWifiEntry2); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + } + + @Test + public void onAccessPointsChanged_oneConnectedEntryAndThreeOthers_callbackCutMore() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mConnectedEntry); + mAccessPoints.add(mWifiEntry1); + mAccessPoints.add(mWifiEntry2); + mAccessPoints.add(mWifiEntry3); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + mWifiEntries.add(mWifiEntry2); + mWifiEntries.add(mWifiEntry3); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + + // Turn off airplane mode to has carrier network, then Wi-Fi entries will cut last one. + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(false); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.remove(mWifiEntry3); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + } + + @Test + public void onAccessPointsChanged_oneConnectedEntryAndFourOthers_callbackCutMore() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mConnectedEntry); + mAccessPoints.add(mWifiEntry1); + mAccessPoints.add(mWifiEntry2); + mAccessPoints.add(mWifiEntry3); + mAccessPoints.add(mWifiEntry4); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + mWifiEntries.add(mWifiEntry2); + mWifiEntries.add(mWifiEntry3); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + + // Turn off airplane mode to has carrier network, then Wi-Fi entries will cut last one. + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(false); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.remove(mWifiEntry3); + verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry); + } + + @Test + public void onAccessPointsChanged_fourWifiEntries_callbackCutMore() { + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(true); + mAccessPoints.clear(); + mAccessPoints.add(mWifiEntry1); + mAccessPoints.add(mWifiEntry2); + mAccessPoints.add(mWifiEntry3); + mAccessPoints.add(mWifiEntry4); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.clear(); + mWifiEntries.add(mWifiEntry1); + mWifiEntries.add(mWifiEntry2); + mWifiEntries.add(mWifiEntry3); + mWifiEntries.add(mWifiEntry4); + verify(mInternetDialogCallback) + .onAccessPointsChanged(mWifiEntries, null /* connectedEntry */); + + // If the Ethernet exists, then Wi-Fi entries will cut last one. + reset(mInternetDialogCallback); + mInternetDialogController.mHasEthernet = true; + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.remove(mWifiEntry4); + verify(mInternetDialogCallback) + .onAccessPointsChanged(mWifiEntries, null /* connectedEntry */); + + // Turn off airplane mode to has carrier network, then Wi-Fi entries will cut last one. + reset(mInternetDialogCallback); + mInternetDialogController.setAirplaneModeEnabled(false); + + mInternetDialogController.onAccessPointsChanged(mAccessPoints); + + mWifiEntries.remove(mWifiEntry3); + verify(mInternetDialogCallback) + .onAccessPointsChanged(mWifiEntries, null /* connectedEntry */); + } + + @Test + public void setMergedCarrierWifiEnabledIfNeed_carrierProvisionsEnabled_doNothing() { + when(mCarrierConfigTracker.getCarrierProvisionsWifiMergedNetworksBool(SUB_ID)) + .thenReturn(true); + + mInternetDialogController.setMergedCarrierWifiEnabledIfNeed(SUB_ID, true); + + verify(mMergedCarrierEntry, never()).setEnabled(anyBoolean()); + } + + @Test + public void setMergedCarrierWifiEnabledIfNeed_mergedCarrierEntryEmpty_doesntCrash() { + when(mCarrierConfigTracker.getCarrierProvisionsWifiMergedNetworksBool(SUB_ID)) + .thenReturn(false); + when(mAccessPointController.getMergedCarrierEntry()).thenReturn(null); + + mInternetDialogController.setMergedCarrierWifiEnabledIfNeed(SUB_ID, true); + } + + @Test + public void setMergedCarrierWifiEnabledIfNeed_neededSetMergedCarrierEntry_setTogether() { + when(mCarrierConfigTracker.getCarrierProvisionsWifiMergedNetworksBool(SUB_ID)) + .thenReturn(false); + + mInternetDialogController.setMergedCarrierWifiEnabledIfNeed(SUB_ID, true); + + verify(mMergedCarrierEntry).setEnabled(true); + + mInternetDialogController.setMergedCarrierWifiEnabledIfNeed(SUB_ID, false); + + verify(mMergedCarrierEntry).setEnabled(false); + } + + @Test + public void isWifiScanEnabled_locationOff_returnFalse() { + when(mLocationController.isLocationEnabled()).thenReturn(false); + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false); + + assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse(); + + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true); + + assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse(); + } + + @Test + public void isWifiScanEnabled_locationOn_returnIsScanAlwaysAvailable() { + when(mLocationController.isLocationEnabled()).thenReturn(true); + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false); + + assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse(); + + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true); + + assertThat(mInternetDialogController.isWifiScanEnabled()).isTrue(); + } + + private String getResourcesString(String name) { + return mContext.getResources().getString(getResourcesId(name)); + } + + private int getResourcesId(String name) { + return mContext.getResources().getIdentifier(name, "string", + mContext.getPackageName()); + } + + private class MockInternetDialogController extends InternetDialogController { + + private GlobalSettings mGlobalSettings; + private boolean mIsAirplaneModeOn; + + MockInternetDialogController(Context context, UiEventLogger uiEventLogger, + ActivityStarter starter, AccessPointController accessPointController, + SubscriptionManager subscriptionManager, TelephonyManager telephonyManager, + @Nullable WifiManager wifiManager, ConnectivityManager connectivityManager, + @Main Handler handler, @Main Executor mainExecutor, + BroadcastDispatcher broadcastDispatcher, + KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings, + KeyguardStateController keyguardStateController, WindowManager windowManager, + ToastFactory toastFactory, Handler workerHandler, + CarrierConfigTracker carrierConfigTracker, + LocationController locationController) { + super(context, uiEventLogger, starter, accessPointController, subscriptionManager, + telephonyManager, wifiManager, connectivityManager, handler, mainExecutor, + broadcastDispatcher, keyguardUpdateMonitor, globalSettings, + keyguardStateController, windowManager, toastFactory, workerHandler, + carrierConfigTracker, locationController); + mGlobalSettings = globalSettings; + } + + @Override + boolean isAirplaneModeEnabled() { + return mIsAirplaneModeOn; + } + + public void setAirplaneModeEnabled(boolean enabled) { + mIsAirplaneModeOn = enabled; + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java new file mode 100644 index 000000000000..5e1fea512d55 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -0,0 +1,385 @@ +package com.android.systemui.qs.tiles.dialog; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.telephony.TelephonyManager; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.filters.SmallTest; + +import com.android.internal.logging.UiEventLogger; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; +import com.android.wifitrackerlib.WifiEntry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class InternetDialogTest extends SysuiTestCase { + + private static final String MOBILE_NETWORK_TITLE = "Mobile Title"; + private static final String MOBILE_NETWORK_SUMMARY = "Mobile Summary"; + private static final String WIFI_TITLE = "Connected Wi-Fi Title"; + private static final String WIFI_SUMMARY = "Connected Wi-Fi Summary"; + + @Mock + private Handler mHandler; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private WifiManager mWifiManager; + @Mock + private WifiEntry mInternetWifiEntry; + @Mock + private List<WifiEntry> mWifiEntries; + @Mock + private InternetAdapter mInternetAdapter; + @Mock + private InternetDialogController mInternetDialogController; + + private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock()); + private InternetDialog mInternetDialog; + private View mDialogView; + private View mSubTitle; + private LinearLayout mEthernet; + private LinearLayout mMobileDataToggle; + private LinearLayout mWifiToggle; + private LinearLayout mConnectedWifi; + private RecyclerView mWifiList; + private LinearLayout mSeeAll; + private LinearLayout mWifiScanNotify; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt()); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE); + when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY); + when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true); + when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true); + when(mWifiEntries.size()).thenReturn(1); + + when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE); + when(mInternetDialogController.getMobileNetworkSummary()) + .thenReturn(MOBILE_NETWORK_SUMMARY); + when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager); + + mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class), + mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler, + mBgExecutor); + mInternetDialog.mAdapter = mInternetAdapter; + mInternetDialog.onAccessPointsChanged(mWifiEntries, mInternetWifiEntry); + mInternetDialog.show(); + + mDialogView = mInternetDialog.mDialogView; + mSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); + mEthernet = mDialogView.requireViewById(R.id.ethernet_layout); + mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_network_layout); + mWifiToggle = mDialogView.requireViewById(R.id.turn_on_wifi_layout); + mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout); + mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout); + mSeeAll = mDialogView.requireViewById(R.id.see_all_layout); + mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); + } + + @After + public void tearDown() { + mInternetDialog.dismissDialog(); + } + + @Test + public void hideWifiViews_WifiViewsGone() { + mInternetDialog.hideWifiViews(); + + assertThat(mInternetDialog.mIsProgressBarVisible).isFalse(); + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.GONE); + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_withApmOn_internetDialogSubTitleGone() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mSubTitle.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_withApmOff_internetDialogSubTitleVisible() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + + mInternetDialog.updateDialog(true); + + assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_apmOffAndHasEthernet_showEthernet() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + when(mInternetDialogController.hasEthernet()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_apmOffAndNoEthernet_hideEthernet() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + when(mInternetDialogController.hasEthernet()).thenReturn(false); + + mInternetDialog.updateDialog(true); + + assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_apmOnAndHasEthernet_showEthernet() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + when(mInternetDialogController.hasEthernet()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_apmOnAndNoEthernet_hideEthernet() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + when(mInternetDialogController.hasEthernet()).thenReturn(false); + + mInternetDialog.updateDialog(true); + + assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_withApmOn_mobileDataLayoutGone() { + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() { + // The preconditions WiFi ON and Internet WiFi are already in setUp() + doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); + + mInternetDialog.updateDialog(false); + + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_wifiOnAndNoConnectedWifi_hideConnectedWifi() { + // The precondition WiFi ON is already in setUp() + mInternetDialog.onAccessPointsChanged(mWifiEntries, null /* connectedEntry*/); + doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); + + mInternetDialog.updateDialog(false); + + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() { + // The precondition WiFi ON is already in setUp() + mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, mInternetWifiEntry); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() { + // The preconditions WiFi ON and WiFi entries are already in setUp() + + mInternetDialog.updateDialog(false); + + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_deviceLockedAndHasInternetWifi_showHighlightWifiToggle() { + // The preconditions WiFi ON and Internet WiFi are already in setUp() + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggle.getBackground()).isNotNull(); + } + + @Test + public void updateDialog_deviceLockedAndHasInternetWifi_hideConnectedWifi() { + // The preconditions WiFi ON and Internet WiFi are already in setUp() + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.updateDialog(false); + + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() { + // The preconditions WiFi entries are already in setUp() + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOn_hideWifiScanNotify() { + // The preconditions WiFi ON and Internet WiFi are already in setUp() + + mInternetDialog.updateDialog(false); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true); + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true); + when(mInternetDialogController.isDeviceLocked()).thenReturn(false); + + mInternetDialog.updateDialog(false); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE); + TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); + assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0); + assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull(); + } + + @Test + public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() { + mSeeAll.performClick(); + + verify(mInternetDialogController).launchNetworkSetting(); + } + + @Test + public void showProgressBar_wifiDisabled_hideProgressBar() { + Mockito.reset(mHandler); + when(mWifiManager.isWifiEnabled()).thenReturn(false); + + mInternetDialog.showProgressBar(); + + assertThat(mInternetDialog.mIsProgressBarVisible).isFalse(); + verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong()); + } + + @Test + public void showProgressBar_deviceLocked_hideProgressBar() { + Mockito.reset(mHandler); + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.showProgressBar(); + + assertThat(mInternetDialog.mIsProgressBarVisible).isFalse(); + verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong()); + } + + @Test + public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() { + Mockito.reset(mHandler); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + + mInternetDialog.showProgressBar(); + + // Show progress bar + assertThat(mInternetDialog.mIsProgressBarVisible).isTrue(); + + ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mHandler).postDelayed(runnableCaptor.capture(), + eq(InternetDialog.PROGRESS_DELAY_MS)); + runnableCaptor.getValue().run(); + + // Then hide progress bar + assertThat(mInternetDialog.mIsProgressBarVisible).isFalse(); + } + + @Test + public void showProgressBar_wifiEnabledWithoutWifiEntries_showProgressBarThenHideSearch() { + Mockito.reset(mHandler); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry*/); + + mInternetDialog.showProgressBar(); + + // Show progress bar + assertThat(mInternetDialog.mIsProgressBarVisible).isTrue(); + + ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mHandler).postDelayed(runnableCaptor.capture(), + eq(InternetDialog.PROGRESS_DELAY_MS)); + runnableCaptor.getValue().run(); + + // Then hide searching sub-title only + assertThat(mInternetDialog.mIsProgressBarVisible).isTrue(); + assertThat(mInternetDialog.mIsSearchingHidden).isTrue(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureControllerTest.java index 10c878a92745..6f081c759df7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureControllerTest.java @@ -34,6 +34,7 @@ import android.view.ScrollCaptureResponse; import androidx.test.filters.SmallTest; +import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.SysuiTestCase; import com.android.systemui.screenshot.ScrollCaptureClient.Session; @@ -274,7 +275,8 @@ public class ScrollCaptureControllerTest extends SysuiTestCase { when(client.start(/* response */ any(), /* maxPages */ anyFloat())) .thenReturn(immediateFuture(session)); return new ScrollCaptureController(context, context.getMainExecutor(), - client, new ImageTileSet(context.getMainThreadHandler())); + client, new ImageTileSet(context.getMainThreadHandler()), + new UiEventLoggerFake()); } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 21c6292c151f..f3762c566731 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -423,17 +423,18 @@ public class CommandQueueTest extends SysuiTestCase { final boolean credentialAllowed = true; final boolean requireConfirmation = true; final int userId = 10; - final String packageName = "test"; final long operationId = 1; + final String packageName = "test"; + final long requestId = 10; final int multiSensorConfig = BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT; mCommandQueue.showAuthenticationDialog(promptInfo, receiver, sensorIds, - credentialAllowed, requireConfirmation , userId, packageName, operationId, + credentialAllowed, requireConfirmation, userId, operationId, packageName, requestId, multiSensorConfig); waitForIdleSync(); verify(mCallbacks).showAuthenticationDialog(eq(promptInfo), eq(receiver), eq(sensorIds), - eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(packageName), - eq(operationId), eq(multiSensorConfig)); + eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(operationId), + eq(packageName), eq(requestId), eq(multiSensorConfig)); } @Test 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 f5ce673c249e..f5cab1df9fa2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -23,6 +23,7 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE; +import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_RESTING; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST; @@ -111,6 +112,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { 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 +184,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { 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); @@ -637,7 +640,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @Test - public void onRefreshBatteryInfo_fullChargedWithOverheat_presentCharged() { + public void onRefreshBatteryInfo_fullChargedWithOverheat_presentChargingLimited() { createController(); BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 100 /* level */, BatteryManager.BATTERY_PLUGGED_AC, @@ -649,6 +652,24 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { verifyIndicationMessage( INDICATION_TYPE_BATTERY, + mContext.getString( + R.string.keyguard_plugged_in_charging_limited, + NumberFormat.getPercentInstance().format(100 / 100f))); + } + + @Test + public void onRefreshBatteryInfo_fullChargedWithoutOverheat_presentCharged() { + createController(); + BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, + 100 /* level */, BatteryManager.BATTERY_PLUGGED_AC, + BatteryManager.BATTERY_HEALTH_GOOD, 0 /* maxChargingWattage */, + true /* present */); + + mController.getKeyguardCallback().onRefreshBatteryInfo(status); + mController.setVisible(true); + + verifyIndicationMessage( + INDICATION_TYPE_BATTERY, mContext.getString(R.string.keyguard_charged)); } @@ -677,6 +698,48 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { 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)); + } + + @Test + public void testEmptyOwnerInfoHidesIndicationArea() { + createController(); + + // GIVEN the owner info is set to an empty string + when(mLockPatternUtils.getDeviceOwnerInfo()).thenReturn(""); + + // WHEN asked to update the indication area + mController.setVisible(true); + + // THEN the owner info should be hidden + verifyHideIndication(INDICATION_TYPE_OWNER_INFO); + } + 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 000000000000..97fe25d9a619 --- /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 a7b14460f925..465370b59553 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt @@ -25,6 +25,7 @@ import android.view.View import android.view.ViewRootImpl import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.Interpolators import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.BiometricUnlockController @@ -32,6 +33,7 @@ import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.eq +import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test @@ -167,6 +169,22 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { } @Test + fun onPanelExpansionChanged_respectsMinPanelPullDownFraction() { + notificationShadeDepthController.panelPullDownMinFraction = 0.5f + notificationShadeDepthController.onPanelExpansionChanged(0.5f /* expansion */, + true /* tracking */) + assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0f) + + notificationShadeDepthController.onPanelExpansionChanged(0.75f /* expansion */, + true /* tracking */) + assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0.5f) + + notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, + true /* tracking */) + assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(1f) + } + + @Test fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(choreographer) @@ -178,10 +196,21 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun setQsPanelExpansion_appliesBlur() { + statusBarState = StatusBarState.KEYGUARD notificationShadeDepthController.qsPanelExpansion = 1f - notificationShadeDepthController.onPanelExpansionChanged(0.5f, tracking = false) + notificationShadeDepthController.onPanelExpansionChanged(1f, tracking = false) notificationShadeDepthController.updateBlurCallback.doFrame(0) - verify(blurUtils).applyBlur(any(), anyInt(), eq(false)) + verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false)) + } + + @Test + fun setQsPanelExpansion_easing() { + statusBarState = StatusBarState.KEYGUARD + notificationShadeDepthController.qsPanelExpansion = 0.25f + notificationShadeDepthController.onPanelExpansionChanged(1f, tracking = false) + notificationShadeDepthController.updateBlurCallback.doFrame(0) + verify(wallpaperManager).setWallpaperZoomOut(any(), + eq(Interpolators.getNotificationScrimAlpha(0.25f, false /* notifications */))) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt index 116f807a888d..9e103d68dd1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt @@ -44,6 +44,8 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener import com.android.systemui.util.concurrency.FakeExecution import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any @@ -90,6 +92,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock + private lateinit var deviceProvisionedController: DeviceProvisionedController + @Mock private lateinit var handler: Handler @Mock @@ -107,12 +111,15 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { private lateinit var configChangeListenerCaptor: ArgumentCaptor<ConfigurationListener> @Captor private lateinit var statusBarStateListenerCaptor: ArgumentCaptor<StateListener> + @Captor + private lateinit var deviceProvisionedCaptor: ArgumentCaptor<DeviceProvisionedListener> private lateinit var sessionListener: OnTargetsAvailableListener private lateinit var userListener: UserTracker.Callback private lateinit var settingsObserver: ContentObserver private lateinit var configChangeListener: ConfigurationListener private lateinit var statusBarStateListener: StateListener + private lateinit var deviceProvisionedListener: DeviceProvisionedListener private val clock = FakeSystemClock() private val executor = FakeExecutor(clock) @@ -144,6 +151,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { `when`(plugin.getView(any())).thenReturn(fakeSmartspaceView) `when`(userTracker.userProfiles).thenReturn(userList) `when`(statusBarStateController.dozeAmount).thenReturn(0.5f) + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true) setActiveUser(userHandlePrimary) setAllowPrivateNotifications(userHandlePrimary, true) @@ -161,11 +170,15 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { contentResolver, configurationController, statusBarStateController, + deviceProvisionedController, execution, executor, handler, Optional.of(plugin) ) + + verify(deviceProvisionedController).addCallback(capture(deviceProvisionedCaptor)) + deviceProvisionedListener = deviceProvisionedCaptor.value } @Test(expected = RuntimeException::class) @@ -180,6 +193,27 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { } @Test + fun connectOnlyAfterDeviceIsProvisioned() { + // GIVEN an unprovisioned device and an attempt to connect + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(false) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(false) + + // WHEN a connection attempt is made + controller.buildAndConnectView(fakeParent) + + // THEN no session is created + verify(smartspaceManager, never()).createSmartspaceSession(any()) + + // WHEN it does become provisioned + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true) + deviceProvisionedListener.onUserSetupChanged() + + // THEN the session is created + verify(smartspaceManager).createSmartspaceSession(any()) + } + + @Test fun testListenersAreRegistered() { // GIVEN a listener is added after a session is created connectSession() @@ -424,6 +458,20 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { assertEquals(fakeSmartspaceView, controller.view) } + @Test + fun testConnectAttemptBeforeInitializationShouldNotCreateSession() { + // GIVEN an uninitalized smartspaceView + // WHEN the device is provisioned + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true) + deviceProvisionedListener.onDeviceProvisionedChanged() + + // THEN no calls to createSmartspaceSession should occur + verify(smartspaceManager, never()).createSmartspaceSession(any()) + // THEN no listeners should be registered + verify(configurationController, never()).addCallback(any()) + } + private fun connectSession() { controller.buildAndConnectView(fakeParent) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index b03df880f0ba..4151ab2044f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -290,6 +290,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_noNotifications() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); + FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); mStackScroller.updateFooter(); @@ -299,6 +301,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_remoteInput() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(true); @@ -318,6 +321,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_oneClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); when(mEmptyShadeView.getVisibility()).thenReturn(GONE); when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL)) @@ -331,8 +335,25 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testUpdateFooter_oneClearableNotification_beforeUserSetup() { + setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(false); + + when(mEmptyShadeView.getVisibility()).thenReturn(GONE); + when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL)) + .thenReturn(true); + when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true); + + FooterView view = mock(FooterView.class); + mStackScroller.setFooterView(view); + mStackScroller.updateFooter(); + verify(mStackScroller).updateFooterView(false, true, true); + } + + @Test public void testUpdateFooter_oneNonClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(false); @@ -351,6 +372,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_atEnd() { + mStackScroller.setCurrentUserSetup(true); + // add footer mStackScroller.inflateFooterView(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java index f376e88b2cb1..42f38891b1bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -74,6 +74,7 @@ import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; @@ -98,6 +99,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; @Mock private TunerService mTunerService; + @Mock private DeviceProvisionedController mDeviceProvisionedController; @Mock private DynamicPrivacyController mDynamicPrivacyController; @Mock private ConfigurationController mConfigurationController; @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @@ -153,6 +155,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { mHeadsUpManager, mNotificationRoundnessManager, mTunerService, + mDeviceProvisionedController, mDynamicPrivacyController, mConfigurationController, mSysuiStatusBarStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index 690b8415762d..1043faa8b1bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -16,24 +16,37 @@ package com.android.systemui.statusbar.phone; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; + import static com.google.common.truth.Truth.assertThat; +import static org.mockito.AdditionalAnswers.returnsFirstArg; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import android.content.res.Resources; import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; +import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.doze.util.BurnInHelperKt; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; @SmallTest @RunWith(AndroidTestingRunner.class) public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private static final int SCREEN_HEIGHT = 2000; - private static final int EMPTY_MARGIN = 0; private static final int EMPTY_HEIGHT = 0; private static final float ZERO_DRAG = 0.f; private static final float OPAQUE = 1.f; @@ -41,10 +54,15 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private static final boolean HAS_CUSTOM_CLOCK = false; private static final boolean HAS_VISIBLE_NOTIFS = false; + @Mock + private Resources mResources; + private KeyguardClockPositionAlgorithm mClockPositionAlgorithm; private KeyguardClockPositionAlgorithm.Result mClockPosition; + private MockitoSession mStaticMockSession; private int mNotificationStackHeight; private float mPanelExpansion; + private int mKeyguardStatusBarHeaderHeight; private int mKeyguardStatusHeight; private float mDark; private boolean mHasCustomClock; @@ -52,16 +70,32 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private float mQsExpansion; private int mCutoutTopInset = 0; // in pixels private boolean mIsSplitShade = false; + private float mUdfpsTop = -1; + private float mClockBottom = SCREEN_HEIGHT / 2; + private boolean mClockTopAligned; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + mStaticMockSession = mockitoSession() + .mockStatic(BurnInHelperKt.class) + .startMocking(); + mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm(); + when(mResources.getDimensionPixelSize(anyInt())).thenReturn(0); + mClockPositionAlgorithm.loadDimens(mResources); + mClockPosition = new KeyguardClockPositionAlgorithm.Result(); mHasCustomClock = HAS_CUSTOM_CLOCK; mHasVisibleNotifs = HAS_VISIBLE_NOTIFS; } + @After + public void tearDown() { + mStaticMockSession.finishMocking(); + } + @Test public void clockPositionTopOfScreenOnAOD() { // GIVEN on AOD and both stack scroll and clock have 0 height @@ -338,6 +372,155 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT); } + @Test + public void clockPositionMinimizesBurnInMovementToAvoidUdfpsOnAOD() { + // GIVEN a center aligned clock + mClockTopAligned = false; + + // GIVEN the clock + udfps are 100px apart + mClockBottom = SCREEN_HEIGHT - 500; + mUdfpsTop = SCREEN_HEIGHT - 400; + + // GIVEN it's AOD and the burn-in y value is 200 + givenAOD(); + givenMaxBurnInOffset(200); + + // WHEN the clock position algorithm is run with the highest burn in offset + givenHighestBurnInOffset(); + positionClock(); + + // THEN the worst-case clock Y position is shifted only by 100 (not the full 200), + // so that it's at the same location as mUdfpsTop + assertThat(mClockPosition.clockY).isEqualTo(100); + + // WHEN the clock position algorithm is run with the lowest burn in offset + givenLowestBurnInOffset(); + positionClock(); + + // THEN lowest case starts at mCutoutTopInset + assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset); + } + + @Test + public void clockPositionShiftsToAvoidUdfpsOnAOD_usesSpaceAboveClock() { + // GIVEN a center aligned clock + mClockTopAligned = false; + + // GIVEN there's space at the top of the screen on LS (that's available to be used for + // burn-in on AOD) + mKeyguardStatusBarHeaderHeight = 150; + + // GIVEN the bottom of the clock is beyond the top of UDFPS + mClockBottom = SCREEN_HEIGHT - 300; + mUdfpsTop = SCREEN_HEIGHT - 400; + + // GIVEN it's AOD and the burn-in y value is 200 + givenAOD(); + givenMaxBurnInOffset(200); + + // WHEN the clock position algorithm is run with the highest burn in offset + givenHighestBurnInOffset(); + positionClock(); + + // THEN the algo should shift the clock up and use the area above the clock for + // burn-in since the burn in offset > space above clock + assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight); + + // WHEN the clock position algorithm is run with the lowest burn in offset + givenLowestBurnInOffset(); + positionClock(); + + // THEN lowest case starts at mCutoutTopInset (0 in this case) + assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset); + } + + @Test + public void clockPositionShiftsToAvoidUdfpsOnAOD_usesMaxBurnInOffset() { + // GIVEN a center aligned clock + mClockTopAligned = false; + + // GIVEN there's 200px space at the top of the screen on LS (that's available to be used for + // burn-in on AOD) but 50px are taken up by the cutout + mKeyguardStatusBarHeaderHeight = 200; + mCutoutTopInset = 50; + + // GIVEN the bottom of the clock is beyond the top of UDFPS + mClockBottom = SCREEN_HEIGHT - 300; + mUdfpsTop = SCREEN_HEIGHT - 400; + + // GIVEN it's AOD and the burn-in y value is only 25px (less than space above clock) + givenAOD(); + int maxYBurnInOffset = 25; + givenMaxBurnInOffset(maxYBurnInOffset); + + // WHEN the clock position algorithm is run with the highest burn in offset + givenHighestBurnInOffset(); + positionClock(); + + // THEN the algo should shift the clock up and use the area above the clock for + // burn-in + assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight); + + // WHEN the clock position algorithm is run with the lowest burn in offset + givenLowestBurnInOffset(); + positionClock(); + + // THEN lowest case starts above mKeyguardStatusBarHeaderHeight + assertThat(mClockPosition.clockY).isEqualTo( + mKeyguardStatusBarHeaderHeight - 2 * maxYBurnInOffset); + } + + @Test + public void clockPositionShiftsToMaximizeUdfpsBurnInMovement() { + // GIVEN a center aligned clock + mClockTopAligned = false; + + // GIVEN there's 200px space at the top of the screen on LS (that's available to be used for + // burn-in on AOD) but 50px are taken up by the cutout + mKeyguardStatusBarHeaderHeight = 200; + mCutoutTopInset = 50; + int upperSpaceAvailable = mKeyguardStatusBarHeaderHeight - mCutoutTopInset; + + // GIVEN the bottom of the clock and the top of UDFPS are 100px apart + mClockBottom = SCREEN_HEIGHT - 500; + mUdfpsTop = SCREEN_HEIGHT - 400; + float lowerSpaceAvailable = mUdfpsTop - mClockBottom; + + // GIVEN it's AOD and the burn-in y value is 200 + givenAOD(); + givenMaxBurnInOffset(200); + + // WHEN the clock position algorithm is run with the highest burn in offset + givenHighestBurnInOffset(); + positionClock(); + + // THEN the algo should shift the clock up and use both the area above + // the clock and below the clock (vertically centered in its allowed area) + assertThat(mClockPosition.clockY).isEqualTo( + (int) (mCutoutTopInset + upperSpaceAvailable + lowerSpaceAvailable)); + + // WHEN the clock position algorithm is run with the lowest burn in offset + givenLowestBurnInOffset(); + positionClock(); + + // THEN lowest case starts at mCutoutTopInset + assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset); + } + + private void givenHighestBurnInOffset() { + when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).then(returnsFirstArg()); + } + + private void givenLowestBurnInOffset() { + when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).thenReturn(0); + } + + private void givenMaxBurnInOffset(int offset) { + when(mResources.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y_large_clock)) + .thenReturn(offset); + mClockPositionAlgorithm.loadDimens(mResources); + } + private void givenAOD() { mPanelExpansion = 1.f; mDark = 1.f; @@ -348,13 +531,33 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { mDark = 0.f; } + /** + * Setup and run the clock position algorithm. + * + * mClockPosition.clockY will contain the top y-coordinate for the clock position + */ private void positionClock() { - mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight, - mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, - 0 /* userSwitchHeight */, 0 /* userSwitchPreferredY */, - mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */, - 0 /* unlockedStackScrollerPadding */, mQsExpansion, - mCutoutTopInset, mIsSplitShade); + mClockPositionAlgorithm.setup( + mKeyguardStatusBarHeaderHeight, + SCREEN_HEIGHT, + mNotificationStackHeight, + mPanelExpansion, + SCREEN_HEIGHT, + mKeyguardStatusHeight, + 0 /* userSwitchHeight */, + 0 /* userSwitchPreferredY */, + mHasCustomClock, + mHasVisibleNotifs, + mDark, + ZERO_DRAG, + false /* bypassEnabled */, + 0 /* unlockedStackScrollerPadding */, + mQsExpansion, + mCutoutTopInset, + mIsSplitShade, + mUdfpsTop, + mClockBottom, + mClockTopAligned); mClockPositionAlgorithm.run(mClockPosition); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 525bb1c641fd..1b0b40408b60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -142,7 +142,7 @@ import java.util.List; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class NotificationPanelViewTest extends SysuiTestCase { +public class NotificationPanelViewControllerTest extends SysuiTestCase { private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50; @@ -474,6 +474,12 @@ public class NotificationPanelViewTest extends SysuiTestCase { } @Test + public void testSetMinFraction() { + mNotificationPanelViewController.setMinFraction(0.5f); + verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f)); + } + + @Test public void testSetDozing_notifiesNsslAndStateController() { mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */, null /* touch */); 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 ddd78541d113..90b8a74d88be 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 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { 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 9b7c78f7dba1..aafaebd959f0 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; @@ -56,6 +61,8 @@ import com.android.systemui.util.InjectionInflationController; 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; @@ -93,6 +100,10 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController; @Mock private LockIconViewController mLockIconViewController; + @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler> + mInteractionEventHandlerCaptor; + private NotificationShadeWindowView.InteractionEventHandler mInteractionEventHandler; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -150,4 +161,49 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { 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 c71318fa9464..47c8806be6d4 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 @@ -624,7 +624,7 @@ public class ScrimControllerTest extends SysuiTestCase { assertScrimTinted(Map.of( mScrimInFront, false, - mScrimBehind, false, + mScrimBehind, true, mScrimForBubble, true )); @@ -705,7 +705,7 @@ public class ScrimControllerTest extends SysuiTestCase { public void qsExpansion_half_clippingQs() { reset(mScrimBehind); mScrimController.setClipsQsScrim(true); - mScrimController.setQsPosition(0.5f, 999 /* value doesn't matter */); + mScrimController.setQsPosition(0.25f, 999 /* value doesn't matter */); finishAnimationsImmediately(); assertScrimAlpha(Map.of( @@ -744,13 +744,6 @@ public class ScrimControllerTest extends SysuiTestCase { finishAnimationsImmediately(); mScrimController.transitionTo(ScrimState.UNLOCKED); - // Immediately tinted black after the transition starts - assertScrimTinted(Map.of( - mScrimInFront, true, - mScrimBehind, true, - mScrimForBubble, true - )); - finishAnimationsImmediately(); // All scrims should be transparent at the end of fade transition. @@ -1143,7 +1136,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void testScrimsVisible_whenShadeVisibleOnLockscreen() { mScrimController.transitionTo(ScrimState.KEYGUARD); - mScrimController.setQsPosition(0.5f, 300); + mScrimController.setQsPosition(0.25f, 300); assertScrimAlpha(Map.of( mScrimBehind, SEMI_TRANSPARENT, 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 c39a9061f95d..5ed69853e40f 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 @@ -102,6 +102,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @Mock + private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor; + @Mock private KeyguardMessageArea mKeyguardMessageArea; private WakefulnessLifecycle mWakefulnessLifecycle; @@ -287,6 +289,24 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void testShowing_whenAlternateAuthShowing() { + mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); + when(mBouncer.isShowing()).thenReturn(false); + when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true); + assertTrue("Is showing not accurate when alternative auth showing", + mStatusBarKeyguardViewManager.isShowing()); + } + + @Test + public void testWillBeShowing_whenAlternateAuthShowing() { + mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); + when(mBouncer.isShowing()).thenReturn(false); + when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true); + assertTrue("Is or will be showing not accurate when alternative auth showing", + mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()); + } + + @Test public void testUpdateResources_delegatesToBouncer() { mStatusBarKeyguardViewManager.updateResources(); @@ -299,18 +319,4 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { verify(mBouncer).updateKeyguardPosition(1.0f); } - - @Test - public void testNavBarHiddenWhenSleepAnimationStarts() { - mStatusBarKeyguardViewManager.hide(0 /* startTime */, 0 /* fadeoutDuration */); - assertTrue(mStatusBarKeyguardViewManager.isNavBarVisible()); - - // Verify that the nav bar is hidden when the screen off animation starts - doReturn(true).when(mUnlockedScreenOffAnimationController).isScreenOffAnimationPlaying(); - mWakefulnessLifecycle.dispatchFinishedGoingToSleep(); - assertFalse(mStatusBarKeyguardViewManager.isNavBarVisible()); - - mWakefulnessLifecycle.dispatchFinishedWakingUp(); - assertTrue(mStatusBarKeyguardViewManager.isNavBarVisible()); - } } 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 bd9835c0e8e3..6051c5615f8d 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 @@ -824,6 +824,34 @@ public class StatusBarTest extends SysuiTestCase { } @Test + public void testSetExpansionAffectsAlpha_onlyWhenHidingKeyguard() { + mStatusBar.updateScrimController(); + verify(mScrimController).setExpansionAffectsAlpha(eq(true)); + + clearInvocations(mScrimController); + when(mBiometricUnlockController.isBiometricUnlock()).thenReturn(true); + mStatusBar.updateScrimController(); + verify(mScrimController).setExpansionAffectsAlpha(eq(true)); + + clearInvocations(mScrimController); + when(mKeyguardStateController.isShowing()).thenReturn(true); + mStatusBar.updateScrimController(); + verify(mScrimController).setExpansionAffectsAlpha(eq(false)); + + clearInvocations(mScrimController); + reset(mKeyguardStateController); + when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true); + mStatusBar.updateScrimController(); + verify(mScrimController).setExpansionAffectsAlpha(eq(false)); + + clearInvocations(mScrimController); + reset(mKeyguardStateController); + when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); + mStatusBar.updateScrimController(); + verify(mScrimController).setExpansionAffectsAlpha(eq(false)); + } + + @Test public void testTransitionLaunch_noPreview_doesntGoUnlocked() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); mStatusBar.showKeyguardImpl(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt index d26db4c69ece..b7c4d0a7d223 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt @@ -221,6 +221,18 @@ class OngoingCallControllerTest : SysuiTestCase() { verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean()) } + /** Regression test for b/201097913. */ + @Test + fun onEntryCleanUp_callNotifAddedThenRemoved_listenerNotified() { + val ongoingCallNotifEntry = createOngoingCallNotifEntry() + notifCollectionListener.onEntryAdded(ongoingCallNotifEntry) + reset(mockOngoingCallListener) + + notifCollectionListener.onEntryCleanUp(ongoingCallNotifEntry) + + verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean()) + } + /** Regression test for b/188491504. */ @Test fun onEntryRemoved_removedNotifHasSameKeyAsAddedNotif_listenerNotified() { 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 57198dbe18bb..4a5770d12239 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 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { 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 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { 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/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt new file mode 100644 index 000000000000..871a48c503be --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt @@ -0,0 +1,176 @@ +/* + * 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.statusbar.policy + +import android.os.Handler +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +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.Mockito.`when` +import org.mockito.Mockito.anyString +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations +import java.util.Date + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +@SmallTest +class VariableDateViewControllerTest : SysuiTestCase() { + + companion object { + private const val TIME_STAMP = 1_500_000_000_000 + private const val LONG_PATTERN = "EEEMMMd" + private const val SHORT_PATTERN = "MMMd" + private const val CHAR_WIDTH = 10f + } + + @Mock + private lateinit var broadcastDispatcher: BroadcastDispatcher + @Mock + private lateinit var view: VariableDateView + @Captor + private lateinit var onMeasureListenerCaptor: ArgumentCaptor<VariableDateView.OnMeasureListener> + + private var lastText: String? = null + + private lateinit var systemClock: FakeSystemClock + private lateinit var testableLooper: TestableLooper + private lateinit var testableHandler: Handler + private lateinit var controller: VariableDateViewController + + private lateinit var longText: String + private lateinit var shortText: String + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + testableLooper = TestableLooper.get(this) + testableHandler = Handler(testableLooper.looper) + + systemClock = FakeSystemClock() + systemClock.setCurrentTimeMillis(TIME_STAMP) + + `when`(view.longerPattern).thenReturn(LONG_PATTERN) + `when`(view.shorterPattern).thenReturn(SHORT_PATTERN) + `when`(view.handler).thenReturn(testableHandler) + + `when`(view.setText(anyString())).thenAnswer { + lastText = it.arguments[0] as? String + Unit + } + `when`(view.isAttachedToWindow).thenReturn(true) + + val date = Date(TIME_STAMP) + longText = getTextForFormat(date, getFormatFromPattern(LONG_PATTERN)) + shortText = getTextForFormat(date, getFormatFromPattern(SHORT_PATTERN)) + + // Assume some sizes for the text, the controller doesn't need to know if these sizes are + // the true ones + `when`(view.getDesiredWidthForText(any())).thenAnswer { + getTextLength(it.arguments[0] as CharSequence) + } + + controller = VariableDateViewController( + systemClock, + broadcastDispatcher, + testableHandler, + view + ) + + controller.init() + testableLooper.processAllMessages() + + verify(view).onAttach(capture(onMeasureListenerCaptor)) + } + + @Test + fun testViewStartsWithLongText() { + assertThat(lastText).isEqualTo(longText) + } + + @Test + fun testListenerNotNull() { + assertThat(onMeasureListenerCaptor.value).isNotNull() + } + + @Test + fun testLotsOfSpaceUseLongText() { + onMeasureListenerCaptor.value.onMeasureAction(10000) + + testableLooper.processAllMessages() + assertThat(lastText).isEqualTo(longText) + } + + @Test + fun testSmallSpaceUseEmpty() { + onMeasureListenerCaptor.value.onMeasureAction(1) + testableLooper.processAllMessages() + + assertThat(lastText).isEmpty() + } + + @Test + fun testSpaceInBetweenUseShortText() { + val average = ((getTextLength(longText) + getTextLength(shortText)) / 2).toInt() + + onMeasureListenerCaptor.value.onMeasureAction(average) + testableLooper.processAllMessages() + + assertThat(lastText).isEqualTo(shortText) + } + + @Test + fun testSwitchBackToLonger() { + onMeasureListenerCaptor.value.onMeasureAction(1) + testableLooper.processAllMessages() + + onMeasureListenerCaptor.value.onMeasureAction(10000) + testableLooper.processAllMessages() + + assertThat(lastText).isEqualTo(longText) + } + + @Test + fun testNoSwitchingWhenFrozen() { + `when`(view.freezeSwitching).thenReturn(true) + + val average = ((getTextLength(longText) + getTextLength(shortText)) / 2).toInt() + onMeasureListenerCaptor.value.onMeasureAction(average) + testableLooper.processAllMessages() + assertThat(lastText).isEqualTo(longText) + + onMeasureListenerCaptor.value.onMeasureAction(1) + testableLooper.processAllMessages() + assertThat(lastText).isEqualTo(longText) + } + + private fun getTextLength(text: CharSequence): Float { + return text.length * CHAR_WIDTH + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java index 9c47f19b20c8..2c461ae1b598 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java @@ -103,7 +103,8 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - mManager = new ThemeOverlayApplier(mOverlayManager, MoreExecutors.directExecutor(), + mManager = new ThemeOverlayApplier(mOverlayManager, + MoreExecutors.directExecutor(), MoreExecutors.directExecutor(), LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE, mDumpManager) { @Override protected OverlayManagerTransaction.Builder getTransactionBuilder() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt new file mode 100644 index 000000000000..eebcbe63d004 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt @@ -0,0 +1,89 @@ +/* + * 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.usb + +import android.app.PendingIntent +import android.content.Intent +import android.hardware.usb.IUsbSerialReader +import android.hardware.usb.UsbAccessory +import android.hardware.usb.UsbManager +import android.testing.AndroidTestingRunner +import android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS +import androidx.test.filters.SmallTest +import androidx.test.rule.ActivityTestRule +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import java.lang.Exception + +/** + * UsbPermissionActivityTest + */ +@RunWith(AndroidTestingRunner::class) +@SmallTest +class UsbPermissionActivityTest : SysuiTestCase() { + + class UsbPermissionActivityTestable : UsbPermissionActivity() + + @Rule + @JvmField + var activityRule = ActivityTestRule<UsbPermissionActivityTestable>( + UsbPermissionActivityTestable::class.java, false, false) + + private val activityIntent = Intent(mContext, UsbPermissionActivityTestable::class.java) + .apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + putExtra(UsbManager.EXTRA_PACKAGE, "com.android.systemui") + putExtra(Intent.EXTRA_INTENT, PendingIntent.getBroadcast( + mContext, + 334, + Intent("NO_ACTION"), + PendingIntent.FLAG_MUTABLE)) + putExtra(UsbManager.EXTRA_ACCESSORY, UsbAccessory( + "manufacturer", + "model", + "description", + "version", + "uri", + object : IUsbSerialReader.Stub() { + override fun getSerial(packageName: String): String { + return "serial" + } + })) + } + + @Before + fun setUp() { + activityRule.launchActivity(activityIntent) + } + + @After + fun tearDown() { + activityRule.finishActivity() + } + + @Test + @Throws(Exception::class) + fun testHideNonSystemOverlay() { + assertThat(activityRule.activity.window.attributes.privateFlags and + SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) + .isEqualTo(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java index a34c5986f36c..0e9d96c61e54 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java @@ -16,6 +16,8 @@ package com.android.systemui.util.sensors; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -338,30 +340,25 @@ public class ProximitySensorDualTest extends SysuiTestCase { @Test public void testSecondaryCancelsSecondary() { TestableListener listener = new TestableListener(); - ThresholdSensor.Listener cancelingListener = new ThresholdSensor.Listener() { - @Override - public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent event) { - mProximitySensor.pause(); - } - }; + ThresholdSensor.Listener cancelingListener = event -> mProximitySensor.pause(); mProximitySensor.register(listener); mProximitySensor.register(cancelingListener); - assertNull(listener.mLastEvent); - assertEquals(0, listener.mCallCount); + assertThat(listener.mLastEvent).isNull(); + assertThat(listener.mCallCount).isEqualTo(0); mThresholdSensorPrimary.triggerEvent(true, 0); - assertNull(listener.mLastEvent); - assertEquals(0, listener.mCallCount); + assertThat(listener.mLastEvent).isNull(); + assertThat(listener.mCallCount).isEqualTo(0); mThresholdSensorSecondary.triggerEvent(true, 0); - assertTrue(listener.mLastEvent.getBelow()); - assertEquals(1, listener.mCallCount); + assertThat(listener.mLastEvent.getBelow()).isTrue(); + assertThat(listener.mCallCount).isEqualTo(1); // The proximity sensor should now be canceled. Advancing the clock should do nothing. - assertEquals(0, mFakeExecutor.numPending()); + assertThat(mFakeExecutor.numPending()).isEqualTo(0); mThresholdSensorSecondary.triggerEvent(false, 1); - assertTrue(listener.mLastEvent.getBelow()); - assertEquals(1, listener.mCallCount); + assertThat(listener.mLastEvent.getBelow()).isTrue(); + assertThat(listener.mCallCount).isEqualTo(1); mProximitySensor.unregister(listener); } @@ -372,33 +369,66 @@ public class ProximitySensorDualTest extends SysuiTestCase { TestableListener listener = new TestableListener(); - // WE immediately register the secondary sensor. + // We immediately register the secondary sensor. mProximitySensor.register(listener); - assertFalse(mThresholdSensorPrimary.isPaused()); - assertFalse(mThresholdSensorSecondary.isPaused()); - assertNull(listener.mLastEvent); - assertEquals(0, listener.mCallCount); + assertThat(mThresholdSensorPrimary.isPaused()).isTrue(); + assertThat(mThresholdSensorSecondary.isPaused()).isFalse(); + assertThat(listener.mLastEvent).isNull(); + assertThat(listener.mCallCount).isEqualTo(0); mThresholdSensorPrimary.triggerEvent(true, 0); - assertNull(listener.mLastEvent); - assertEquals(0, listener.mCallCount); + assertThat(listener.mLastEvent).isNull(); + assertThat(listener.mCallCount).isEqualTo(0); mThresholdSensorSecondary.triggerEvent(true, 0); - assertTrue(listener.mLastEvent.getBelow()); - assertEquals(1, listener.mCallCount); + assertThat(listener.mLastEvent.getBelow()).isTrue(); + assertThat(listener.mCallCount).isEqualTo(1); // The secondary sensor should now remain resumed indefinitely. - assertFalse(mThresholdSensorSecondary.isPaused()); + assertThat(mThresholdSensorSecondary.isPaused()).isFalse(); mThresholdSensorSecondary.triggerEvent(false, 1); - assertFalse(listener.mLastEvent.getBelow()); - assertEquals(2, listener.mCallCount); + assertThat(listener.mLastEvent.getBelow()).isFalse(); + assertThat(listener.mCallCount).isEqualTo(2); // The secondary is still running, and not polling with the executor. - assertFalse(mThresholdSensorSecondary.isPaused()); - assertEquals(0, mFakeExecutor.numPending()); + assertThat(mThresholdSensorSecondary.isPaused()).isFalse(); + assertThat(mFakeExecutor.numPending()).isEqualTo(0); mProximitySensor.unregister(listener); } + @Test + public void testSecondaryPausesPrimary() { + TestableListener listener = new TestableListener(); + + mProximitySensor.register(listener); + + assertThat(mThresholdSensorPrimary.isPaused()).isFalse(); + assertThat(mThresholdSensorSecondary.isPaused()).isTrue(); + + mProximitySensor.setSecondarySafe(true); + + assertThat(mThresholdSensorPrimary.isPaused()).isTrue(); + assertThat(mThresholdSensorSecondary.isPaused()).isFalse(); + } + + @Test + public void testSecondaryResumesPrimary() { + mProximitySensor.setSecondarySafe(true); + + TestableListener listener = new TestableListener(); + mProximitySensor.register(listener); + + assertThat(mThresholdSensorPrimary.isPaused()).isTrue(); + assertThat(mThresholdSensorSecondary.isPaused()).isFalse(); + + mProximitySensor.setSecondarySafe(false); + + assertThat(mThresholdSensorPrimary.isPaused()).isFalse(); + assertThat(mThresholdSensorSecondary.isPaused()).isTrue(); + + + } + private static class TestableListener implements ThresholdSensor.Listener { ThresholdSensor.ThresholdSensorEvent mLastEvent; int mCallCount = 0; diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettings.java b/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettings.java index 69764227040b..7bb26748a9d9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettings.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettings.java @@ -31,6 +31,7 @@ public class FakeSettings implements SecureSettings, GlobalSettings, SystemSetti private final Map<SettingsKey, String> mValues = new HashMap<>(); private final Map<SettingsKey, List<ContentObserver>> mContentObservers = new HashMap<>(); + private final Map<String, List<ContentObserver>> mContentObserversAllUsers = new HashMap<>(); public static final Uri CONTENT_URI = Uri.parse("content://settings/fake"); @@ -55,9 +56,15 @@ public class FakeSettings implements SecureSettings, GlobalSettings, SystemSetti @Override public void registerContentObserverForUser(Uri uri, boolean notifyDescendents, ContentObserver settingsObserver, int userHandle) { - SettingsKey key = new SettingsKey(userHandle, uri.toString()); - mContentObservers.putIfAbsent(key, new ArrayList<>()); - List<ContentObserver> observers = mContentObservers.get(key); + List<ContentObserver> observers; + if (userHandle == UserHandle.USER_ALL) { + mContentObserversAllUsers.putIfAbsent(uri.toString(), new ArrayList<>()); + observers = mContentObserversAllUsers.get(uri.toString()); + } else { + SettingsKey key = new SettingsKey(userHandle, uri.toString()); + mContentObservers.putIfAbsent(key, new ArrayList<>()); + observers = mContentObservers.get(key); + } observers.add(settingsObserver); } @@ -67,6 +74,10 @@ public class FakeSettings implements SecureSettings, GlobalSettings, SystemSetti List<ContentObserver> observers = mContentObservers.get(key); observers.remove(settingsObserver); } + for (String key : mContentObserversAllUsers.keySet()) { + List<ContentObserver> observers = mContentObserversAllUsers.get(key); + observers.remove(settingsObserver); + } } @Override @@ -114,6 +125,10 @@ public class FakeSettings implements SecureSettings, GlobalSettings, SystemSetti for (ContentObserver observer : mContentObservers.getOrDefault(key, new ArrayList<>())) { observer.dispatchChange(false, List.of(uri), userHandle); } + for (ContentObserver observer : + mContentObserversAllUsers.getOrDefault(uri.toString(), new ArrayList<>())) { + observer.dispatchChange(false, List.of(uri), userHandle); + } return true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettingsTest.java index 0d560f237a07..34cae58d30e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettingsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/FakeSettingsTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.database.ContentObserver; +import android.os.UserHandle; import android.provider.Settings; import android.testing.AndroidTestingRunner; @@ -89,6 +90,16 @@ public class FakeSettingsTest extends SysuiTestCase { } @Test + public void testRegisterContentObserverAllUsers() { + mFakeSettings.registerContentObserverForUser( + mFakeSettings.getUriFor("cat"), false, mContentObserver, UserHandle.USER_ALL); + + mFakeSettings.putString("cat", "hat"); + + verify(mContentObserver).dispatchChange(anyBoolean(), any(Collection.class), anyInt()); + } + + @Test public void testUnregisterContentObserver() { mFakeSettings.registerContentObserver("cat", mContentObserver); mFakeSettings.unregisterContentObserver(mContentObserver); @@ -98,4 +109,16 @@ public class FakeSettingsTest extends SysuiTestCase { verify(mContentObserver, never()).dispatchChange( anyBoolean(), any(Collection.class), anyInt()); } + + @Test + public void testUnregisterContentObserverAllUsers() { + mFakeSettings.registerContentObserverForUser( + mFakeSettings.getUriFor("cat"), false, mContentObserver, UserHandle.USER_ALL); + mFakeSettings.unregisterContentObserver(mContentObserver); + + mFakeSettings.putString("cat", "hat"); + + verify(mContentObserver, never()).dispatchChange( + anyBoolean(), any(Collection.class), anyInt()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java index be110242a3eb..4f9cb35db1a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java @@ -51,6 +51,11 @@ public class FakeRotationLockController extends BaseLeakChecker<RotationLockCont } @Override + public boolean isCameraRotationEnabled() { + return false; + } + + @Override public void setRotationLockedAtAngle(boolean locked, int rotation) { } diff --git a/packages/VpnDialogs/res/values-as/strings.xml b/packages/VpnDialogs/res/values-as/strings.xml index 4669a6941cf4..3f2e2347135d 100644 --- a/packages/VpnDialogs/res/values-as/strings.xml +++ b/packages/VpnDialogs/res/values-as/strings.xml @@ -17,7 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"সংযোগৰ অনুৰোধ"</string> - <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীণৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string> + <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীনৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string> <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>এ এটা ভিপিএন সংযোগ ছেট আপ কৰিব বিচাৰে, যিটোৱে ইয়াক নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ দিয়ে। আপুনি উৎসটোক বিশ্বাস কৰিলেহে গ্ৰহণ কৰক। ভিপিএনটো সক্ৰিয় হৈ থকাৰ সময়ত আপোনাৰ স্ক্ৰীনত<br /> <br /> <img src=vpn_icon /> প্ৰদৰ্শিত হয়।"</string> <string name="legacy_title" msgid="192936250066580964">"ভিপিএন সংযোগ হৈ আছে"</string> <string name="session" msgid="6470628549473641030">"ছেশ্বন:"</string> @@ -29,7 +29,7 @@ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>ক সকলো সময়তে সংযুক্ত হৈ থাকিবলৈ ছেট কৰি থোৱা হৈছে, কিন্তু ই বৰ্তমান সংযোগ কৰিবপৰা নাই। আপোনাৰ ফ\'নটোৱে <xliff:g id="VPN_APP_1">%1$s</xliff:g>ৰ সৈতে সংযোগ কৰিব নোৱাৰালৈকে এটা ৰাজহুৱা নেটৱৰ্ক ব্যৱহাৰ কৰিব।"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>ক সকলো সময়তে সংযুক্ত হৈ থাকিবলৈ ছেট কৰি থোৱা হৈছে, কিন্তু ই বৰ্তমান সংযোগ কৰিবপৰা নাই। ভিপিএনটোৰ সৈতে পুনৰ সংযুক্ত নোহোৱালৈকে আপোনাৰ কোনো সংযোগ নাথাকিব।"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> - <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"ভিপিএন ছেটিংসমূহ সলনি কৰক"</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"ভিপিএন ছেটিং সলনি কৰক"</string> <string name="configure" msgid="4905518375574791375">"কনফিগাৰ কৰক"</string> <string name="disconnect" msgid="971412338304200056">"সংযোগ বিচ্ছিন্ন কৰক"</string> <string name="open_app" msgid="3717639178595958667">"এপ্ খোলক"</string> diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml index 059008f3674e..88a588c5eddc 100644 --- a/packages/VpnDialogs/res/values-in/strings.xml +++ b/packages/VpnDialogs/res/values-in/strings.xml @@ -19,19 +19,19 @@ <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan sambungan VPN yang memungkinkannya memantau traffic jaringan. Terima hanya jika Anda memercayai sumber. <br /> <br /> <img src=vpn_icon /> muncul di bagian atas layar Anda saat VPN aktif."</string> <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan koneksi VPN yang memungkinkannya memantau traffic jaringan. Hanya terima jika Anda memercayai sumbernya. <br /> <br /> <img src=vpn_icon /> muncul di layar bila VPN aktif."</string> - <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string> + <string name="legacy_title" msgid="192936250066580964">"VPN terhubung"</string> <string name="session" msgid="6470628549473641030">"Sesi:"</string> <string name="duration" msgid="3584782459928719435">"Durasi:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Terkirim:"</string> <string name="data_received" msgid="4062776929376067820">"Diterima:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bita / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> - <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat tersambung ke VPN yang selalu aktif"</string> - <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Ponsel akan menggunakan jaringan publik sampai dapat tersambung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> - <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Anda akan tersambung jika VPN dapat tersambung ulang."</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat terhubung ke VPN yang selalu aktif"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Ponsel akan menggunakan jaringan publik sampai dapat terhubung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Anda akan terhubung jika VPN dapat terhubung ulang."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ubah setelan VPN"</string> <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> - <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> + <string name="disconnect" msgid="971412338304200056">"Putuskan koneksi"</string> <string name="open_app" msgid="3717639178595958667">"Buka aplikasi"</string> <string name="dismiss" msgid="6192859333764711227">"Tutup"</string> </resources> diff --git a/packages/VpnDialogs/res/values-te/strings.xml b/packages/VpnDialogs/res/values-te/strings.xml index 2316c62785d9..8f8ff0778d06 100644 --- a/packages/VpnDialogs/res/values-te/strings.xml +++ b/packages/VpnDialogs/res/values-te/strings.xml @@ -16,7 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="prompt" msgid="3183836924226407828">"కనెక్షన్ అభ్యర్థన"</string> + <string name="prompt" msgid="3183836924226407828">"కనెక్షన్ రిక్వెస్ట్"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> నెట్వర్క్ ట్రాఫిక్ని పర్యవేక్షించగలగడానికి VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు మూలాన్ని విశ్వసిస్తే మాత్రమే ఆమోదించండి. VPN సక్రియంగా ఉన్నప్పుడు మీ స్క్రీన్ ఎగువన <br /> <br /> <img src=vpn_icon /> కనిపిస్తుంది."</string> <string name="warning" product="tv" msgid="5188957997628124947">"నెట్వర్క్ ట్రాఫిక్ను పర్యవేక్షించగలగడానికి, <xliff:g id="APP">%s</xliff:g> VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు సోర్స్ను విశ్వసిస్తే మాత్రమే ఆమోదించండి. <br /> <br /> <img src=vpn_icon /> VPN యాక్టివ్గా ఉన్నప్పుడు మీ స్క్రీన్ పై కనిపిస్తుంది."</string> <string name="legacy_title" msgid="192936250066580964">"VPN కనెక్ట్ చేయబడింది"</string> diff --git a/packages/services/CameraExtensionsProxy/AndroidManifest.xml b/packages/services/CameraExtensionsProxy/AndroidManifest.xml index d35689413749..ef1d581d717e 100644 --- a/packages/services/CameraExtensionsProxy/AndroidManifest.xml +++ b/packages/services/CameraExtensionsProxy/AndroidManifest.xml @@ -8,6 +8,7 @@ android:directBootAware="true"> <service android:name=".CameraExtensionsProxyService" + android:visibleToInstantApps="true" android:exported="true"> </service> <uses-library android:name="androidx.camera.extensions.impl" android:required="false" /> diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 8a42ddfdc19d..757f1aeb275f 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -1072,26 +1072,18 @@ public final class ContentCaptureManagerService extends ParcelFileDescriptor sourceOut = servicePipe.second; ParcelFileDescriptor sinkOut = servicePipe.first; - mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName()); - - try { - mClientAdapter.write(sourceIn); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to call write() the client operation", e); - sendErrorSignal(mClientAdapter, serviceAdapter, - ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); - logServiceEvent( - CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL); - return; + synchronized (mParentService.mLock) { + mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName()); } - try { - serviceAdapter.start(sinkOut); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to call start() the service operation", e); + + if (!setUpSharingPipeline(mClientAdapter, serviceAdapter, sourceIn, sinkOut)) { sendErrorSignal(mClientAdapter, serviceAdapter, ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); - logServiceEvent( - CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL); + bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut); + synchronized (mParentService.mLock) { + mParentService.mPackagesWithShareRequests + .remove(mDataShareRequest.getPackageName()); + } return; } @@ -1184,6 +1176,32 @@ public final class ContentCaptureManagerService extends } } + private boolean setUpSharingPipeline( + IDataShareWriteAdapter clientAdapter, + IDataShareReadAdapter serviceAdapter, + ParcelFileDescriptor sourceIn, + ParcelFileDescriptor sinkOut) { + try { + clientAdapter.write(sourceIn); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to call write() the client operation", e); + logServiceEvent( + CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL); + return false; + } + + try { + serviceAdapter.start(sinkOut); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to call start() the service operation", e); + logServiceEvent( + CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL); + return false; + } + + return true; + } + private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn, ParcelFileDescriptor sinkIn, ParcelFileDescriptor sourceOut, diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 197b77f014f9..6f25e8d1acd8 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -25,9 +25,9 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGRO import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; -import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; @@ -189,8 +189,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mBinding; private int mBindingUserID; private boolean mUnbinding; - private int mWaitForEnableRetry; - private int mWaitForDisableRetry; private boolean mTryBindOnBindTimeout = false; private BluetoothModeChangeHelper mBluetoothModeChangeHelper; @@ -1022,14 +1020,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mState == BluetoothAdapter.STATE_ON || mState == BluetoothAdapter.STATE_BLE_ON || mState == BluetoothAdapter.STATE_TURNING_ON - || mState == BluetoothAdapter.STATE_TURNING_OFF) { - Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + || mState == BluetoothAdapter.STATE_TURNING_OFF + || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { + Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on"); return true; } synchronized (mReceiver) { // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false, - BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, true); } return true; } @@ -1981,6 +1980,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private class BluetoothHandler extends Handler { boolean mGetNameAddressOnly = false; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; BluetoothHandler(Looper looper) { super(looper); @@ -2033,6 +2034,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_ENABLE: int quietEnable = msg.arg1; + int isBle = msg.arg2; if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { if (msg.arg2 == 0) { @@ -2082,26 +2084,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { + boolean isHandled = true; int state = mBluetooth.getState(); - if (state == BluetoothAdapter.STATE_BLE_ON) { - if (isBluetoothPersistedStateOnBluetooth() || - mEnableExternal) { - Slog.w(TAG, "BLE_ON State:Enable from Settings or" + - "BT on persisted, going to ON"); - mBluetooth.updateQuietModeStatus(mQuietEnable, - mContext.getAttributionSource()); - mBluetooth.onLeServiceUp(mContext.getAttributionSource()); - - // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - Binder.restoreCallingIdentity(callingIdentity); - } else { - Slog.w(TAG, "BLE_ON State:Queued enable from ble app," + - " stay in ble on"); - } - break; + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + if (isBle == 1) { + Slog.i(TAG, "Already at BLE_ON State"); + } else { + Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); + mBluetooth.onLeServiceUp(mContext.getAttributionSource()); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + break; + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_TURNING_ON: + case BluetoothAdapter.STATE_ON: + Slog.i(TAG, "MESSAGE_ENABLE: already enabled"); + break; + default: + isHandled = false; + break; } + if (isHandled) break; } } catch (RemoteException e) { Slog.e(TAG, "", e); @@ -2898,7 +2902,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { foregroundUser = ActivityManager.getCurrentUser(); valid = (callingUser == foregroundUser) || parentUser == foregroundUser - || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; + || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid + || callingAppId == Process.SHELL_UID; if (DBG && !valid) { Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + " parentUser=" + parentUser + " foregroundUser=" @@ -3110,7 +3115,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendEnableMsg(boolean quietMode, int reason, String packageName) { - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); + sendEnableMsg(quietMode, reason, packageName, false); + } + + private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, + isBle ? 1 : 0)); addActiveLog(reason, packageName, true); mLastEnabledTime = SystemClock.elapsedRealtime(); } diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index fdba098e6b80..48f5b51a8404 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -476,7 +476,11 @@ public class BootReceiver extends BroadcastReceiver { */ public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); - final String bootReason = SystemProperties.get("ro.boot.bootreason", null); + if (db == null) { + Slog.e(TAG, "Can't log tombstone: DropBoxManager not available"); + return; + } + HashMap<String, Long> timestamps = readTimestamps(); try { if (proto) { @@ -484,7 +488,7 @@ public class BootReceiver extends BroadcastReceiver { } else { final String headers = getBootHeadersToLogAndUpdate(); addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, - TAG_TOMBSTONE); + TAG_TOMBSTONE); } } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 483250ad2257..68fd0c12bea8 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -92,6 +92,8 @@ option java_package com.android.server 27533 notification_autogrouped (key|3) # notification was removed from an autogroup 275534 notification_unautogrouped (key|3) +# when a notification is adjusted via assistant +27535 notification_adjusted (key|3),(adjustment_type|3),(new_value|3) # --------------------------- # Watchdog.java diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 91b2440f71fe..06a78c864cac 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -39,6 +39,7 @@ import static android.hardware.SensorPrivacyManager.Sources.OTHER; import static android.hardware.SensorPrivacyManager.Sources.QS_TILE; import static android.hardware.SensorPrivacyManager.Sources.SETTINGS; import static android.hardware.SensorPrivacyManager.Sources.SHELL; +import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN; @@ -195,7 +196,7 @@ public final class SensorPrivacyService extends SystemService { private EmergencyCallHelper mEmergencyCallHelper; private KeyguardManager mKeyguardManager; - private int mCurrentUser = -1; + private int mCurrentUser = USER_NULL; public SensorPrivacyService(Context context) { super(context); @@ -228,9 +229,9 @@ public final class SensorPrivacyService extends SystemService { @Override public void onUserStarting(TargetUser user) { - if (mCurrentUser == -1) { + if (mCurrentUser == USER_NULL) { mCurrentUser = user.getUserIdentifier(); - mSensorPrivacyServiceImpl.userSwitching(-1, user.getUserIdentifier()); + mSensorPrivacyServiceImpl.userSwitching(USER_NULL, user.getUserIdentifier()); } } @@ -420,9 +421,12 @@ public final class SensorPrivacyService extends SystemService { } synchronized (mLock) { - if (mSuppressReminders.containsKey(new Pair<>(sensor, user))) { + UserHandle parentUser = UserHandle.of(mUserManagerInternal + .getProfileParentId(user.getIdentifier())); + if (mSuppressReminders.containsKey(new Pair<>(sensor, parentUser))) { Log.d(TAG, - "Suppressed sensor privacy reminder for " + packageName + "/" + user); + "Suppressed sensor privacy reminder for " + packageName + "/" + + parentUser); return; } } @@ -708,6 +712,16 @@ public final class SensorPrivacyService extends SystemService { @Override public void setIndividualSensorPrivacy(@UserIdInt int userId, @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) { + if (DEBUG) { + Log.d(TAG, "callingUid=" + Binder.getCallingUid() + + " callingPid=" + Binder.getCallingPid() + + " setIndividualSensorPrivacy(" + + "userId=" + userId + + " source=" + source + + " sensor=" + sensor + + " enable=" + enable + + ")"); + } enforceManageSensorPrivacyPermission(); if (userId == UserHandle.USER_CURRENT) { userId = mCurrentUser; @@ -892,6 +906,14 @@ public final class SensorPrivacyService extends SystemService { @Override public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { + if (DEBUG) { + Log.d(TAG, "callingUid=" + Binder.getCallingUid() + + " callingPid=" + Binder.getCallingPid() + + " isIndividualSensorPrivacyEnabled(" + + "userId=" + userId + + " sensor=" + sensor + + ")"); + } enforceObserveSensorPrivacyPermission(); if (userId == UserHandle.USER_CURRENT) { userId = mCurrentUser; @@ -1273,13 +1295,13 @@ public final class SensorPrivacyService extends SystemService { micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE); camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA); } - if (prevMicState != micState) { + if (from == USER_NULL || prevMicState != micState) { mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState); setGlobalRestriction(MICROPHONE, micState); } - if (prevCamState != camState) { + if (from == USER_NULL || prevCamState != camState) { mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState); - setGlobalRestriction(CAMERA, micState); + setGlobalRestriction(CAMERA, camState); } } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 398c5ad42938..0a81c9d12b94 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -222,6 +222,9 @@ class StorageManagerService extends IStorageManager.Stub @GuardedBy("mLock") private final Set<Integer> mFuseMountedUser = new ArraySet<>(); + @GuardedBy("mLock") + private final Set<Integer> mCeStoragePreparedUsers = new ArraySet<>(); + public static class Lifecycle extends SystemService { private StorageManagerService mStorageManagerService; @@ -4881,5 +4884,19 @@ class StorageManagerService extends IStorageManager.Stub } return primaryVolumeIds; } + + @Override + public void markCeStoragePrepared(int userId) { + synchronized (mLock) { + mCeStoragePreparedUsers.add(userId); + } + } + + @Override + public boolean isCeStoragePrepared(int userId) { + synchronized (mLock) { + return mCeStoragePreparedUsers.contains(userId); + } + } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fb4fe369e148..69a8a2c60b7e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7817,6 +7817,17 @@ public class ActivityManagerService extends IActivityManager.Stub } else { killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid), "Too many Binders sent to SYSTEM"); + // We need to run a GC here, because killing the processes involved + // actually isn't guaranteed to free up the proxies; in fact, if the + // GC doesn't run for a long time, we may even exceed the global + // proxy limit for a process (20000), resulting in system_server itself + // being killed. + // Note that the GC here might not actually clean up all the proxies, + // because the binder reference decrements will come in asynchronously; + // but if new processes belonging to the UID keep adding proxies, we + // will get another callback here, and run the GC again - this time + // cleaning up the old proxies. + VMRuntime.getRuntime().requestConcurrentGC(); } }, mHandler); t.traceEnd(); // setBinderProxies @@ -15512,12 +15523,14 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void updateDeviceIdleTempAllowlist(int[] appids, int changingUid, boolean adding, - long durationMs, @TempAllowListType int type, @ReasonCode int reasonCode, - @Nullable String reason, int callingUid) { + public void updateDeviceIdleTempAllowlist(@Nullable int[] appids, int changingUid, + boolean adding, long durationMs, @TempAllowListType int type, + @ReasonCode int reasonCode, @Nullable String reason, int callingUid) { synchronized (ActivityManagerService.this) { synchronized (mProcLock) { - mDeviceIdleTempAllowlist = appids; + if (appids != null) { + mDeviceIdleTempAllowlist = appids; + } if (adding) { if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { // Note, the device idle temp-allowlist are by app-ids, but here @@ -15527,12 +15540,7 @@ public class ActivityManagerService extends IActivityManager.Stub callingUid)); } } else { - // Note in the removing case, we need to remove all the UIDs matching - // the appId, because DeviceIdle's temp-allowlist are based on AppIds, - // not UIDs. - // For eacmple, "cmd deviceidle tempallowlist -r PACKAGE" will - // not only remove this app for user 0, but for all users. - mFgsStartTempAllowList.removeAppId(UserHandle.getAppId(changingUid)); + mFgsStartTempAllowList.removeUid(changingUid); } setAppIdTempAllowlistStateLSP(changingUid, adding); } diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 0c633cacda92..7ba032f683b8 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -478,7 +478,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { for (int uid : uidsToRemove) { FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, -1, uid, FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED); - mStats.removeIsolatedUidLocked(uid, SystemClock.elapsedRealtime(), + mStats.maybeRemoveIsolatedUidLocked(uid, SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); } mStats.clearPendingRemovedUids(); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 503b3a93b31f..94bf62f8b9b7 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1568,17 +1568,23 @@ public final class BroadcastQueue { perm = PackageManager.PERMISSION_DENIED; } - if (perm == PackageManager.PERMISSION_GRANTED) { - skip = true; - break; - } - int appOp = AppOpsManager.permissionToOpCode(excludedPermission); if (appOp != AppOpsManager.OP_NONE) { - if (mService.getAppOpsManager().checkOpNoThrow(appOp, + // When there is an app op associated with the permission, + // skip when both the permission and the app op are + // granted. + if ((perm == PackageManager.PERMISSION_GRANTED) && ( + mService.getAppOpsManager().checkOpNoThrow(appOp, info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) - == AppOpsManager.MODE_ALLOWED) { + == AppOpsManager.MODE_ALLOWED)) { + skip = true; + break; + } + } else { + // When there is no app op associated with the permission, + // skip when permission is granted. + if (perm == PackageManager.PERMISSION_GRANTED) { skip = true; break; } diff --git a/services/core/java/com/android/server/am/CacheOomRanker.java b/services/core/java/com/android/server/am/CacheOomRanker.java index 50278fd81bb2..e6ffcfcd3510 100644 --- a/services/core/java/com/android/server/am/CacheOomRanker.java +++ b/services/core/java/com/android/server/am/CacheOomRanker.java @@ -16,6 +16,8 @@ package com.android.server.am; +import android.os.Process; +import android.os.SystemClock; import android.provider.DeviceConfig; import android.util.Slog; @@ -38,21 +40,40 @@ public class CacheOomRanker { private static final boolean DEFAULT_USE_OOM_RE_RANKING = false; @VisibleForTesting static final String KEY_OOM_RE_RANKING_NUMBER_TO_RE_RANK = "oom_re_ranking_number_to_re_rank"; - @VisibleForTesting static final int DEFAULT_OOM_RE_RANKING_NUMBER_TO_RE_RANK = 8; + @VisibleForTesting + static final int DEFAULT_OOM_RE_RANKING_NUMBER_TO_RE_RANK = 8; + @VisibleForTesting + static final String KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS = + "oom_re_ranking_preserve_top_n_apps"; + @VisibleForTesting + static final int DEFAULT_PRESERVE_TOP_N_APPS = 3; + @VisibleForTesting + static final String KEY_OOM_RE_RANKING_USE_FREQUENT_RSS = "oom_re_ranking_rss_use_frequent_rss"; + @VisibleForTesting + static final boolean DEFAULT_USE_FREQUENT_RSS = true; + @VisibleForTesting + static final String KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS = "oom_re_ranking_rss_update_rate_ms"; + @VisibleForTesting + static final long DEFAULT_RSS_UPDATE_RATE_MS = 10_000; // 10 seconds @VisibleForTesting static final String KEY_OOM_RE_RANKING_LRU_WEIGHT = "oom_re_ranking_lru_weight"; - @VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_LRU_WEIGHT = 0.35f; + @VisibleForTesting + static final float DEFAULT_OOM_RE_RANKING_LRU_WEIGHT = 0.35f; @VisibleForTesting static final String KEY_OOM_RE_RANKING_USES_WEIGHT = "oom_re_ranking_uses_weight"; - @VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_USES_WEIGHT = 0.5f; + @VisibleForTesting + static final float DEFAULT_OOM_RE_RANKING_USES_WEIGHT = 0.5f; @VisibleForTesting static final String KEY_OOM_RE_RANKING_RSS_WEIGHT = "oom_re_ranking_rss_weight"; - @VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_RSS_WEIGHT = 0.15f; + @VisibleForTesting + static final float DEFAULT_OOM_RE_RANKING_RSS_WEIGHT = 0.15f; private static final Comparator<RankedProcessRecord> SCORED_PROCESS_RECORD_COMPARATOR = new ScoreComparator(); private static final Comparator<RankedProcessRecord> CACHE_USE_COMPARATOR = new CacheUseComparator(); + private static final Comparator<RankedProcessRecord> RSS_COMPARATOR = + new RssComparator(); private static final Comparator<RankedProcessRecord> LAST_RSS_COMPARATOR = new LastRssComparator(); private static final Comparator<RankedProcessRecord> LAST_ACTIVITY_TIME_COMPARATOR = @@ -61,20 +82,33 @@ public class CacheOomRanker { private final Object mPhenotypeFlagLock = new Object(); private final ActivityManagerService mService; + private final ProcessDependencies mProcessDependencies; private final ActivityManagerGlobalLock mProcLock; private final Object mProfilerLock; @GuardedBy("mPhenotypeFlagLock") private boolean mUseOomReRanking = DEFAULT_USE_OOM_RE_RANKING; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting + int mPreserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting + boolean mUseFrequentRss = DEFAULT_USE_FREQUENT_RSS; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting + long mRssUpdateRateMs = DEFAULT_RSS_UPDATE_RATE_MS; // Weight to apply to the LRU ordering. @GuardedBy("mPhenotypeFlagLock") - @VisibleForTesting float mLruWeight = DEFAULT_OOM_RE_RANKING_LRU_WEIGHT; + @VisibleForTesting + float mLruWeight = DEFAULT_OOM_RE_RANKING_LRU_WEIGHT; // Weight to apply to the ordering by number of times the process has been added to the cache. @GuardedBy("mPhenotypeFlagLock") - @VisibleForTesting float mUsesWeight = DEFAULT_OOM_RE_RANKING_USES_WEIGHT; + @VisibleForTesting + float mUsesWeight = DEFAULT_OOM_RE_RANKING_USES_WEIGHT; // Weight to apply to the ordering by RSS used by the processes. @GuardedBy("mPhenotypeFlagLock") - @VisibleForTesting float mRssWeight = DEFAULT_OOM_RE_RANKING_RSS_WEIGHT; + @VisibleForTesting + float mRssWeight = DEFAULT_OOM_RE_RANKING_RSS_WEIGHT; // Positions to replace in the lru list. @GuardedBy("mPhenotypeFlagLock") @@ -93,6 +127,12 @@ public class CacheOomRanker { updateUseOomReranking(); } else if (KEY_OOM_RE_RANKING_NUMBER_TO_RE_RANK.equals(name)) { updateNumberToReRank(); + } else if (KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS.equals(name)) { + updatePreserveTopNApps(); + } else if (KEY_OOM_RE_RANKING_USE_FREQUENT_RSS.equals(name)) { + updateUseFrequentRss(); + } else if (KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS.equals(name)) { + updateRssUpdateRateMs(); } else if (KEY_OOM_RE_RANKING_LRU_WEIGHT.equals(name)) { updateLruWeight(); } else if (KEY_OOM_RE_RANKING_USES_WEIGHT.equals(name)) { @@ -106,9 +146,15 @@ public class CacheOomRanker { }; CacheOomRanker(final ActivityManagerService service) { + this(service, new ProcessDependenciesImpl()); + } + + @VisibleForTesting + CacheOomRanker(final ActivityManagerService service, ProcessDependencies processDependencies) { mService = service; mProcLock = service.mProcLock; mProfilerLock = service.mAppProfiler.mProfilerLock; + mProcessDependencies = processDependencies; } /** Load settings from device config and register a listener for changes. */ @@ -160,6 +206,31 @@ public class CacheOomRanker { } @GuardedBy("mPhenotypeFlagLock") + private void updatePreserveTopNApps() { + int preserveTopNApps = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS, DEFAULT_PRESERVE_TOP_N_APPS); + if (preserveTopNApps < 0) { + Slog.w(OomAdjuster.TAG, + "Found negative value for preserveTopNApps, setting to default: " + + preserveTopNApps); + preserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS; + } + mPreserveTopNApps = preserveTopNApps; + } + + @GuardedBy("mPhenotypeFlagLock") + private void updateRssUpdateRateMs() { + mRssUpdateRateMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS, DEFAULT_RSS_UPDATE_RATE_MS); + } + + @GuardedBy("mPhenotypeFlagLock") + private void updateUseFrequentRss() { + mUseFrequentRss = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_OOM_RE_RANKING_USE_FREQUENT_RSS, DEFAULT_USE_FREQUENT_RSS); + } + + @GuardedBy("mPhenotypeFlagLock") private void updateLruWeight() { mLruWeight = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_OOM_RE_RANKING_LRU_WEIGHT, DEFAULT_OOM_RE_RANKING_LRU_WEIGHT); @@ -183,9 +254,39 @@ public class CacheOomRanker { */ @GuardedBy({"mService", "mProcLock"}) void reRankLruCachedAppsLSP(ArrayList<ProcessRecord> lruList, int lruProcessServiceStart) { + // The lruList is a list of processes ordered by how recently they were used. The + // least-recently-used apps are at the beginning of the list. We keep track of two + // indices in the lruList: + // + // getNumberToReRank=5, preserveTopNApps=3, lruProcessServiceStart=7, + // lruList= + // 0: app A ^ + // 1: app B | These apps are re-ranked, as they are the first five apps (see + // 2: app C | getNumberToReRank), excluding... + // 3: app D v + // 4: app E ^ + // 5: app F | The three most-recently-used apps in the cache (see preserveTopNApps). + // 6: app G v + // 7: service A ^ + // 8: service B | Everything beyond lruProcessServiceStart is ignored, as these aren't + // 9: service C | apps. + // 10: activity A | + // ... | + // + // `numProcessesEvaluated` moves across the apps (indices 0-6) or until we've found enough + // apps to re-rank, and made sure none of them are in the top `preserveTopNApps` apps. + // Re-ranked apps are copied into `scoredProcessRecords`, where the re-ranking calculation + // happens. + // + // Note that some apps in the `lruList` can be skipped, if they don't pass + //`appCanBeReRanked`. + float lruWeight; float usesWeight; float rssWeight; + int preserveTopNApps; + boolean useFrequentRss; + long rssUpdateRateMs; int[] lruPositions; RankedProcessRecord[] scoredProcessRecords; @@ -193,6 +294,9 @@ public class CacheOomRanker { lruWeight = mLruWeight; usesWeight = mUsesWeight; rssWeight = mRssWeight; + preserveTopNApps = mPreserveTopNApps; + useFrequentRss = mUseFrequentRss; + rssUpdateRateMs = mRssUpdateRateMs; lruPositions = mLruPositions; scoredProcessRecords = mScoredProcessRecords; } @@ -202,52 +306,98 @@ public class CacheOomRanker { return; } + int numProcessesEvaluated = 0; // Collect the least recently used processes to re-rank, only rank cached // processes further down the list than mLruProcessServiceStart. - int cachedProcessPos = 0; - for (int i = 0; i < lruProcessServiceStart - && cachedProcessPos < scoredProcessRecords.length; ++i) { - ProcessRecord app = lruList.get(i); + int numProcessesReRanked = 0; + while (numProcessesEvaluated < lruProcessServiceStart + && numProcessesReRanked < scoredProcessRecords.length) { + ProcessRecord process = lruList.get(numProcessesEvaluated); // Processes that will be assigned a cached oom adj score. - if (!app.isKilledByAm() && app.getThread() != null && app.mState.getCurAdj() - >= ProcessList.UNKNOWN_ADJ) { - scoredProcessRecords[cachedProcessPos].proc = app; - scoredProcessRecords[cachedProcessPos].score = 0.0f; - lruPositions[cachedProcessPos] = i; - ++cachedProcessPos; + if (appCanBeReRanked(process)) { + scoredProcessRecords[numProcessesReRanked].proc = process; + scoredProcessRecords[numProcessesReRanked].score = 0.0f; + lruPositions[numProcessesReRanked] = numProcessesEvaluated; + ++numProcessesReRanked; } + ++numProcessesEvaluated; } - // TODO maybe ensure a certain number above this in the cache before re-ranking. - if (cachedProcessPos < scoredProcessRecords.length) { - // Ignore we don't have enough processes to worry about re-ranking. - return; + // Count how many apps we're not re-ranking (up to preserveTopNApps). + int numProcessesNotReRanked = 0; + while (numProcessesEvaluated < lruProcessServiceStart + && numProcessesNotReRanked < preserveTopNApps) { + ProcessRecord process = lruList.get(numProcessesEvaluated); + if (appCanBeReRanked(process)) { + numProcessesNotReRanked++; + } + numProcessesEvaluated++; + } + // Exclude the top `preserveTopNApps` apps from re-ranking. + if (numProcessesNotReRanked < preserveTopNApps) { + numProcessesReRanked -= preserveTopNApps - numProcessesNotReRanked; + if (numProcessesReRanked < 0) { + numProcessesReRanked = 0; + } + } + + if (useFrequentRss) { + // Update RSS values for re-ranked apps. + long nowMs = SystemClock.elapsedRealtime(); + for (int i = 0; i < numProcessesReRanked; ++i) { + RankedProcessRecord scoredProcessRecord = scoredProcessRecords[i]; + long sinceUpdateMs = + nowMs - scoredProcessRecord.proc.mState.getCacheOomRankerRssTimeMs(); + if (scoredProcessRecord.proc.mState.getCacheOomRankerRss() != 0 + && sinceUpdateMs < rssUpdateRateMs) { + continue; + } + + long[] rss = mProcessDependencies.getRss(scoredProcessRecord.proc.getPid()); + if (rss == null || rss.length == 0) { + Slog.e( + OomAdjuster.TAG, + "Process.getRss returned bad value, not re-ranking: " + + Arrays.toString(rss)); + return; + } + // First element is total RSS: + // frameworks/base/core/jni/android_util_Process.cpp:1192 + scoredProcessRecord.proc.mState.setCacheOomRankerRss(rss[0], nowMs); + scoredProcessRecord.proc.mProfile.setLastRss(rss[0]); + } } // Add scores for each of the weighted features we want to rank based on. if (lruWeight > 0.0f) { // This doesn't use the LRU list ordering as after the first re-ranking // that will no longer be lru. - Arrays.sort(scoredProcessRecords, LAST_ACTIVITY_TIME_COMPARATOR); + Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, + LAST_ACTIVITY_TIME_COMPARATOR); addToScore(scoredProcessRecords, lruWeight); } if (rssWeight > 0.0f) { - synchronized (mService.mAppProfiler.mProfilerLock) { - Arrays.sort(scoredProcessRecords, LAST_RSS_COMPARATOR); + if (useFrequentRss) { + Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, RSS_COMPARATOR); + } else { + synchronized (mService.mAppProfiler.mProfilerLock) { + Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR); + } } addToScore(scoredProcessRecords, rssWeight); } if (usesWeight > 0.0f) { - Arrays.sort(scoredProcessRecords, CACHE_USE_COMPARATOR); + Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, CACHE_USE_COMPARATOR); addToScore(scoredProcessRecords, usesWeight); } // Re-rank by the new combined score. - Arrays.sort(scoredProcessRecords, SCORED_PROCESS_RECORD_COMPARATOR); + Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, + SCORED_PROCESS_RECORD_COMPARATOR); if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) { boolean printedHeader = false; - for (int i = 0; i < scoredProcessRecords.length; ++i) { + for (int i = 0; i < numProcessesReRanked; ++i) { if (scoredProcessRecords[i].proc.getPid() != lruList.get(lruPositions[i]).getPid()) { if (!printedHeader) { @@ -260,12 +410,18 @@ public class CacheOomRanker { } } - for (int i = 0; i < scoredProcessRecords.length; ++i) { + for (int i = 0; i < numProcessesReRanked; ++i) { lruList.set(lruPositions[i], scoredProcessRecords[i].proc); scoredProcessRecords[i].proc = null; } } + private static boolean appCanBeReRanked(ProcessRecord process) { + return !process.isKilledByAm() + && process.getThread() != null + && process.mState.getCurAdj() >= ProcessList.UNKNOWN_ADJ; + } + private static void addToScore(RankedProcessRecord[] scores, float weight) { for (int i = 1; i < scores.length; ++i) { scores[i].score += i * weight; @@ -305,6 +461,16 @@ public class CacheOomRanker { } } + private static class RssComparator implements Comparator<RankedProcessRecord> { + @Override + public int compare(RankedProcessRecord o1, RankedProcessRecord o2) { + // High RSS first to match least recently used. + return Long.compare( + o2.proc.mState.getCacheOomRankerRss(), + o1.proc.mState.getCacheOomRankerRss()); + } + } + private static class LastRssComparator implements Comparator<RankedProcessRecord> { @Override public int compare(RankedProcessRecord o1, RankedProcessRecord o2) { @@ -317,4 +483,18 @@ public class CacheOomRanker { public ProcessRecord proc; public float score; } + + /** + * Interface for mocking {@link Process} static methods. + */ + interface ProcessDependencies { + long[] getRss(int pid); + } + + private static class ProcessDependenciesImpl implements ProcessDependencies { + @Override + public long[] getRss(int pid) { + return Process.getRss(pid); + } + } } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 8a74cf648acf..c641bf04731f 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -160,6 +160,9 @@ public final class CachedAppOptimizer { static final int SYNC_RECEIVED_WHILE_FROZEN = 1; static final int ASYNC_RECEIVED_WHILE_FROZEN = 2; + // Bitfield values for sync transactions received by frozen binder threads + static final int TXNS_PENDING_WHILE_FROZEN = 4; + /** * This thread must be moved to the system background cpuset. * If that doesn't happen, it's probably going to draw a lot of power. @@ -709,8 +712,9 @@ public final class CachedAppOptimizer { * binder for the specificed pid. * * @throws RuntimeException in case a flush/freeze operation could not complete successfully. + * @return 0 if success, or -EAGAIN indicating there's pending transaction. */ - private static native void freezeBinder(int pid, boolean freeze); + private static native int freezeBinder(int pid, boolean freeze); /** * Retrieves binder freeze info about a process. @@ -1047,7 +1051,7 @@ public final class CachedAppOptimizer { int freezeInfo = getBinderFreezeInfo(pid); if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) { - Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " " + Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " received sync transactions while frozen, killing"); app.killLocked("Sync transaction while in frozen state", ApplicationExitInfo.REASON_OTHER, @@ -1055,8 +1059,8 @@ public final class CachedAppOptimizer { processKilled = true; } - if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) { - Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " " + if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0 && DEBUG_FREEZER) { + Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " received async transactions while frozen"); } } catch (Exception e) { @@ -1391,7 +1395,9 @@ public final class CachedAppOptimizer { public void handleMessage(Message msg) { switch (msg.what) { case SET_FROZEN_PROCESS_MSG: - freezeProcess((ProcessRecord) msg.obj); + synchronized (mAm) { + freezeProcess((ProcessRecord) msg.obj); + } break; case REPORT_UNFREEZE_MSG: int pid = msg.arg1; @@ -1405,6 +1411,15 @@ public final class CachedAppOptimizer { } } + @GuardedBy({"mAm", "mProcLock"}) + private void rescheduleFreeze(final ProcessRecord proc, final String reason) { + Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid() + + " " + proc.processName + " (" + reason + ")"); + unfreezeAppLSP(proc); + freezeAppAsyncLSP(proc); + } + + @GuardedBy({"mAm"}) private void freezeProcess(final ProcessRecord proc) { int pid = proc.getPid(); // Unlocked intentionally final String name = proc.processName; @@ -1454,10 +1469,15 @@ public final class CachedAppOptimizer { return; } + Slog.d(TAG_AM, "freezing " + pid + " " + name); + // Freeze binder interface before the process, to flush any // transactions that might be pending. try { - freezeBinder(pid, true); + if (freezeBinder(pid, true) != 0) { + rescheduleFreeze(proc, "outstanding txns"); + return; + } } catch (RuntimeException e) { Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); mFreezeHandler.post(() -> { @@ -1503,24 +1523,36 @@ public final class CachedAppOptimizer { try { // post-check to prevent races + int freezeInfo = getBinderFreezeInfo(pid); + + if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) { + synchronized (mProcLock) { + rescheduleFreeze(proc, "new pending txns"); + } + return; + } + } catch (RuntimeException e) { + Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); + mFreezeHandler.post(() -> { + synchronized (mAm) { + proc.killLocked("Unable to freeze binder interface", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); + } + }); + } + + try { + // post-check to prevent races if (mProcLocksReader.hasFileLocks(pid)) { if (DEBUG_FREEZER) { Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, reverting freeze"); } - - synchronized (mAm) { - synchronized (mProcLock) { - unfreezeAppLSP(proc); - } - } + unfreezeAppLSP(proc); } } catch (Exception e) { Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e); - synchronized (mAm) { - synchronized (mProcLock) { - unfreezeAppLSP(proc); - } - } + unfreezeAppLSP(proc); } } diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 5c9d38515e49..2e3e635c1157 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -94,8 +94,6 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put( Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, String.class); sGlobalSettingToTypeMap.put( - Settings.Global.ANGLE_ALLOWLIST, String.class); - sGlobalSettingToTypeMap.put( Settings.Global.ANGLE_EGL_FEATURES, String.class); sGlobalSettingToTypeMap.put( Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 183c620b61ec..d993772b4f3b 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -73,6 +73,7 @@ import static com.android.server.am.AppProfiler.TAG_PSS; import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; +import android.annotation.IntDef; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityThread; @@ -117,6 +118,8 @@ import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.WindowProcessController; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayDeque; import java.util.ArrayList; @@ -174,6 +177,27 @@ public class OomAdjuster { @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) static final long USE_SHORT_FGS_USAGE_INTERACTION_TIME = 183972877L; + static final int CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY = 0; + static final int CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY = 1; + static final int CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME = 2; + + @IntDef(prefix = { "CACHED_COMPAT_CHANGE_" }, value = { + CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY, + CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY, + CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME, + }) + @Retention(RetentionPolicy.SOURCE) + static @interface CachedCompatChangeId{} + + /** + * Mapping from CACHED_COMPAT_CHANGE_* to the actual compat change id. + */ + static final long[] CACHED_COMPAT_CHANGE_IDS_MAPPING = new long[] { + PROCESS_CAPABILITY_CHANGE_ID, + CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID, + USE_SHORT_FGS_USAGE_INTERACTION_TIME, + }; + /** * For some direct access we need to power manager. */ @@ -391,6 +415,12 @@ public class OomAdjuster { return mPlatformCompatCache; } + boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, ApplicationInfo app, + boolean defaultValue) { + return getPlatformCompatCache().isChangeEnabled( + CACHED_COMPAT_CHANGE_IDS_MAPPING[cachedCompatChangeId], app, defaultValue); + } + OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) { this(service, processList, activeUids, createAdjusterThread()); } @@ -2026,12 +2056,8 @@ public class OomAdjuster { (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; - boolean enabled = false; - try { - enabled = getPlatformCompatCache().isChangeEnabled( - CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID, s.appInfo); - } catch (RemoteException e) { - } + final boolean enabled = state.getCachedCompatChange( + CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY); if (enabled) { capabilityFromFGS |= (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA) @@ -2248,12 +2274,8 @@ public class OomAdjuster { // to client's state. clientProcState = PROCESS_STATE_BOUND_TOP; state.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP); - boolean enabled = false; - try { - enabled = getPlatformCompatCache().isChangeEnabled( - PROCESS_CAPABILITY_CHANGE_ID, client.info); - } catch (RemoteException e) { - } + final boolean enabled = cstate.getCachedCompatChange( + CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY); if (enabled) { if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { // TOP process passes all capabilities to the service. @@ -2922,8 +2944,8 @@ public class OomAdjuster { state.setProcStateChanged(true); } } else if (state.hasReportedInteraction()) { - final boolean fgsInteractionChangeEnabled = getPlatformCompatCache().isChangeEnabled( - USE_SHORT_FGS_USAGE_INTERACTION_TIME, app.info, false); + final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( + CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); final long interactionThreshold = fgsInteractionChangeEnabled ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S; @@ -2933,8 +2955,8 @@ public class OomAdjuster { maybeUpdateUsageStatsLSP(app, nowElapsed); } } else { - final boolean fgsInteractionChangeEnabled = getPlatformCompatCache().isChangeEnabled( - USE_SHORT_FGS_USAGE_INTERACTION_TIME, app.info, false); + final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( + CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); final long interactionThreshold = fgsInteractionChangeEnabled ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S; @@ -3023,8 +3045,8 @@ public class OomAdjuster { if (mService.mUsageStatsService == null) { return; } - final boolean fgsInteractionChangeEnabled = getPlatformCompatCache().isChangeEnabled( - USE_SHORT_FGS_USAGE_INTERACTION_TIME, app.info, false); + final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange( + CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME); boolean isInteraction; // To avoid some abuse patterns, we are going to be careful about what we consider // to be an app interaction. Being the top activity doesn't count while the display diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java index dc6bcd8ab9de..206dd889fb70 100644 --- a/services/core/java/com/android/server/am/ProcessStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessStateRecord.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; +import static com.android.server.am.OomAdjuster.CachedCompatChangeId; import static com.android.server.am.ProcessRecord.TAG; import android.annotation.ElapsedRealtimeLong; @@ -342,6 +343,20 @@ final class ProcessStateRecord { private int mCacheOomRankerUseCount; /** + * Process memory usage (RSS). + * + * Periodically populated by {@code CacheOomRanker}, stored in this object to cache the values. + */ + @GuardedBy("mService") + private long mCacheOomRankerRss; + + /** + * The last time, in milliseconds since boot, since {@link #mCacheOomRankerRss} was updated. + */ + @GuardedBy("mService") + private long mCacheOomRankerRssTimeMs; + + /** * Whether or not this process is reachable from given process. */ @GuardedBy("mService") @@ -377,6 +392,16 @@ final class ProcessStateRecord { @GuardedBy("mService") private int mCachedIsReceivingBroadcast = VALUE_INVALID; + /** + * Cache the return value of PlatformCompat.isChangeEnabled(). + */ + @GuardedBy("mService") + private int[] mCachedCompatChanges = new int[] { + VALUE_INVALID, // CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY + VALUE_INVALID, // CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY + VALUE_INVALID, // CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME + }; + @GuardedBy("mService") private int mCachedAdj = ProcessList.INVALID_ADJ; @GuardedBy("mService") @@ -566,6 +591,10 @@ final class ProcessStateRecord { @GuardedBy({"mService", "mProcLock"}) void setSetProcState(int setProcState) { + if (ActivityManager.isProcStateCached(mSetProcState) + && !ActivityManager.isProcStateCached(setProcState)) { + mCacheOomRankerUseCount++; + } mSetProcState = setProcState; } @@ -829,12 +858,7 @@ final class ProcessStateRecord { @GuardedBy("mService") void setCached(boolean cached) { - if (mCached != cached) { - mCached = cached; - if (cached) { - ++mCacheOomRankerUseCount; - } - } + mCached = cached; } @GuardedBy("mService") @@ -1009,6 +1033,16 @@ final class ProcessStateRecord { } @GuardedBy("mService") + boolean getCachedCompatChange(@CachedCompatChangeId int cachedCompatChangeId) { + if (mCachedCompatChanges[cachedCompatChangeId] == VALUE_INVALID) { + mCachedCompatChanges[cachedCompatChangeId] = mService.mOomAdjuster + .isChangeEnabled(cachedCompatChangeId, mApp.info, false /* default */) + ? VALUE_TRUE : VALUE_FALSE; + } + return mCachedCompatChanges[cachedCompatChangeId] == VALUE_TRUE; + } + + @GuardedBy("mService") void computeOomAdjFromActivitiesIfNecessary(OomAdjuster.ComputeOomAdjWindowCallback callback, int adj, boolean foregroundActivities, boolean hasVisibleActivities, int procState, int schedGroup, int appUid, int logUid, int processCurTop) { @@ -1088,6 +1122,9 @@ final class ProcessStateRecord { mCurSchedGroup = mSetSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND; mCurProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; + for (int i = 0; i < mCachedCompatChanges.length; i++) { + mCachedCompatChanges[i] = VALUE_INVALID; + } } @GuardedBy("mService") @@ -1127,6 +1164,21 @@ final class ProcessStateRecord { return mLastInvisibleTime; } + public void setCacheOomRankerRss(long rss, long rssTimeMs) { + mCacheOomRankerRss = rss; + mCacheOomRankerRssTimeMs = rssTimeMs; + } + + @GuardedBy("mService") + public long getCacheOomRankerRss() { + return mCacheOomRankerRss; + } + + @GuardedBy("mService") + public long getCacheOomRankerRssTimeMs() { + return mCacheOomRankerRssTimeMs; + } + @GuardedBy({"mService", "mProcLock"}) void dump(PrintWriter pw, String prefix, long nowUptime) { if (mReportedInteraction || mFgInteractionTime != 0) { diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 804e442bc8de..17930ea9c93c 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -927,9 +927,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } public void postNotification() { - final int appUid = appInfo.uid; - final int appPid = app.getPid(); - if (isForeground && foregroundNoti != null) { + if (isForeground && foregroundNoti != null && app != null) { + final int appUid = appInfo.uid; + final int appPid = app.getPid(); // Do asynchronous communication with notification manager to // avoid deadlocks. final String localPackageName = packageName; diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index e022e977e02f..2f20efbf5730 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -84,6 +84,7 @@ public class SettingsToPropertiesMapper { DeviceConfig.NAMESPACE_CONNECTIVITY, DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT, DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS, + DeviceConfig.NAMESPACE_LMKD_NATIVE, DeviceConfig.NAMESPACE_MEDIA_NATIVE, DeviceConfig.NAMESPACE_NETD_NATIVE, DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index af8d7a6a282b..3003c520254b 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -272,6 +272,13 @@ public final class GameManagerService extends IGameManagerService.Stub { "com.android.graphics.intervention.wm.allowDownscale"; /** + * Metadata that can be included in the app manifest to allow/disallow any ANGLE + * interventions. Default value is TRUE. + */ + public static final String METADATA_ANGLE_ALLOW_ANGLE = + "com.android.graphics.intervention.angle.allowAngle"; + + /** * Metadata that needs to be included in the app manifest to OPT-IN to PERFORMANCE mode. * This means the app will assume full responsibility for the experience provided by this * mode and the system will enable no window manager downscaling. @@ -294,6 +301,7 @@ public final class GameManagerService extends IGameManagerService.Stub { private boolean mPerfModeOptedIn; private boolean mBatteryModeOptedIn; private boolean mAllowDownscale; + private boolean mAllowAngle; GamePackageConfiguration(String packageName, int userId) { mPackageName = packageName; @@ -305,10 +313,12 @@ public final class GameManagerService extends IGameManagerService.Stub { mPerfModeOptedIn = ai.metaData.getBoolean(METADATA_PERFORMANCE_MODE_ENABLE); mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE); mAllowDownscale = ai.metaData.getBoolean(METADATA_WM_ALLOW_DOWNSCALE, true); + mAllowAngle = ai.metaData.getBoolean(METADATA_ANGLE_ALLOW_ANGLE, true); } else { mPerfModeOptedIn = false; mBatteryModeOptedIn = false; mAllowDownscale = true; + mAllowAngle = true; } } catch (PackageManager.NameNotFoundException e) { // Not all packages are installed, hence ignore those that are not installed yet. @@ -340,14 +350,26 @@ public final class GameManagerService extends IGameManagerService.Stub { public static final String MODE_KEY = "mode"; public static final String SCALING_KEY = "downscaleFactor"; public static final String DEFAULT_SCALING = "1.0"; + public static final String ANGLE_KEY = "useAngle"; private final @GameMode int mGameMode; private final String mScaling; + private final boolean mUseAngle; GameModeConfiguration(KeyValueListParser parser) { mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED); - mScaling = !mAllowDownscale || isGameModeOptedIn(mGameMode) + // isGameModeOptedIn() returns if an app will handle all of the changes necessary + // for a particular game mode. If so, the Android framework (i.e. + // GameManagerService) will not do anything for the app (like window scaling or + // using ANGLE). + mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode) ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING); + // We only want to use ANGLE if: + // - We're allowed to use ANGLE (the app hasn't opted out via the manifest) AND + // - The app has not opted in to performing the work itself AND + // - The Phenotype config has enabled it. + mUseAngle = mAllowAngle && !willGamePerformOptimizations(mGameMode) + && parser.getBoolean(ANGLE_KEY, false); } public int getGameMode() { @@ -358,6 +380,10 @@ public final class GameManagerService extends IGameManagerService.Stub { return mScaling; } + public boolean getUseAngle() { + return mUseAngle; + } + public boolean isValid() { return (mGameMode == GameManager.GAME_MODE_PERFORMANCE || mGameMode == GameManager.GAME_MODE_BATTERY) @@ -368,7 +394,8 @@ public final class GameManagerService extends IGameManagerService.Stub { * @hide */ public String toString() { - return "[Game Mode:" + mGameMode + ",Scaling:" + mScaling + "]"; + return "[Game Mode:" + mGameMode + ",Scaling:" + mScaling + ",Use Angle:" + + mUseAngle + "]"; } /** @@ -384,13 +411,14 @@ public final class GameManagerService extends IGameManagerService.Stub { } /** - * Gets whether a package has opted into a game mode via its manifest. + * Returns if the app will assume full responsibility for the experience provided by this + * mode. If True, the system will not perform any interventions for the app. * * @return True if the app package has specified in its metadata either: * "com.android.app.gamemode.performance.enabled" or * "com.android.app.gamemode.battery.enabled" with a value of "true" */ - public boolean isGameModeOptedIn(@GameMode int gameMode) { + public boolean willGamePerformOptimizations(@GameMode int gameMode) { return (mBatteryModeOptedIn && gameMode == GameManager.GAME_MODE_BATTERY) || (mPerfModeOptedIn && gameMode == GameManager.GAME_MODE_PERFORMANCE); } @@ -631,7 +659,34 @@ public final class GameManagerService extends IGameManagerService.Stub { mHandler.sendMessageDelayed(msg, WRITE_SETTINGS_DELAY); } } - updateCompatModeDownscale(packageName, gameMode); + updateInterventions(packageName, gameMode); + } + + /** + * Get if ANGLE is enabled for the package for the currently enabled game mode. + * Checks that the caller has {@link android.Manifest.permission#MANAGE_GAME_MODE}. + */ + @Override + @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) + public @GameMode boolean getAngleEnabled(String packageName, int userId) + throws SecurityException { + final int gameMode = getGameMode(packageName, userId); + if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) { + return false; + } + + synchronized (mDeviceConfigLock) { + final GamePackageConfiguration config = mConfigs.get(packageName); + if (config == null) { + return false; + } + GamePackageConfiguration.GameModeConfiguration gameModeConfiguration = + config.getGameModeConfiguration(gameMode); + if (gameModeConfiguration == null) { + return false; + } + return gameModeConfiguration.getUseAngle(); + } } /** @@ -753,7 +808,7 @@ public final class GameManagerService extends IGameManagerService.Stub { if (DEBUG) { Slog.v(TAG, dumpDeviceConfigs()); } - if (packageConfig.isGameModeOptedIn(gameMode)) { + if (packageConfig.willGamePerformOptimizations(gameMode)) { disableCompatScale(packageName); return; } @@ -782,6 +837,17 @@ public final class GameManagerService extends IGameManagerService.Stub { return (bitField & modeToBitmask(gameMode)) != 0; } + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + private void updateUseAngle(String packageName, @GameMode int gameMode) { + // TODO (b/188475576): Nothing to do yet. Remove if it's still empty when we're ready to + // ship. + } + + private void updateInterventions(String packageName, @GameMode int gameMode) { + updateCompatModeDownscale(packageName, gameMode); + updateUseAngle(packageName, gameMode); + } + /** * @hide */ @@ -839,11 +905,11 @@ public final class GameManagerService extends IGameManagerService.Stub { if (newGameMode != gameMode) { setGameMode(packageName, newGameMode, userId); } - updateCompatModeDownscale(packageName, gameMode); + updateInterventions(packageName, gameMode); } } } catch (Exception e) { - Slog.e(TAG, "Failed to update compat modes for user: " + userId); + Slog.e(TAG, "Failed to update compat modes for user " + userId + ": " + e); } } @@ -851,7 +917,7 @@ public final class GameManagerService extends IGameManagerService.Stub { final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(0, userId); return packages.stream().filter(e -> e.applicationInfo != null && e.applicationInfo.category - == ApplicationInfo.CATEGORY_GAME) + == ApplicationInfo.CATEGORY_GAME) .map(e -> e.packageName) .toArray(String[]::new); } diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index db2ecc54dbfe..19dcee4828dd 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -696,7 +696,7 @@ public final class AppHibernationService extends SystemService { idpw.print("User Level Hibernation States, "); idpw.printPair("user", userId); idpw.println(); - Map<String, UserLevelState> stateMap = mUserStates.get(i); + Map<String, UserLevelState> stateMap = mUserStates.get(userId); idpw.increaseIndent(); for (UserLevelState state : stateMap.values()) { idpw.print(state); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 87a6a6cba8c2..e4e6a5424efa 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -1752,11 +1752,10 @@ import java.util.concurrent.atomic.AtomicBoolean; 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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index f2769d696ba7..c0b58998ddf1 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -2631,18 +2631,19 @@ public class AudioService extends IAudioService.Stub case KeyEvent.KEYCODE_VOLUME_UP: adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller, - Binder.getCallingUid(), true, keyEventMode); + Binder.getCallingUid(), Binder.getCallingPid(), true, keyEventMode); break; case KeyEvent.KEYCODE_VOLUME_DOWN: adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller, - Binder.getCallingUid(), true, keyEventMode); + Binder.getCallingUid(), Binder.getCallingPid(), true, keyEventMode); break; case KeyEvent.KEYCODE_VOLUME_MUTE: if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { adjustSuggestedStreamVolume(AudioManager.ADJUST_TOGGLE_MUTE, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller, - Binder.getCallingUid(), true, VOL_ADJUST_NORMAL); + Binder.getCallingUid(), Binder.getCallingPid(), + true, VOL_ADJUST_NORMAL); } break; default: @@ -2655,8 +2656,8 @@ public class AudioService extends IAudioService.Stub public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller) { adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage, - caller, Binder.getCallingUid(), callingHasAudioSettingsPermission(), - VOL_ADJUST_NORMAL); + caller, Binder.getCallingUid(), Binder.getCallingPid(), + callingHasAudioSettingsPermission(), VOL_ADJUST_NORMAL); } public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) { @@ -2682,7 +2683,7 @@ public class AudioService extends IAudioService.Stub } private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, - String callingPackage, String caller, int uid, boolean hasModifyAudioSettings, + String callingPackage, String caller, int uid, int pid, boolean hasModifyAudioSettings, int keyEventMode) { if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType + ", flags=" + flags + ", caller=" + caller @@ -2759,7 +2760,7 @@ public class AudioService extends IAudioService.Stub if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment"); } - adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid, + adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid, pid, hasModifyAudioSettings, keyEventMode); } @@ -2791,12 +2792,12 @@ public class AudioService extends IAudioService.Stub sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType, direction/*val1*/, flags/*val2*/, callingPackage)); adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage, - Binder.getCallingUid(), callingHasAudioSettingsPermission(), - VOL_ADJUST_NORMAL); + Binder.getCallingUid(), Binder.getCallingPid(), + callingHasAudioSettingsPermission(), VOL_ADJUST_NORMAL); } protected void adjustStreamVolume(int streamType, int direction, int flags, - String callingPackage, String caller, int uid, boolean hasModifyAudioSettings, + String callingPackage, String caller, int uid, int pid, boolean hasModifyAudioSettings, int keyEventMode) { if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction + ", flags=" + flags + ", caller=" + caller); @@ -2819,8 +2820,7 @@ public class AudioService extends IAudioService.Stub if (isMuteAdjust && (streamType == AudioSystem.STREAM_VOICE_CALL || streamType == AudioSystem.STREAM_BLUETOOTH_SCO) && - mContext.checkCallingOrSelfPermission( - android.Manifest.permission.MODIFY_PHONE_STATE) + mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid) != PackageManager.PERMISSION_GRANTED) { Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); @@ -2830,8 +2830,8 @@ public class AudioService extends IAudioService.Stub // If the stream is STREAM_ASSISTANT, // make sure that the calling app have the MODIFY_AUDIO_ROUTING permission. if (streamType == AudioSystem.STREAM_ASSISTANT && - mContext.checkCallingOrSelfPermission( - android.Manifest.permission.MODIFY_AUDIO_ROUTING) + mContext.checkPermission( + android.Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid) != PackageManager.PERMISSION_GRANTED) { Log.w(TAG, "MODIFY_AUDIO_ROUTING Permission Denial: adjustStreamVolume from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); @@ -2863,8 +2863,8 @@ public class AudioService extends IAudioService.Stub if (uid == android.os.Process.SYSTEM_UID) { uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid)); } - if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage) - != AppOpsManager.MODE_ALLOWED) { + // validate calling package and app op + if (!checkNoteAppOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)) { return; } @@ -3588,8 +3588,7 @@ public class AudioService extends IAudioService.Stub if (uid == android.os.Process.SYSTEM_UID) { uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid)); } - if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage) - != AppOpsManager.MODE_ALLOWED) { + if (!checkNoteAppOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)) { return; } @@ -4017,20 +4016,19 @@ public class AudioService extends IAudioService.Stub } private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid, - int userId) { + int userId, int pid) { // If we are being called by the system check for user we are going to change // so we handle user restrictions correctly. if (uid == android.os.Process.SYSTEM_UID) { uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); } // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting. - if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) - != AppOpsManager.MODE_ALLOWED) { + if (!mute && !checkNoteAppOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)) { return; } if (userId != UserHandle.getCallingUserId() && - mContext.checkCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + pid, uid) != PackageManager.PERMISSION_GRANTED) { return; } @@ -4070,7 +4068,7 @@ public class AudioService extends IAudioService.Stub public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) { enforceModifyAudioRoutingPermission(); setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(), - userId); + userId, Binder.getCallingPid()); } /** @see AudioManager#getStreamVolume(int) */ @@ -4156,8 +4154,7 @@ public class AudioService extends IAudioService.Stub ? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE); // If OP_MUTE_MICROPHONE is set, disallow unmuting. - if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage) - != AppOpsManager.MODE_ALLOWED) { + if (!on && !checkNoteAppOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)) { mmi.set(MediaMetrics.Property.EARLY_RETURN, "disallow unmuting").record(); return; } @@ -4972,8 +4969,8 @@ public class AudioService extends IAudioService.Stub // direction and stream type swap here because the public // adjustSuggested has a different order than the other methods. - adjustSuggestedStreamVolume(direction, streamType, flags, packageName, packageName, uid, - hasAudioSettingsPermission(uid, pid), VOL_ADJUST_NORMAL); + adjustSuggestedStreamVolume(direction, streamType, flags, packageName, packageName, + uid, pid, hasAudioSettingsPermission(uid, pid), VOL_ADJUST_NORMAL); } /** @see AudioManager#adjustStreamVolumeForUid(int, int, int, String, int, int, int) */ @@ -4992,7 +4989,7 @@ public class AudioService extends IAudioService.Stub .toString())); } - adjustStreamVolume(streamType, direction, flags, packageName, packageName, uid, + adjustStreamVolume(streamType, direction, flags, packageName, packageName, uid, pid, hasAudioSettingsPermission(uid, pid), VOL_ADJUST_NORMAL); } @@ -5341,6 +5338,10 @@ public class AudioService extends IAudioService.Stub // TODO investigate internal users due to deprecation of SDK API /** @see AudioManager#setBluetoothA2dpOn(boolean) */ public void setBluetoothA2dpOn(boolean on) { + if (!checkAudioSettingsPermission("setBluetoothA2dpOn()")) { + return; + } + // for logging only final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); @@ -5367,11 +5368,16 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothSco() */ public void startBluetoothSco(IBinder cb, int targetSdkVersion) { Log.i(TAG, "In startBluetoothSco()"); + if (!checkAudioSettingsPermission("startBluetoothSco()")) { + return; + } + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if ((adapter == null) || (adapter.getState() != BluetoothAdapter.STATE_ON)) { Log.i(TAG, "startBluetoothSco(), BT is not turned ON or adapter is null"); return; } + final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int scoAudioMode = @@ -5395,6 +5401,10 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothScoVirtualCall() */ public void startBluetoothScoVirtualCall(IBinder cb) { Log.i(TAG, "In startBluetoothScoVirtualCall()"); + if (!checkAudioSettingsPermission("startBluetoothScoVirtualCall()")) { + return; + } + final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()") @@ -10612,4 +10622,31 @@ public class AudioService extends IAudioService.Stub } mFullVolumeDevices.remove(audioSystemDeviceOut); } + + //==================== + // Helper functions for app ops + //==================== + /** + * Validates, and notes an app op for a given uid and package name. + * Validation comes from exception catching: a security exception indicates the package + * doesn't exist, an IAE indicates the uid and package don't match. The code only checks + * if exception was thrown for robustness to code changes in op validation + * @param op the app op to check + * @param uid the uid of the caller + * @param packageName the package to check + * @return true if the origin of the call is valid (no uid / package mismatch) and the caller + * is allowed to perform the operation + */ + private boolean checkNoteAppOp(int op, int uid, String packageName) { + try { + if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { + return false; + } + } catch (Exception e) { + Log.e(TAG, "Error noting op:" + op + " on uid:" + uid + " for package:" + + packageName, e); + return false; + } + return true; + } } diff --git a/services/core/java/com/android/server/audio/FadeOutManager.java b/services/core/java/com/android/server/audio/FadeOutManager.java index bb627e5a21fb..00cb280236d7 100644 --- a/services/core/java/com/android/server/audio/FadeOutManager.java +++ b/services/core/java/com/android/server/audio/FadeOutManager.java @@ -36,7 +36,16 @@ public final class FadeOutManager { public static final String TAG = "AudioService.FadeOutManager"; + /** duration of the fade out curve */ /*package*/ static final long FADE_OUT_DURATION_MS = 2000; + /** + * delay after which a faded out player will be faded back in. This will be heard by the user + * only in the case of unmuting players that didn't respect audio focus and didn't stop/pause + * when their app lost focus. + * This is the amount of time between the app being notified of + * the focus loss (when its muted by the fade out), and the time fade in (to unmute) starts + */ + /*package*/ static final long DELAY_FADE_IN_OFFENDERS_MS = 2000; private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG; @@ -148,6 +157,11 @@ public final class FadeOutManager { } } + /** + * Remove the app for the given UID from the list of faded out apps, unfade out its players + * @param uid the uid for the app to unfade out + * @param players map of current available players (so we can get an APC from piid) + */ synchronized void unfadeOutUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { Log.i(TAG, "unfadeOutUid() uid:" + uid); final FadedOutApp fa = mFadedApps.remove(uid); @@ -157,12 +171,6 @@ public final class FadeOutManager { fa.removeUnfadeAll(players); } - synchronized void forgetUid(int uid) { - //Log.v(TAG, "forget() uid:" + uid); - //mFadedApps.remove(uid); - // TODO unfade all players later in case they are reused or the app continued to play - } - // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // see {@link PlaybackActivityMonitor#playerEvent} synchronized void checkFade(@NonNull AudioPlaybackConfiguration apc) { diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index e6c4abfa2086..9548ada14b8e 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -131,6 +131,11 @@ public class MediaFocusControl implements PlayerFocusEnforcer { @Override public void restoreVShapedPlayers(@NonNull FocusRequester winner) { mFocusEnforcer.restoreVShapedPlayers(winner); + // remove scheduled events to unfade out offending players (if any) corresponding to + // this uid, as we're removing any effects of muting/ducking/fade out now + mFocusHandler.removeEqualMessages(MSL_L_FORGET_UID, + new ForgetFadeUidInfo(winner.getClientUid())); + } @Override @@ -1182,6 +1187,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer { mFocusHandler.obtainMessage(MSG_L_FOCUS_LOSS_AFTER_FADE, focusLoser), FadeOutManager.FADE_OUT_DURATION_MS); } + + private void postForgetUidLater(int uid) { + mFocusHandler.sendMessageDelayed( + mFocusHandler.obtainMessage(MSL_L_FORGET_UID, new ForgetFadeUidInfo(uid)), + FadeOutManager.DELAY_FADE_IN_OFFENDERS_MS); + } + //================================================================= // Message handling private Handler mFocusHandler; @@ -1196,6 +1208,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer { */ private static final int MSG_L_FOCUS_LOSS_AFTER_FADE = 1; + private static final int MSL_L_FORGET_UID = 2; + private void initFocusThreading() { mFocusThread = new HandlerThread(TAG); mFocusThread.start(); @@ -1213,15 +1227,56 @@ public class MediaFocusControl implements PlayerFocusEnforcer { if (loser.isInFocusLossLimbo()) { loser.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS); loser.release(); - mFocusEnforcer.forgetUid(loser.getClientUid()); + postForgetUidLater(loser.getClientUid()); } } break; + + case MSL_L_FORGET_UID: + final int uid = ((ForgetFadeUidInfo) msg.obj).mUid; + if (DEBUG) { + Log.d(TAG, "MSL_L_FORGET_UID uid=" + uid); + } + mFocusEnforcer.forgetUid(uid); + break; default: break; } } }; + } + /** + * Class to associate a UID with a scheduled event to "forget" a UID for the fade out behavior. + * Having a class with an equals() override allows using Handler.removeEqualsMessage() to + * unschedule events when needed. Here we need to unschedule the "unfading out" == "forget uid" + * whenever a new, more recent, focus related event happens before this one is handled. + */ + private static final class ForgetFadeUidInfo { + private final int mUid; + + ForgetFadeUidInfo(int uid) { + mUid = uid; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ForgetFadeUidInfo f = (ForgetFadeUidInfo) o; + if (f.mUid != mUid) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return mUid; + } } } diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index a13b2eb344d9..b94cea4d5d40 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -747,7 +747,11 @@ public final class PlaybackActivityMonitor @Override public void forgetUid(int uid) { - mFadingManager.forgetUid(uid); + final HashMap<Integer, AudioPlaybackConfiguration> players; + synchronized (mPlayerLock) { + players = (HashMap<Integer, AudioPlaybackConfiguration>) mPlayers.clone(); + } + mFadingManager.unfadeOutUid(uid, players); } //================================================================= diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 0cd2e3d0ff59..b42f8980d1c0 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -206,7 +206,7 @@ public class AuthService extends SystemService { } @Override - public void authenticate(IBinder token, long sessionId, int userId, + public long authenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) throws RemoteException { // Only allow internal clients to authenticate with a different userId. @@ -223,18 +223,18 @@ public class AuthService extends SystemService { if (!checkAppOps(callingUid, opPackageName, "authenticate()")) { authenticateFastFail("Denied by app ops: " + opPackageName, receiver); - return; + return -1; } if (token == null || receiver == null || opPackageName == null || promptInfo == null) { authenticateFastFail( "Unable to authenticate, one or more null arguments", receiver); - return; + return -1; } if (!Utils.isForeground(callingUid, callingPid)) { authenticateFastFail("Caller is not foreground: " + opPackageName, receiver); - return; + return -1; } if (promptInfo.containsTestConfigurations()) { @@ -251,7 +251,7 @@ public class AuthService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { - mBiometricService.authenticate( + return mBiometricService.authenticate( token, sessionId, userId, receiver, opPackageName, promptInfo); } finally { Binder.restoreCallingIdentity(identity); @@ -270,7 +270,7 @@ public class AuthService extends SystemService { } @Override - public void cancelAuthentication(IBinder token, String opPackageName) + public void cancelAuthentication(IBinder token, String opPackageName, long requestId) throws RemoteException { checkPermission(); @@ -281,7 +281,7 @@ public class AuthService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { - mBiometricService.cancelAuthentication(token, opPackageName); + mBiometricService.cancelAuthentication(token, opPackageName, requestId); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index bdde980f5cae..0da6a1ba3109 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -128,6 +128,7 @@ public final class AuthSession implements IBinder.DeathRecipient { @VisibleForTesting final IBinder mToken; // Info to be shown on BiometricDialog when all cookies are returned. @VisibleForTesting final PromptInfo mPromptInfo; + private final long mRequestId; private final long mOperationId; private final int mUserId; private final IBiometricSensorReceiver mSensorReceiver; @@ -142,6 +143,8 @@ public final class AuthSession implements IBinder.DeathRecipient { private @BiometricMultiSensorMode int mMultiSensorMode; private @MultiSensorState int mMultiSensorState; private int[] mSensors; + // TODO(b/197265902): merge into state + private boolean mCancelled; // For explicit confirmation, do not send to keystore until the user has confirmed // the authentication. private byte[] mTokenEscrow; @@ -162,6 +165,7 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull ClientDeathReceiver clientDeathReceiver, @NonNull PreAuthInfo preAuthInfo, @NonNull IBinder token, + long requestId, long operationId, int userId, @NonNull IBiometricSensorReceiver sensorReceiver, @@ -179,6 +183,7 @@ public final class AuthSession implements IBinder.DeathRecipient { mClientDeathReceiver = clientDeathReceiver; mPreAuthInfo = preAuthInfo; mToken = token; + mRequestId = requestId; mOperationId = operationId; mUserId = userId; mSensorReceiver = sensorReceiver; @@ -187,6 +192,7 @@ public final class AuthSession implements IBinder.DeathRecipient { mPromptInfo = promptInfo; mDebugEnabled = debugEnabled; mFingerprintSensorProperties = fingerprintSensorProperties; + mCancelled = false; try { mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */); @@ -233,7 +239,7 @@ public final class AuthSession implements IBinder.DeathRecipient { Slog.v(TAG, "waiting for cooking for sensor: " + sensor.id); } sensor.goToStateWaitingForCookie(requireConfirmation, mToken, mOperationId, - mUserId, mSensorReceiver, mOpPackageName, cookie, + mUserId, mSensorReceiver, mOpPackageName, mRequestId, cookie, mPromptInfo.isAllowBackgroundAuthentication()); } } @@ -255,8 +261,9 @@ public final class AuthSession implements IBinder.DeathRecipient { true /* credentialAllowed */, false /* requireConfirmation */, mUserId, - mOpPackageName, mOperationId, + mOpPackageName, + mRequestId, mMultiSensorMode); } else if (!mPreAuthInfo.eligibleSensors.isEmpty()) { // Some combination of biometric or biometric|credential is requested @@ -270,6 +277,11 @@ public final class AuthSession implements IBinder.DeathRecipient { } void onCookieReceived(int cookie) { + if (mCancelled) { + Slog.w(TAG, "Received cookie but already cancelled (ignoring): " + cookie); + return; + } + for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) { sensor.goToStateCookieReturnedIfCookieMatches(cookie); } @@ -301,8 +313,9 @@ public final class AuthSession implements IBinder.DeathRecipient { mPreAuthInfo.shouldShowCredential(), requireConfirmation, mUserId, - mOpPackageName, mOperationId, + mOpPackageName, + mRequestId, mMultiSensorMode); mState = STATE_AUTH_STARTED; } catch (RemoteException e) { @@ -369,7 +382,7 @@ public final class AuthSession implements IBinder.DeathRecipient { final boolean shouldCancel = filter.apply(sensor); Slog.d(TAG, "sensorId: " + sensor.id + ", shouldCancel: " + shouldCancel); if (shouldCancel) { - sensor.goToStateCancelling(mToken, mOpPackageName); + sensor.goToStateCancelling(mToken, mOpPackageName, mRequestId); } } catch (RemoteException e) { Slog.e(TAG, "Unable to cancel authentication"); @@ -425,8 +438,9 @@ public final class AuthSession implements IBinder.DeathRecipient { true /* credentialAllowed */, false /* requireConfirmation */, mUserId, - mOpPackageName, mOperationId, + mOpPackageName, + mRequestId, mMultiSensorMode); } else { mClientReceiver.onError(modality, error, vendorCode); @@ -775,6 +789,8 @@ public final class AuthSession implements IBinder.DeathRecipient { * @return true if this AuthSession is finished, e.g. should be set to null */ boolean onCancelAuthSession(boolean force) { + mCancelled = true; + final boolean authStarted = mState == STATE_AUTH_CALLED || mState == STATE_AUTH_STARTED || mState == STATE_AUTH_STARTED_UI_SHOWING; @@ -820,6 +836,7 @@ public final class AuthSession implements IBinder.DeathRecipient { return Utils.isCredentialRequested(mPromptInfo); } + @VisibleForTesting boolean allCookiesReceived() { final int remainingCookies = mPreAuthInfo.numSensorsWaitingForCookie(); Slog.d(TAG, "Remaining cookies: " + remainingCookies); @@ -839,6 +856,10 @@ public final class AuthSession implements IBinder.DeathRecipient { return mState; } + long getRequestId() { + return mRequestId; + } + private int statsModality() { int modality = 0; @@ -901,7 +922,9 @@ public final class AuthSession implements IBinder.DeathRecipient { @Override public String toString() { return "State: " + mState + + ", cancelled: " + mCancelled + ", isCrypto: " + isCrypto() - + ", PreAuthInfo: " + mPreAuthInfo; + + ", PreAuthInfo: " + mPreAuthInfo + + ", requestId: " + mRequestId; } } diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java index 8a842b53d8e8..0333c3e247c0 100644 --- a/services/core/java/com/android/server/biometrics/BiometricSensor.java +++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java @@ -108,11 +108,11 @@ public abstract class BiometricSensor { void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, - int cookie, boolean allowBackgroundAuthentication) + long requestId, int cookie, boolean allowBackgroundAuthentication) throws RemoteException { mCookie = cookie; impl.prepareForAuthentication(requireConfirmation, token, - sessionId, userId, sensorReceiver, opPackageName, mCookie, + sessionId, userId, sensorReceiver, opPackageName, requestId, mCookie, allowBackgroundAuthentication); mSensorState = STATE_WAITING_FOR_COOKIE; } @@ -129,8 +129,9 @@ public abstract class BiometricSensor { mSensorState = STATE_AUTHENTICATING; } - void goToStateCancelling(IBinder token, String opPackageName) throws RemoteException { - impl.cancelAuthenticationFromService(token, opPackageName); + void goToStateCancelling(IBinder token, String opPackageName, long requestId) + throws RemoteException { + impl.cancelAuthenticationFromService(token, opPackageName, requestId); mSensorState = STATE_CANCELING; } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index b1d300cd838e..e0775d48b42f 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -83,6 +83,7 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; /** * System service that arbitrates the modality for BiometricPrompt to use. @@ -115,6 +116,7 @@ public class BiometricService extends SystemService { final SettingObserver mSettingObserver; private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks; private final Random mRandom = new Random(); + @NonNull private final AtomicLong mRequestCounter; @VisibleForTesting IStatusBarService mStatusBarService; @@ -194,6 +196,7 @@ public class BiometricService extends SystemService { SomeArgs args = (SomeArgs) msg.obj; handleAuthenticate( (IBinder) args.arg1 /* token */, + (long) args.arg6 /* requestId */, (long) args.arg2 /* operationId */, args.argi1 /* userid */, (IBiometricServiceReceiver) args.arg3 /* receiver */, @@ -204,7 +207,9 @@ public class BiometricService extends SystemService { } case MSG_CANCEL_AUTHENTICATION: { - handleCancelAuthentication(); + SomeArgs args = (SomeArgs) msg.obj; + handleCancelAuthentication((long) args.arg3 /* requestId */); + args.recycle(); break; } @@ -683,13 +688,13 @@ public class BiometricService extends SystemService { } @Override // Binder call - public void authenticate(IBinder token, long operationId, int userId, + public long authenticate(IBinder token, long operationId, int userId, IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) { checkInternalPermission(); if (token == null || receiver == null || opPackageName == null || promptInfo == null) { Slog.e(TAG, "Unable to authenticate, one or more null arguments"); - return; + return -1; } if (!Utils.isValidAuthenticatorConfig(promptInfo)) { @@ -706,6 +711,8 @@ public class BiometricService extends SystemService { } } + final long requestId = mRequestCounter.incrementAndGet(); + SomeArgs args = SomeArgs.obtain(); args.arg1 = token; args.arg2 = operationId; @@ -713,15 +720,23 @@ public class BiometricService extends SystemService { args.arg3 = receiver; args.arg4 = opPackageName; args.arg5 = promptInfo; + args.arg6 = requestId; mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget(); + + return requestId; } @Override // Binder call - public void cancelAuthentication(IBinder token, String opPackageName) { + public void cancelAuthentication(IBinder token, String opPackageName, long requestId) { checkInternalPermission(); - mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = token; + args.arg2 = opPackageName; + args.arg3 = requestId; + + mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget(); } @Override // Binder call @@ -1111,6 +1126,10 @@ public class BiometricService extends SystemService { return Settings.Secure.getInt(context.getContentResolver(), CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0; } + + public AtomicLong getRequestGenerator() { + return new AtomicLong(0); + } } /** @@ -1136,6 +1155,7 @@ public class BiometricService extends SystemService { mEnabledOnKeyguardCallbacks = new ArrayList<>(); mSettingObserver = mInjector.getSettingObserver(context, mHandler, mEnabledOnKeyguardCallbacks); + mRequestCounter = mInjector.getRequestGenerator(); // TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't // need to depend on context. We can remove this code once the advanced logic is enabled @@ -1349,7 +1369,7 @@ public class BiometricService extends SystemService { mCurrentAuthSession.onCookieReceived(cookie); } - private void handleAuthenticate(IBinder token, long operationId, int userId, + private void handleAuthenticate(IBinder token, long requestId, long operationId, int userId, IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) { mHandler.post(() -> { try { @@ -1360,7 +1380,8 @@ public class BiometricService extends SystemService { final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus(); Slog.d(TAG, "handleAuthenticate: modality(" + preAuthStatus.first - + "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo); + + "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo + + " requestId: " + requestId); if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) { // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but @@ -1372,8 +1393,8 @@ public class BiometricService extends SystemService { promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL); } - authenticateInternal(token, operationId, userId, receiver, opPackageName, - promptInfo, preAuthInfo); + authenticateInternal(token, requestId, operationId, userId, receiver, + opPackageName, promptInfo, preAuthInfo); } else { receiver.onError(preAuthStatus.first /* modality */, preAuthStatus.second /* errorCode */, @@ -1394,7 +1415,7 @@ public class BiometricService extends SystemService { * Note that this path is NOT invoked when the BiometricPrompt "Try again" button is pressed. * In that case, see {@link #handleOnTryAgainPressed()}. */ - private void authenticateInternal(IBinder token, long operationId, int userId, + private void authenticateInternal(IBinder token, long requestId, long operationId, int userId, IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo, PreAuthInfo preAuthInfo) { Slog.d(TAG, "Creating authSession with authRequest: " + preAuthInfo); @@ -1412,9 +1433,9 @@ public class BiometricService extends SystemService { final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId); mCurrentAuthSession = new AuthSession(getContext(), mStatusBarService, mSysuiReceiver, - mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, token, operationId, userId, - mBiometricSensorReceiver, receiver, opPackageName, promptInfo, debugEnabled, - mInjector.getFingerprintSensorProperties(getContext())); + mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, token, requestId, + operationId, userId, mBiometricSensorReceiver, receiver, opPackageName, promptInfo, + debugEnabled, mInjector.getFingerprintSensorProperties(getContext())); try { mCurrentAuthSession.goToInitialState(); } catch (RemoteException e) { @@ -1422,11 +1443,21 @@ public class BiometricService extends SystemService { } } - private void handleCancelAuthentication() { + private void handleCancelAuthentication(long requestId) { if (mCurrentAuthSession == null) { Slog.e(TAG, "handleCancelAuthentication: AuthSession is null"); return; } + if (mCurrentAuthSession.getRequestId() != requestId) { + // TODO: actually cancel the operation + // This can happen if the operation has been queued, but is cancelled before + // it reaches the head of the scheduler. Consider it a programming error for now + // and ignore it. + Slog.e(TAG, "handleCancelAuthentication: AuthSession mismatch current requestId: " + + mCurrentAuthSession.getRequestId() + " cancel for: " + requestId + + " (ignoring cancellation)"); + return; + } final boolean finished = mCurrentAuthSession.onCancelAuthSession(false /* force */); if (finished) { diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java index 3eb6f4ae48a2..9764a167fbbf 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -26,6 +26,8 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; /** @@ -70,26 +72,32 @@ public abstract class BaseClientMonitor extends LoggableMonitor } /** Holder for wrapping multiple handlers into a single Callback. */ - protected static class CompositeCallback implements Callback { + public static class CompositeCallback implements Callback { @NonNull - private final Callback[] mCallbacks; + private final List<Callback> mCallbacks; public CompositeCallback(@NonNull Callback... callbacks) { - mCallbacks = callbacks; + mCallbacks = new ArrayList<>(); + + for (Callback callback : callbacks) { + if (callback != null) { + mCallbacks.add(callback); + } + } } @Override public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { - for (int i = 0; i < mCallbacks.length; i++) { - mCallbacks[i].onClientStarted(clientMonitor); + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).onClientStarted(clientMonitor); } } @Override public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { - for (int i = mCallbacks.length - 1; i >= 0; i--) { - mCallbacks[i].onClientFinished(clientMonitor, success); + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + mCallbacks.get(i).onClientFinished(clientMonitor, success); } } } @@ -101,6 +109,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor private final int mSensorId; // sensorId as configured by the framework @Nullable private IBinder mToken; + private long mRequestId; @Nullable private ClientMonitorCallbackConverter mListener; // Currently only used for authentication client. The cookie generated by BiometricService // is never 0. @@ -154,6 +163,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor mSequentialId = sCount++; mContext = context; mToken = token; + mRequestId = -1; mListener = listener; mTargetUserId = userId; mOwner = owner; @@ -254,10 +264,33 @@ public abstract class BaseClientMonitor extends LoggableMonitor return mToken; } - public final int getSensorId() { + public int getSensorId() { return mSensorId; } + /** Unique request id. */ + public final long getRequestId() { + return mRequestId; + } + + /** If a unique id has been set via {@link #setRequestId(long)} */ + public final boolean hasRequestId() { + return mRequestId > 0; + } + + /** + * A unique identifier used to tie this operation to a request (i.e an API invocation). + * + * Subclasses should not call this method if this operation does not have a direct + * correspondence to a request and {@link #hasRequestId()} will return false. + */ + protected final void setRequestId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("request id must be positive"); + } + mRequestId = id; + } + @VisibleForTesting public Callback getCallback() { return mCallback; @@ -270,6 +303,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor + ", proto=" + getProtoEnum() + ", owner=" + getOwnerString() + ", cookie=" + getCookie() + + ", requestId=" + getRequestId() + ", userId=" + getTargetUserId() + "}"; } } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index feb9e2a5b03f..361ec40f2877 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -643,22 +643,18 @@ public class BiometricScheduler { /** * Requests to cancel authentication or detection. * @param token from the caller, should match the token passed in when requesting authentication + * @param requestId the id returned when requesting authentication */ - public void cancelAuthenticationOrDetection(IBinder token) { - if (mCurrentOperation == null) { - Slog.e(getTag(), "Unable to cancel authentication, null operation"); - return; - } - final boolean isCorrectClient = isAuthenticationOrDetectionOperation(mCurrentOperation); - final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token; - - Slog.d(getTag(), "cancelAuthenticationOrDetection, isCorrectClient: " + isCorrectClient - + ", tokenMatches: " + tokenMatches); + public void cancelAuthenticationOrDetection(IBinder token, long requestId) { + Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId + + " current: " + mCurrentOperation + + " stack size: " + mPendingOperations.size()); - if (isCorrectClient && tokenMatches) { + if (mCurrentOperation != null + && canCancelAuthOperation(mCurrentOperation, token, requestId)) { Slog.d(getTag(), "Cancelling: " + mCurrentOperation); cancelInternal(mCurrentOperation); - } else if (!isCorrectClient) { + } else { // Look through the current queue for all authentication clients for the specified // token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking // all of them, instead of just the first one, since the API surface currently doesn't @@ -666,8 +662,7 @@ public class BiometricScheduler { // process. However, this generally does not happen anyway, and would be a class of // bugs on its own. for (Operation operation : mPendingOperations) { - if (isAuthenticationOrDetectionOperation(operation) - && operation.mClientMonitor.getToken() == token) { + if (canCancelAuthOperation(operation, token, requestId)) { Slog.d(getTag(), "Marking " + operation + " as STATE_WAITING_IN_QUEUE_CANCELING"); operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING; @@ -676,10 +671,26 @@ public class BiometricScheduler { } } - private boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) { - final boolean isAuthentication = operation.mClientMonitor - instanceof AuthenticationConsumer; - final boolean isDetection = operation.mClientMonitor instanceof DetectionConsumer; + private static boolean canCancelAuthOperation(Operation operation, IBinder token, + long requestId) { + // TODO: restrict callers that can cancel without requestId (negative value)? + return isAuthenticationOrDetectionOperation(operation) + && operation.mClientMonitor.getToken() == token + && isMatchingRequestId(operation, requestId); + } + + // By default, monitors are not associated with a request id to retain the original + // behavior (i.e. if no requestId is explicitly set then assume it matches) + private static boolean isMatchingRequestId(Operation operation, long requestId) { + return !operation.mClientMonitor.hasRequestId() + || operation.mClientMonitor.getRequestId() == requestId; + } + + private static boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) { + final boolean isAuthentication = + operation.mClientMonitor instanceof AuthenticationConsumer; + final boolean isDetection = + operation.mClientMonitor instanceof DetectionConsumer; return isAuthentication || isDetection; } diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java index a15e14b79e30..9191b8b55989 100644 --- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java @@ -31,7 +31,7 @@ import java.util.Arrays; /** * A class to keep track of the enrollment state for a given client. */ -public abstract class EnrollClient<T> extends AcquisitionClient<T> { +public abstract class EnrollClient<T> extends AcquisitionClient<T> implements EnrollmentModifier { private static final String TAG = "Biometrics/EnrollClient"; @@ -40,6 +40,7 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> { protected final BiometricUtils mBiometricUtils; private long mEnrollmentStartTimeMs; + private final boolean mHasEnrollmentsBeforeStarting; /** * @return true if the user has already enrolled the maximum number of templates. @@ -56,6 +57,18 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> { mBiometricUtils = utils; mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length); mTimeoutSec = timeoutSec; + mHasEnrollmentsBeforeStarting = hasEnrollments(); + } + + @Override + public boolean hasEnrollmentStateChanged() { + final boolean hasEnrollmentsNow = hasEnrollments(); + return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting; + } + + @Override + public boolean hasEnrollments() { + return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty(); } public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) { diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java b/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java new file mode 100644 index 000000000000..c2f909b08bb6 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java @@ -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 com.android.server.biometrics.sensors; + +/** + * Interface for {@link BaseClientMonitor} subclasses that affect the state of enrollment. + */ +public interface EnrollmentModifier { + + /** + * Callers should typically check this after + * {@link BaseClientMonitor.Callback#onClientFinished(BaseClientMonitor, boolean)} + * + * @return true if the user has gone from: + * 1) none-enrolled --> enrolled + * 2) enrolled --> none-enrolled + * but NOT any-enrolled --> more-enrolled + */ + boolean hasEnrollmentStateChanged(); + + /** + * @return true if the user has any enrollments + */ + boolean hasEnrollments(); +} diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java index 282261e6556f..579dfd69ec66 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -40,7 +40,8 @@ import java.util.Map; * {@link #onRemoved(BiometricAuthenticator.Identifier, int)} returns true/ */ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Identifier, T> - extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer { + extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer, + EnrollmentModifier { private static final String TAG = "Biometrics/InternalCleanupClient"; @@ -61,6 +62,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide private final BiometricUtils<S> mBiometricUtils; private final Map<Integer, Long> mAuthenticatorIds; private final List<S> mEnrolledList; + private final boolean mHasEnrollmentsBeforeStarting; private BaseClientMonitor mCurrentTask; private final Callback mEnumerateCallback = new Callback() { @@ -115,6 +117,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide mBiometricUtils = utils; mAuthenticatorIds = authenticatorIds; mEnrolledList = enrolledList; + mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty(); } private void startCleanupUnknownHalTemplates() { @@ -166,6 +169,18 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide } @Override + public boolean hasEnrollmentStateChanged() { + final boolean hasEnrollmentsNow = !mBiometricUtils + .getBiometricsForUser(getContext(), getTargetUserId()).isEmpty(); + return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting; + } + + @Override + public boolean hasEnrollments() { + return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty(); + } + + @Override public void onEnumerationResult(BiometricAuthenticator.Identifier identifier, int remaining) { if (!(mCurrentTask instanceof InternalEnumerateClient)) { diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java index 383efce5bb2a..2a6677e55d60 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -33,12 +33,13 @@ import java.util.Map; * A class to keep track of the remove state for a given client. */ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, T> - extends HalClientMonitor<T> implements RemovalConsumer { + extends HalClientMonitor<T> implements RemovalConsumer, EnrollmentModifier { private static final String TAG = "Biometrics/RemovalClient"; private final BiometricUtils<S> mBiometricUtils; private final Map<Integer, Long> mAuthenticatorIds; + private final boolean mHasEnrollmentsBeforeStarting; public RemovalClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, @@ -49,6 +50,7 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricUtils = utils; mAuthenticatorIds = authenticatorIds; + mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty(); } @Override @@ -91,6 +93,18 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, } @Override + public boolean hasEnrollmentStateChanged() { + final boolean hasEnrollmentsNow = !mBiometricUtils + .getBiometricsForUser(getContext(), getTargetUserId()).isEmpty(); + return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting; + } + + @Override + public boolean hasEnrollments() { + return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty(); + } + + @Override public int getProtoEnum() { return BiometricsProto.CM_REMOVE; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java index 0bc4f1b54d59..b2fd46d1475d 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java @@ -61,10 +61,11 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { @Override public void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, - String opPackageName, int cookie, boolean allowBackgroundAuthentication) + String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication) throws RemoteException { mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId, - userId, sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication); + userId, sensorReceiver, opPackageName, requestId, cookie, + allowBackgroundAuthentication); } @Override @@ -73,9 +74,9 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public void cancelAuthenticationFromService(IBinder token, String opPackageName) + public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId) throws RemoteException { - mFaceService.cancelAuthenticationFromService(mSensorId, token, opPackageName); + mFaceService.cancelAuthenticationFromService(mSensorId, token, opPackageName, requestId); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 12d6b08b8bcf..675ee545a14f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -250,7 +250,7 @@ public class FaceService extends SystemService { } @Override // Binder call - public void authenticate(final IBinder token, final long operationId, int userId, + public long authenticate(final IBinder token, final long operationId, int userId, final IFaceServiceReceiver receiver, final String opPackageName, boolean isKeyguardBypassEnabled) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); @@ -270,38 +270,38 @@ public class FaceService extends SystemService { final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for authenticate"); - return; + return -1; } - provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, + return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName, restricted, statsClient, isKeyguard, isKeyguardBypassEnabled); } @Override // Binder call - public void detectFace(final IBinder token, final int userId, + public long detectFace(final IBinder token, final int userId, final IFaceServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); if (!Utils.isKeyguard(getContext(), opPackageName)) { Slog.w(TAG, "detectFace called from non-sysui package: " + opPackageName); - return; + return -1; } if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { // If this happens, something in KeyguardUpdateMonitor is wrong. This should only // ever be invoked when the user is encrypted or lockdown. Slog.e(TAG, "detectFace invoked when user is not encrypted or lockdown"); - return; + return -1; } final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFace"); - return; + return -1; } - provider.second.scheduleFaceDetect(provider.first, token, userId, + return provider.second.scheduleFaceDetect(provider.first, token, userId, new ClientMonitorCallbackConverter(receiver), opPackageName, BiometricsProtoEnums.CLIENT_KEYGUARD); } @@ -309,8 +309,8 @@ public class FaceService extends SystemService { @Override // Binder call public void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, long operationId, int userId, - IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie, - boolean allowBackgroundAuthentication) { + IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId, + int cookie, boolean allowBackgroundAuthentication) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -322,9 +322,9 @@ public class FaceService extends SystemService { final boolean isKeyguardBypassEnabled = false; // only valid for keyguard clients final boolean restricted = true; // BiometricPrompt is always restricted provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie, - new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted, - BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication, - isKeyguardBypassEnabled); + new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId, + restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, + allowBackgroundAuthentication, isKeyguardBypassEnabled); } @Override // Binder call @@ -341,7 +341,8 @@ public class FaceService extends SystemService { } @Override // Binder call - public void cancelAuthentication(final IBinder token, final String opPackageName) { + public void cancelAuthentication(final IBinder token, final String opPackageName, + final long requestId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final Pair<Integer, ServiceProvider> provider = getSingleProvider(); @@ -350,11 +351,12 @@ public class FaceService extends SystemService { return; } - provider.second.cancelAuthentication(provider.first, token); + provider.second.cancelAuthentication(provider.first, token, requestId); } @Override // Binder call - public void cancelFaceDetect(final IBinder token, final String opPackageName) { + public void cancelFaceDetect(final IBinder token, final String opPackageName, + final long requestId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); if (!Utils.isKeyguard(getContext(), opPackageName)) { Slog.w(TAG, "cancelFaceDetect called from non-sysui package: " @@ -368,12 +370,12 @@ public class FaceService extends SystemService { return; } - provider.second.cancelFaceDetect(provider.first, token); + provider.second.cancelFaceDetect(provider.first, token, requestId); } @Override // Binder call public void cancelAuthenticationFromService(int sensorId, final IBinder token, - final String opPackageName) { + final String opPackageName, final long requestId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -382,7 +384,7 @@ public class FaceService extends SystemService { return; } - provider.cancelAuthentication(sensorId, token); + provider.cancelAuthentication(sensorId, token, requestId); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java index 93ab1b65edff..e099ba372b05 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java @@ -101,18 +101,23 @@ public interface ServiceProvider { void cancelEnrollment(int sensorId, @NonNull IBinder token); - void scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, + long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, int statsClient); - void cancelFaceDetect(int sensorId, @NonNull IBinder token); + void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId); - void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, + long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled); - void cancelAuthentication(int sensorId, @NonNull IBinder token); + void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, + int cookie, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled); + + void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId); void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index d66a27920f49..cbceba6cc959 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -65,7 +65,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements @FaceManager.FaceAcquired private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN; FaceAuthenticationClient(@NonNull Context context, - @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<ISession> lazyDaemon, + @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats, @@ -76,6 +77,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */, lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */, isKeyguardBypassEnabled); + setRequestId(requestId); mUsageStats = usageStats; mLockoutCache = lockoutCache; mNotificationManager = context.getSystemService(NotificationManager.class); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java index 1e73ac528f08..2ef0911658b1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java @@ -43,11 +43,13 @@ public class FaceDetectClient extends AcquisitionClient<ISession> implements Det @Nullable private ICancellationSignal mCancellationSignal; public FaceDetectClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, - @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull IBinder token, long requestId, + @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FACE, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); + setRequestId(requestId); mIsStrongBiometric = isStrongBiometric; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 718b9da968f5..4bae7756abe0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -65,6 +65,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; /** * Provider for a single instance of the {@link IFace} HAL. @@ -83,6 +84,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { @NonNull private final UsageStats mUsageStats; @NonNull private final ActivityTaskManager mActivityTaskManager; @NonNull private final BiometricTaskStackListener mTaskStackListener; + // for requests that do not use biometric prompt + @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); @Nullable private IFace mDaemon; @@ -110,8 +113,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { && !client.isAlreadyDone()) { Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); - mSensors.valueAt(i).getScheduler() - .cancelAuthenticationOrDetection(client.getToken()); + mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection( + client.getToken(), client.getRequestId()); } } } @@ -356,34 +359,39 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } @Override - public void scheduleFaceDetect(int sensorId, @NonNull IBinder token, + public long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, int statsClient) { + final long id = mRequestCounter.incrementAndGet(); + mHandler.post(() -> { final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FaceDetectClient client = new FaceDetectClient(mContext, - mSensors.get(sensorId).getLazySession(), token, callback, userId, opPackageName, + mSensors.get(sensorId).getLazySession(), + token, id, callback, userId, opPackageName, sensorId, isStrongBiometric, statsClient); scheduleForSensor(sensorId, client); }); + + return id; } @Override - public void cancelFaceDetect(int sensorId, @NonNull IBinder token) { + public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) { mHandler.post(() -> mSensors.get(sensorId).getScheduler() - .cancelAuthenticationOrDetection(token)); + .cancelAuthenticationOrDetection(token, requestId)); } @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, - @NonNull String opPackageName, boolean restricted, int statsClient, + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) { mHandler.post(() -> { final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FaceAuthenticationClient client = new FaceAuthenticationClient( - mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, - operationId, restricted, opPackageName, cookie, + mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback, + userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, mUsageStats, mSensors.get(sensorId).getLockoutCache(), allowBackgroundAuthentication, isKeyguardBypassEnabled); @@ -392,9 +400,23 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } @Override - public void cancelAuthentication(int sensorId, @NonNull IBinder token) { + public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, + int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) { + final long id = mRequestCounter.incrementAndGet(); + + scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback, + opPackageName, id, restricted, statsClient, + allowBackgroundAuthentication, isKeyguardBypassEnabled); + + return id; + } + + @Override + public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) { mHandler.post(() -> mSensors.get(sensorId).getScheduler() - .cancelAuthenticationOrDetection(token)); + .cancelAuthenticationOrDetection(token, requestId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index d05333db7532..f4dcbbba21d7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -87,6 +87,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; /** * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or its extended @@ -115,6 +116,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull private final Map<Integer, Long> mAuthenticatorIds; @Nullable private IBiometricsFace mDaemon; @NonNull private final HalResultController mHalResultController; + // for requests that do not use biometric prompt + @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); private int mCurrentUserId = UserHandle.USER_NULL; private final int mSensorId; private final List<Long> mGeneratedChallengeCount = new ArrayList<>(); @@ -605,7 +608,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } @Override - public void scheduleFaceDetect(int sensorId, @NonNull IBinder token, + public long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, int statsClient) { throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you" @@ -613,7 +616,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } @Override - public void cancelFaceDetect(int sensorId, @NonNull IBinder token) { + public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) { throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you" + "forget to check the supportsFaceDetection flag?"); } @@ -621,26 +624,38 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver, - @NonNull String opPackageName, boolean restricted, int statsClient, + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) { mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId); final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext, - mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName, - cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric, - statsClient, mLockoutTracker, mUsageStats, allowBackgroundAuthentication, - isKeyguardBypassEnabled); + mLazyDaemon, token, requestId, receiver, userId, operationId, restricted, + opPackageName, cookie, false /* requireConfirmation */, mSensorId, + isStrongBiometric, statsClient, mLockoutTracker, mUsageStats, + allowBackgroundAuthentication, isKeyguardBypassEnabled); mScheduler.scheduleClientMonitor(client); }); } @Override - public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> { - mScheduler.cancelAuthenticationOrDetection(token); - }); + public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, + int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver, + @NonNull String opPackageName, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) { + final long id = mRequestCounter.incrementAndGet(); + + scheduleAuthenticate(sensorId, token, operationId, userId, cookie, receiver, + opPackageName, id, restricted, statsClient, + allowBackgroundAuthentication, isKeyguardBypassEnabled); + + return id; + } + + @Override + public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) { + mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 33950af2216f..40f2801541d3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -57,7 +57,8 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { private int mLastAcquire; FaceAuthenticationClient(@NonNull Context context, - @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, + @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker, @@ -68,6 +69,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */, lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */, isKeyguardBypassEnabled); + setRequestId(requestId); mUsageStats = usageStats; final Resources resources = getContext().getResources(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java index 1e5942930b01..52d887a75216 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java @@ -61,10 +61,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub @Override public void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, - String opPackageName, int cookie, boolean allowBackgroundAuthentication) + String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication) throws RemoteException { mFingerprintService.prepareForAuthentication(mSensorId, token, operationId, userId, - sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication); + sensorReceiver, opPackageName, requestId, cookie, allowBackgroundAuthentication); } @Override @@ -73,9 +73,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub } @Override - public void cancelAuthenticationFromService(IBinder token, String opPackageName) + public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId) throws RemoteException { - mFingerprintService.cancelAuthenticationFromService(mSensorId, token, opPackageName); + mFingerprintService.cancelAuthenticationFromService( + mSensorId, token, opPackageName, requestId); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 183fabdc2a7b..f35bb7ffd26b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -35,6 +35,7 @@ import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricsProtoEnums; @@ -62,11 +63,13 @@ import android.os.Build; import android.os.CancellationSignal; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.util.EventLog; import android.util.Pair; @@ -111,6 +114,7 @@ public class FingerprintService extends SystemService { private final FingerprintServiceWrapper mServiceWrapper; @NonNull private final List<ServiceProvider> mServiceProviders; @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final Handler mHandler; @GuardedBy("mLock") @NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback> @@ -125,6 +129,37 @@ public class FingerprintService extends SystemService { */ public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { mFingerprintStateCallback.registerFingerprintStateListener(listener); + broadcastCurrentEnrollmentState(listener); + } + + /** + * @param listener if non-null, notifies only this listener. if null, notifies all listeners + * in {@link FingerprintStateCallback}. This is slightly ugly, but reduces + * redundant code. + */ + private void broadcastCurrentEnrollmentState(@Nullable IFingerprintStateListener listener) { + final UserManager um = UserManager.get(getContext()); + synchronized (mLock) { + // Update the new listener with current state of all sensors + for (FingerprintSensorPropertiesInternal prop : mSensorProps) { + final ServiceProvider provider = getProviderForSensor(prop.sensorId); + for (UserInfo userInfo : um.getAliveUsers()) { + final boolean enrolled = !provider + .getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty(); + + // Defer this work and allow the loop to release the lock sooner + mHandler.post(() -> { + if (listener != null) { + mFingerprintStateCallback.notifyFingerprintEnrollmentStateChanged( + listener, userInfo.id, prop.sensorId, enrolled); + } else { + mFingerprintStateCallback.notifyAllFingerprintEnrollmentStateChanged( + userInfo.id, prop.sensorId, enrolled); + } + }); + } + } + } } /** @@ -143,8 +178,7 @@ public class FingerprintService extends SystemService { return null; } - return provider.createTestSession(sensorId, callback, mFingerprintStateCallback, - opPackageName); + return provider.createTestSession(sensorId, callback, opPackageName); } @Override @@ -227,7 +261,7 @@ public class FingerprintService extends SystemService { } provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, - receiver, opPackageName, enrollReason, mFingerprintStateCallback); + receiver, opPackageName, enrollReason); } @Override // Binder call @@ -245,7 +279,7 @@ public class FingerprintService extends SystemService { @SuppressWarnings("deprecation") @Override // Binder call - public void authenticate(final IBinder token, final long operationId, + public long authenticate(final IBinder token, final long operationId, final int sensorId, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName) { final int callingUid = Binder.getCallingUid(); @@ -255,7 +289,7 @@ public class FingerprintService extends SystemService { if (!canUseFingerprint(opPackageName, true /* requireForeground */, callingUid, callingPid, callingUserId)) { Slog.w(TAG, "Authenticate rejecting package: " + opPackageName); - return; + return -1; } // Keyguard check must be done on the caller's binder identity, since it also checks @@ -270,7 +304,7 @@ public class FingerprintService extends SystemService { // SafetyNet for b/79776455 EventLog.writeEvent(0x534e4554, "79776455"); Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown"); - return; + return -1; } } finally { Binder.restoreCallingIdentity(identity); @@ -290,7 +324,7 @@ public class FingerprintService extends SystemService { } if (provider == null) { Slog.w(TAG, "Null provider for authenticate"); - return; + return -1; } final FingerprintSensorPropertiesInternal sensorProps = @@ -299,18 +333,17 @@ public class FingerprintService extends SystemService { && sensorProps != null && sensorProps.isAnyUdfpsType()) { identity = Binder.clearCallingIdentity(); try { - authenticateWithPrompt(operationId, sensorProps, userId, receiver); + return authenticateWithPrompt(operationId, sensorProps, userId, receiver); } finally { Binder.restoreCallingIdentity(identity); } - } else { - provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, - 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName, - restricted, statsClient, isKeyguard, mFingerprintStateCallback); } + return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, + 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName, + restricted, statsClient, isKeyguard); } - private void authenticateWithPrompt( + private long authenticateWithPrompt( final long operationId, @NonNull final FingerprintSensorPropertiesInternal props, final int userId, @@ -387,41 +420,41 @@ public class FingerprintService extends SystemService { } }; - biometricPrompt.authenticateUserForOperation( + return biometricPrompt.authenticateUserForOperation( new CancellationSignal(), executor, promptCallback, userId, operationId); } @Override - public void detectFingerprint(final IBinder token, final int userId, + public long detectFingerprint(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); if (!Utils.isKeyguard(getContext(), opPackageName)) { Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName); - return; + return -1; } if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { // If this happens, something in KeyguardUpdateMonitor is wrong. This should only // ever be invoked when the user is encrypted or lockdown. Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown"); - return; + return -1; } final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFingerprint"); - return; + return -1; } - provider.second.scheduleFingerDetect(provider.first, token, userId, + return provider.second.scheduleFingerDetect(provider.first, token, userId, new ClientMonitorCallbackConverter(receiver), opPackageName, - BiometricsProtoEnums.CLIENT_KEYGUARD, mFingerprintStateCallback); + BiometricsProtoEnums.CLIENT_KEYGUARD); } @Override // Binder call public void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, - int cookie, boolean allowBackgroundAuthentication) { + long requestId, int cookie, boolean allowBackgroundAuthentication) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -432,9 +465,9 @@ public class FingerprintService extends SystemService { final boolean restricted = true; // BiometricPrompt is always restricted provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie, - new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted, - BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication, - mFingerprintStateCallback); + new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId, + restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, + allowBackgroundAuthentication); } @Override // Binder call @@ -452,7 +485,8 @@ public class FingerprintService extends SystemService { @Override // Binder call - public void cancelAuthentication(final IBinder token, final String opPackageName) { + public void cancelAuthentication(final IBinder token, final String opPackageName, + long requestId) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final int callingUserId = UserHandle.getCallingUserId(); @@ -469,11 +503,12 @@ public class FingerprintService extends SystemService { return; } - provider.second.cancelAuthentication(provider.first, token); + provider.second.cancelAuthentication(provider.first, token, requestId); } @Override // Binder call - public void cancelFingerprintDetect(final IBinder token, final String opPackageName) { + public void cancelFingerprintDetect(final IBinder token, final String opPackageName, + final long requestId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); if (!Utils.isKeyguard(getContext(), opPackageName)) { Slog.w(TAG, "cancelFingerprintDetect called from non-sysui package: " @@ -489,12 +524,12 @@ public class FingerprintService extends SystemService { return; } - provider.second.cancelAuthentication(provider.first, token); + provider.second.cancelAuthentication(provider.first, token, requestId); } @Override // Binder call public void cancelAuthenticationFromService(final int sensorId, final IBinder token, - final String opPackageName) { + final String opPackageName, final long requestId) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); @@ -506,7 +541,7 @@ public class FingerprintService extends SystemService { return; } - provider.cancelAuthentication(sensorId, token); + provider.cancelAuthentication(sensorId, token, requestId); } @Override // Binder call @@ -686,27 +721,6 @@ public class FingerprintService extends SystemService { .isEmpty(); } - @Override // Binder call - public boolean hasEnrolledTemplatesForAnySensor(int userId, - @NonNull List<FingerprintSensorPropertiesInternal> sensors, - @NonNull String opPackageName) { - Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - - for (FingerprintSensorPropertiesInternal prop : sensors) { - final ServiceProvider provider = getProviderForSensor(prop.sensorId); - if (provider == null) { - Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId - + ", caller: " + opPackageName); - continue; - } - - if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) { - return true; - } - } - return false; - } - public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); @@ -796,10 +810,12 @@ public class FingerprintService extends SystemService { && Settings.Secure.getIntForUser(getContext().getContentResolver(), Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, UserHandle.USER_CURRENT) != 0) { - fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor, + fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), + mFingerprintStateCallback, hidlSensor, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } else { - fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor, + fingerprint21 = Fingerprint21.newInstance(getContext(), + mFingerprintStateCallback, hidlSensor, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } mServiceProviders.add(fingerprint21); @@ -822,8 +838,9 @@ public class FingerprintService extends SystemService { try { final SensorProps[] props = fp.getSensorProps(); final FingerprintProvider provider = - new FingerprintProvider(getContext(), props, instance, - mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + new FingerprintProvider(getContext(), mFingerprintStateCallback, props, + instance, mLockoutResetDispatcher, + mGestureAvailabilityDispatcher); mServiceProviders.add(provider); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); @@ -877,6 +894,7 @@ public class FingerprintService extends SystemService { } } + broadcastCurrentEnrollmentState(null); // broadcasts to all listeners broadcastAllAuthenticatorsRegistered(); }); } @@ -974,6 +992,7 @@ public class FingerprintService extends SystemService { mFingerprintStateCallback = new FingerprintStateCallback(); mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>(); mSensorProps = new ArrayList<>(); + mHandler = new Handler(Looper.getMainLooper()); } // Notifies the callbacks that all of the authenticators have been registered and removes the diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java index 5f998d81fb83..0050a895034f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java @@ -23,6 +23,7 @@ import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE; import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH; import android.annotation.NonNull; +import android.content.Context; import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintStateListener; import android.os.RemoteException; @@ -31,6 +32,9 @@ import android.util.Slog; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; +import com.android.server.biometrics.sensors.EnrollClient; +import com.android.server.biometrics.sensors.EnrollmentModifier; +import com.android.server.biometrics.sensors.RemovalConsumer; import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient; import java.util.concurrent.CopyOnWriteArrayList; @@ -39,9 +43,11 @@ import java.util.concurrent.CopyOnWriteArrayList; * A callback for receiving notifications about changes in fingerprint state. */ public class FingerprintStateCallback implements BaseClientMonitor.Callback { - private @FingerprintStateListener.State int mFingerprintState; + @NonNull private final CopyOnWriteArrayList<IFingerprintStateListener> - mFingerprintStateListeners = new CopyOnWriteArrayList<>(); + mFingerprintStateListeners = new CopyOnWriteArrayList<>(); + + private @FingerprintStateListener.State int mFingerprintState; public FingerprintStateCallback() { mFingerprintState = STATE_IDLE; @@ -54,8 +60,9 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback { @Override public void onClientStarted(@NonNull BaseClientMonitor client) { final int previousFingerprintState = mFingerprintState; + if (client instanceof AuthenticationClient) { - AuthenticationClient authClient = (AuthenticationClient) client; + final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client; if (authClient.isKeyguard()) { mFingerprintState = STATE_KEYGUARD_AUTH; } else if (authClient.isBiometricPrompt()) { @@ -70,6 +77,7 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback { "Other authentication client: " + Utils.getClientName(client)); mFingerprintState = STATE_IDLE; } + Slog.d(FingerprintService.TAG, "Fps state updated from " + previousFingerprintState + " to " + mFingerprintState + ", client " + client); notifyFingerprintStateListeners(mFingerprintState); @@ -81,6 +89,18 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback { Slog.d(FingerprintService.TAG, "Client finished, fps state updated to " + mFingerprintState + ", client " + client); + + if (client instanceof EnrollmentModifier) { + EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client; + final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged(); + Slog.d(FingerprintService.TAG, "Enrollment state changed: " + enrollmentStateChanged); + if (enrollmentStateChanged) { + notifyAllFingerprintEnrollmentStateChanged(client.getTargetUserId(), + client.getSensorId(), + enrollmentModifier.hasEnrollments()); + } + } + notifyFingerprintStateListeners(mFingerprintState); } @@ -95,6 +115,32 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback { } /** + * This should be invoked when: + * 1) Enrolled --> None-enrolled + * 2) None-enrolled --> enrolled + * 3) HAL becomes ready + * 4) Listener is registered + */ + void notifyAllFingerprintEnrollmentStateChanged(int userId, int sensorId, + boolean hasEnrollments) { + for (IFingerprintStateListener listener : mFingerprintStateListeners) { + notifyFingerprintEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments); + } + } + + /** + * Notifies the listener of enrollment state changes. + */ + void notifyFingerprintEnrollmentStateChanged(@NonNull IFingerprintStateListener listener, + int userId, int sensorId, boolean hasEnrollments) { + try { + listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments); + } catch (RemoteException e) { + Slog.e(FingerprintService.TAG, "Remote exception", e); + } + } + + /** * Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward * updates in fingerprint sensor state to the SideFpNsEventHandler * @param listener diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 706ac1013746..1772f814dd10 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -90,25 +90,27 @@ public interface ServiceProvider { */ void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, - @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason, - @NonNull FingerprintStateCallback fingerprintStateCallback); + @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason); void cancelEnrollment(int sensorId, @NonNull IBinder token); - void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, + long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, - int statsClient, - @NonNull FingerprintStateCallback fingerprintStateCallback); + int statsClient); void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication); + + long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, + int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, - boolean allowBackgroundAuthentication, - @NonNull FingerprintStateCallback fingerprintStateCallback); + boolean allowBackgroundAuthentication); void startPreparedClient(int sensorId, int cookie); - void cancelAuthentication(int sensorId, @NonNull IBinder token); + void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId); void scheduleRemove(int sensorId, @NonNull IBinder token, @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, @@ -163,6 +165,5 @@ public interface ServiceProvider { @NonNull ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull String opPackageName); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java index 29f2f20b8a75..2b50b96c69a1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java @@ -143,8 +143,7 @@ class BiometricTestSessionImpl extends ITestSession.Stub { Utils.checkPermission(mContext, TEST_BIOMETRIC); mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver, - mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL, - mFingerprintStateCallback); + mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 4400834efb3f..b405be75bdf1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -61,7 +61,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp private boolean mIsPointerDown; FingerprintAuthenticationClient(@NonNull Context context, - @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<ISession> lazyDaemon, + @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @@ -74,6 +75,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */, false /* isKeyguardBypassEnabled */); + setRequestId(requestId); mLockoutCache = lockoutCache; mUdfpsOverlayController = udfpsOverlayController; mSensorProps = sensorProps; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java index c5dc44988612..da91cdd981b9 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java @@ -47,13 +47,15 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> implements Det @Nullable private ICancellationSignal mCancellationSignal; FingerprintDetectClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, - @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull IBinder token, long requestId, + @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); + setRequestId(requestId); mIsStrongBiometric = isStrongBiometric; mUdfpsOverlayController = udfpsOverlayController; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 102b07493134..ca83dda3bc4e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -71,6 +71,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; /** * Provider for a single instance of the {@link IFingerprint} HAL. @@ -81,6 +82,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi private boolean mTestHalEnabled; @NonNull private final Context mContext; + @NonNull private final FingerprintStateCallback mFingerprintStateCallback; @NonNull private final String mHalInstanceName; @NonNull @VisibleForTesting final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports @@ -88,6 +90,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private final ActivityTaskManager mActivityTaskManager; @NonNull private final BiometricTaskStackListener mTaskStackListener; + // for requests that do not use biometric prompt + @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); @Nullable private IFingerprint mDaemon; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; @@ -118,8 +122,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi && !client.isAlreadyDone()) { Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); - mSensors.valueAt(i).getScheduler() - .cancelAuthenticationOrDetection(client.getToken()); + mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection( + client.getToken(), client.getRequestId()); } } } @@ -127,10 +131,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } } - public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props, - @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, + public FingerprintProvider(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull SensorProps[] props, @NonNull String halInstanceName, + @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { mContext = context; + mFingerprintStateCallback = fingerprintStateCallback; mHalInstanceName = halInstanceName; mSensors = new SparseArray<>(); mHandler = new Handler(Looper.getMainLooper()); @@ -332,8 +339,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi public void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, - @FingerprintManager.EnrollReason int enrollReason, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + @FingerprintManager.EnrollReason int enrollReason) { mHandler.post(() -> { final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() .maxEnrollmentsPerUser; @@ -347,13 +353,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { - fingerprintStateCallback.onClientStarted(clientMonitor); + mFingerprintStateCallback.onClientStarted(clientMonitor); } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { - fingerprintStateCallback.onClientFinished(clientMonitor, success); + mFingerprintStateCallback.onClientFinished(clientMonitor, success); if (success) { scheduleLoadAuthenticatorIdsForUser(sensorId, userId); scheduleInvalidationRequest(sensorId, userId); @@ -369,48 +375,62 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, + public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, - int statsClient, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + int statsClient) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FingerprintDetectClient client = new FingerprintDetectClient(mContext, - mSensors.get(sensorId).getLazySession(), token, callback, userId, + mSensors.get(sensorId).getLazySession(), token, id, callback, userId, opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric, statsClient); - scheduleForSensor(sensorId, client, fingerprintStateCallback); + scheduleForSensor(sensorId, client, mFingerprintStateCallback); }); + + return id; } @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, - @NonNull String opPackageName, boolean restricted, int statsClient, - boolean allowBackgroundAuthentication, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication) { mHandler.post(() -> { final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( - mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, - operationId, restricted, opPackageName, cookie, + mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback, + userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), mUdfpsOverlayController, allowBackgroundAuthentication, mSensors.get(sensorId).getSensorProperties()); - scheduleForSensor(sensorId, client, fingerprintStateCallback); + scheduleForSensor(sensorId, client, mFingerprintStateCallback); }); } @Override + public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, + int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication) { + final long id = mRequestCounter.incrementAndGet(); + + scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback, + opPackageName, id, restricted, statsClient, allowBackgroundAuthentication); + + return id; + } + + @Override public void startPreparedClient(int sensorId, int cookie) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie)); } @Override - public void cancelAuthentication(int sensorId, @NonNull IBinder token) { + public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) { mHandler.post(() -> mSensors.get(sensorId).getScheduler() - .cancelAuthenticationOrDetection(token)); + .cancelAuthenticationOrDetection(token, requestId)); } @Override @@ -444,7 +464,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId, opPackageName, FingerprintUtils.getInstance(sensorId), sensorId, mSensors.get(sensorId).getAuthenticatorIds()); - scheduleForSensor(sensorId, client); + scheduleForSensor(sensorId, client, mFingerprintStateCallback); }); } @@ -459,7 +479,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mContext.getOpPackageName(), sensorId, enrolledList, FingerprintUtils.getInstance(sensorId), mSensors.get(sensorId).getAuthenticatorIds()); - scheduleForSensor(sensorId, client, callback); + scheduleForSensor(sensorId, client, new BaseClientMonitor.CompositeCallback(callback, + mFingerprintStateCallback)); }); } @@ -604,9 +625,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull @Override public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull String opPackageName) { - return mSensors.get(sensorId).createTestSession(callback, fingerprintStateCallback); + return mSensors.get(sensorId).createTestSession(callback, mFingerprintStateCallback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java index c00daffb867f..79c6b1b30d5b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java @@ -143,8 +143,7 @@ public class BiometricTestSessionImpl extends ITestSession.Stub { Utils.checkPermission(mContext, TEST_BIOMETRIC); mFingerprint21.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver, - mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL, - mFingerprintStateCallback); + mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 2f5b5c7b9727..d2882aa4094c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -88,6 +88,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; /** * Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or @@ -101,6 +102,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider private boolean mTestHalEnabled; final Context mContext; + @NonNull private final FingerprintStateCallback mFingerprintStateCallback; private final ActivityTaskManager mActivityTaskManager; @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties; private final BiometricScheduler mScheduler; @@ -115,6 +117,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @NonNull private final HalResultController mHalResultController; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ISidefpsController mSidefpsController; + // for requests that do not use biometric prompt + @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); private int mCurrentUserId = UserHandle.USER_NULL; private final boolean mIsUdfps; private final int mSensorId; @@ -142,7 +146,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider && !client.isAlreadyDone()) { Slog.e(TAG, "Stopping background authentication, top: " + topPackage + " currentClient: " + client); - mScheduler.cancelAuthenticationOrDetection(client.getToken()); + mScheduler.cancelAuthenticationOrDetection( + client.getToken(), client.getRequestId()); } } }); @@ -313,11 +318,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } Fingerprint21(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller) { mContext = context; + mFingerprintStateCallback = fingerprintStateCallback; mSensorProperties = sensorProps; mSensorId = sensorProps.sensorId; @@ -347,6 +354,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } public static Fingerprint21 newInstance(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { @@ -358,8 +366,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider final HalResultController controller = new HalResultController(sensorProps.sensorId, context, handler, scheduler); - return new Fingerprint21(context, sensorProps, scheduler, handler, lockoutResetDispatcher, - controller); + return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler, + lockoutResetDispatcher, controller); } @Override @@ -553,8 +561,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider public void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, - @FingerprintManager.EnrollReason int enrollReason, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + @FingerprintManager.EnrollReason int enrollReason) { mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); @@ -566,13 +573,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { - fingerprintStateCallback.onClientStarted(clientMonitor); + mFingerprintStateCallback.onClientStarted(clientMonitor); } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { - fingerprintStateCallback.onClientFinished(clientMonitor, success); + mFingerprintStateCallback.onClientFinished(clientMonitor, success); if (success) { // Update authenticatorIds scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(), @@ -591,51 +598,65 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, + public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, - int statsClient, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + int statsClient) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId); final FingerprintDetectClient client = new FingerprintDetectClient(mContext, - mLazyDaemon, token, listener, userId, opPackageName, + mLazyDaemon, token, id, listener, userId, opPackageName, mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric, statsClient); - mScheduler.scheduleClientMonitor(client, fingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); + + return id; } @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, - @NonNull String opPackageName, boolean restricted, int statsClient, - boolean allowBackgroundAuthentication, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication) { mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId); final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( - mContext, mLazyDaemon, token, listener, userId, operationId, restricted, - opPackageName, cookie, false /* requireConfirmation */, + mContext, mLazyDaemon, token, requestId, listener, userId, operationId, + restricted, opPackageName, cookie, false /* requireConfirmation */, mSensorProperties.sensorId, isStrongBiometric, statsClient, mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, allowBackgroundAuthentication, mSensorProperties); - mScheduler.scheduleClientMonitor(client, fingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); } @Override + public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, + int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, + @NonNull String opPackageName, boolean restricted, int statsClient, + boolean allowBackgroundAuthentication) { + final long id = mRequestCounter.incrementAndGet(); + + scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener, + opPackageName, id, restricted, statsClient, allowBackgroundAuthentication); + + return id; + } + + @Override public void startPreparedClient(int sensorId, int cookie) { mHandler.post(() -> mScheduler.startPreparedClient(cookie)); } @Override - public void cancelAuthentication(int sensorId, @NonNull IBinder token) { + public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) { Slog.d(TAG, "cancelAuthentication, sensorId: " + sensorId); - mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token)); + mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId)); } @Override @@ -649,7 +670,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId, userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId), mSensorProperties.sensorId, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client); + mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); } @@ -666,7 +687,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider 0 /* fingerprintId */, userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId), mSensorProperties.sensorId, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client); + mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); } @@ -688,7 +709,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @Override public void scheduleInternalCleanup(int sensorId, int userId, @Nullable BaseClientMonitor.Callback callback) { - scheduleInternalCleanup(userId, callback); + scheduleInternalCleanup(userId, new BaseClientMonitor.CompositeCallback(callback, + mFingerprintStateCallback)); } @Override @@ -896,9 +918,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @NonNull @Override public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull String opPackageName) { return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback, - fingerprintStateCallback, this, mHalResultController); + mFingerprintStateCallback, this, mHalResultController); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 24ce8676235a..79ad8e1a5c70 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -26,6 +26,7 @@ import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Handler; import android.os.IBinder; @@ -42,6 +43,7 @@ import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; +import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import java.util.ArrayList; @@ -270,6 +272,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } public static Fingerprint21UdfpsMock newInstance(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { @@ -280,8 +283,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher); final MockHalResultController controller = new MockHalResultController(sensorProps.sensorId, context, handler, scheduler); - return new Fingerprint21UdfpsMock(context, sensorProps, scheduler, handler, - lockoutResetDispatcher, controller); + return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler, + handler, lockoutResetDispatcher, controller); } private static abstract class FakeFingerRunnable implements Runnable { @@ -400,17 +403,19 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage // internal preemption logic is not run. mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token, operationId, user, cookie, listener, opPackageName, restricted, statsClient, - isKeyguard, null /* fingerprintStateCallback */); + isKeyguard); } } private Fingerprint21UdfpsMock(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull TestableBiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull MockHalResultController controller) { - super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); + super(context, fingerprintStateCallback, sensorProps, scheduler, handler, + lockoutResetDispatcher, controller); mScheduler = scheduler; mScheduler.init(this); mHandler = handler; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index 5060744bb33e..7d95ec098fee 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -59,7 +59,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi private boolean mIsPointerDown; FingerprintAuthenticationClient(@NonNull Context context, - @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, + @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @@ -73,6 +74,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */, false /* isKeyguardBypassEnabled */); + setRequestId(requestId); mLockoutFrameworkImpl = lockoutTracker; mUdfpsOverlayController = udfpsOverlayController; mSensorProps = sensorProps; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java index 8e73ee6b3e9f..147a20699b54 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java @@ -52,13 +52,15 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint> private boolean mIsPointerDown; public FingerprintDetectClient(@NonNull Context context, - @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, + @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric, int statsClient) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); + setRequestId(requestId); mUdfpsOverlayController = udfpsOverlayController; mIsStrongBiometric = isStrongBiometric; } diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java index 491818520e3c..5c0c3626037a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java @@ -59,7 +59,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub { @Override public void prepareForAuthentication(boolean requireConfirmation, IBinder token, long sessionId, int userId, IBiometricSensorReceiver sensorReceiver, - String opPackageName, int cookie, boolean allowBackgroundAuthentication) + String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication) throws RemoteException { } @@ -68,7 +68,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public void cancelAuthenticationFromService(IBinder token, String opPackageName) + public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId) throws RemoteException { } diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 4c9d0f2691b3..2ae5cbbbf24b 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -590,7 +590,7 @@ public class DisplayDeviceConfig { newIndex = i - newStart; final float newBacklightVal; final float newNitsVal; - isLastValue = mRawBacklight[i] > mBacklightMaximum + isLastValue = mRawBacklight[i] >= mBacklightMaximum || i >= mRawBacklight.length - 1; // Clamp beginning and end to valid backlight values. if (newIndex == 0) { diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 604b525856dd..c8f654c5f5c7 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -17,6 +17,7 @@ package com.android.server.display; import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE; +import static android.os.PowerManager.BRIGHTNESS_INVALID; import android.annotation.NonNull; import android.annotation.Nullable; @@ -40,6 +41,7 @@ import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -60,6 +62,7 @@ import android.view.DisplayInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.display.utils.AmbientFilter; @@ -155,7 +158,7 @@ public class DisplayModeDirector { mAppRequestObserver = new AppRequestObserver(); mSettingsObserver = new SettingsObserver(context, handler); mDisplayObserver = new DisplayObserver(context, handler); - mBrightnessObserver = new BrightnessObserver(context, handler); + mBrightnessObserver = new BrightnessObserver(context, handler, injector); mUdfpsObserver = new UdfpsObserver(); final BallotBox ballotBox = (displayId, priority, vote) -> { synchronized (mLock) { @@ -1428,8 +1431,6 @@ public class DisplayModeDirector { @Override public void onDisplayChanged(int displayId) { updateDisplayModes(displayId); - // TODO: Break the coupling between DisplayObserver and BrightnessObserver. - mBrightnessObserver.onDisplayChanged(displayId); } private void updateDisplayModes(int displayId) { @@ -1466,7 +1467,7 @@ public class DisplayModeDirector { * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}. */ @VisibleForTesting - public class BrightnessObserver extends ContentObserver { + public class BrightnessObserver implements DisplayManager.DisplayListener { private final static int LIGHT_SENSOR_RATE_MS = 250; private int[] mLowDisplayBrightnessThresholds; private int[] mLowAmbientBrightnessThresholds; @@ -1489,6 +1490,8 @@ public class DisplayModeDirector { private int mBrightness = -1; private final Context mContext; + private final Injector mInjector; + private final Handler mHandler; // Enable light sensor only when mShouldObserveAmbientLowChange is true or // mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate @@ -1501,9 +1504,11 @@ public class DisplayModeDirector { private int mRefreshRateInLowZone; private int mRefreshRateInHighZone; - BrightnessObserver(Context context, Handler handler) { - super(handler); + BrightnessObserver(Context context, Handler handler, Injector injector) { mContext = context; + mHandler = handler; + mInjector = injector; + mLowDisplayBrightnessThresholds = context.getResources().getIntArray( R.array.config_brightnessThresholdsOfPeakRefreshRate); mLowAmbientBrightnessThresholds = context.getResources().getIntArray( @@ -1570,8 +1575,7 @@ public class DisplayModeDirector { public void observe(SensorManager sensorManager) { mSensorManager = sensorManager; final ContentResolver cr = mContext.getContentResolver(); - mBrightness = Settings.System.getIntForUser(cr, - Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId()); + mBrightness = getBrightness(Display.DEFAULT_DISPLAY); // DeviceConfig is accessible after system ready. int[] lowDisplayBrightnessThresholds = @@ -1604,6 +1608,10 @@ public class DisplayModeDirector { restartObserver(); mDeviceConfigDisplaySettings.startListening(); + + mInjector.registerDisplayListener(this, mHandler, + DisplayManager.EVENT_FLAG_DISPLAY_CHANGED | + DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS); } public void setLoggingEnabled(boolean loggingEnabled) { @@ -1719,28 +1727,30 @@ public class DisplayModeDirector { } } + @Override + public void onDisplayAdded(int displayId) {} + + @Override + public void onDisplayRemoved(int displayId) {} + + @Override public void onDisplayChanged(int displayId) { if (displayId == Display.DEFAULT_DISPLAY) { updateDefaultDisplayState(); - } - } - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - synchronized (mLock) { - final ContentResolver cr = mContext.getContentResolver(); - int brightness = Settings.System.getIntForUser(cr, - Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId()); - if (brightness != mBrightness) { - mBrightness = brightness; - onBrightnessChangedLocked(); + // We don't support multiple display blocking zones yet, so only handle + // brightness changes for the default display for now. + int brightness = getBrightness(displayId); + synchronized (mLock) { + if (brightness != mBrightness) { + mBrightness = brightness; + onBrightnessChangedLocked(); + } } } } private void restartObserver() { - final ContentResolver cr = mContext.getContentResolver(); - if (mRefreshRateInLowZone > 0) { mShouldObserveDisplayLowChange = hasValidThreshold( mLowDisplayBrightnessThresholds); @@ -1761,15 +1771,6 @@ public class DisplayModeDirector { mShouldObserveAmbientHighChange = false; } - if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) { - // Content Service does not check if an listener has already been registered. - // To ensure only one listener is registered, force an unregistration first. - mInjector.unregisterBrightnessObserver(cr, this); - mInjector.registerBrightnessObserver(cr, this); - } else { - mInjector.unregisterBrightnessObserver(cr, this); - } - if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) { Resources resources = mContext.getResources(); String lightSensorType = resources.getString( @@ -1969,6 +1970,15 @@ public class DisplayModeDirector { return mDefaultDisplayState == Display.STATE_ON; } + private int getBrightness(int displayId) { + final BrightnessInfo info = mInjector.getBrightnessInfo(displayId); + if (info != null) { + return BrightnessSynchronizer.brightnessFloatToInt(info.adjustedBrightness); + } + + return BRIGHTNESS_INVALID; + } + private final class LightSensorEventListener implements SensorEventListener { final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS; private float mLastSensorData; @@ -2282,6 +2292,7 @@ public class DisplayModeDirector { private final BallotBox mBallotBox; private final Handler mHandler; private final SparseIntArray mHbmMode = new SparseIntArray(); + private final SparseBooleanArray mHbmActive = new SparseBooleanArray(); private final Injector mInjector; private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; private int mRefreshRateInHbmSunlight; @@ -2350,6 +2361,7 @@ public class DisplayModeDirector { public void onDisplayRemoved(int displayId) { mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null); mHbmMode.delete(displayId); + mHbmActive.delete(displayId); } @Override @@ -2359,12 +2371,17 @@ public class DisplayModeDirector { // Display no longer there. Assume we'll get an onDisplayRemoved very soon. return; } + final int hbmMode = info.highBrightnessMode; - if (hbmMode == mHbmMode.get(displayId)) { + final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF && + info.adjustedBrightness > info.highBrightnessTransitionPoint; + if (hbmMode == mHbmMode.get(displayId) && + isHbmActive == mHbmActive.get(displayId)) { // no change, ignore. return; } mHbmMode.put(displayId, hbmMode); + mHbmActive.put(displayId, isHbmActive); recalculateVotesForDisplay(displayId); } @@ -2378,28 +2395,36 @@ public class DisplayModeDirector { } private void recalculateVotesForDisplay(int displayId) { - final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF); Vote vote = null; - if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) { - // Device resource properties take priority over DisplayDeviceConfig - if (mRefreshRateInHbmSunlight > 0) { - vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight, - mRefreshRateInHbmSunlight); - } else { - final List<RefreshRateLimitation> limits = - mDisplayManagerInternal.getRefreshRateLimitations(displayId); - for (int i = 0; limits != null && i < limits.size(); i++) { - final RefreshRateLimitation limitation = limits.get(i); - if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) { - vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max); - break; + if (mHbmActive.get(displayId, false)) { + final int hbmMode = + mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF); + if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) { + // Device resource properties take priority over DisplayDeviceConfig + if (mRefreshRateInHbmSunlight > 0) { + vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight, + mRefreshRateInHbmSunlight); + } else { + final List<RefreshRateLimitation> limits = + mDisplayManagerInternal.getRefreshRateLimitations(displayId); + for (int i = 0; limits != null && i < limits.size(); i++) { + final RefreshRateLimitation limitation = limits.get(i); + if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) { + vote = Vote.forRefreshRates(limitation.range.min, + limitation.range.max); + break; + } } } + } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && + mRefreshRateInHbmHdr > 0) { + // HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for + // a vote from Device properties + vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr); + } else { + Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId); } - } - if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR - && mRefreshRateInHbmHdr > 0) { - vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr); + } mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote); } @@ -2407,6 +2432,7 @@ public class DisplayModeDirector { void dumpLocked(PrintWriter pw) { pw.println(" HbmObserver"); pw.println(" mHbmMode: " + mHbmMode); + pw.println(" mHbmActive: " + mHbmActive); pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight); pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr); } @@ -2629,19 +2655,11 @@ public class DisplayModeDirector { } interface Injector { - // TODO: brightnessfloat: change this to the float setting - Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); @NonNull DeviceConfigInterface getDeviceConfig(); - void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer); - - void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer); - void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer); @@ -2671,19 +2689,6 @@ public class DisplayModeDirector { } @Override - public void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); - } - - @Override - public void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - cr.unregisterContentObserver(observer); - } - - @Override public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index cca6655707ae..81cbbff44778 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -125,6 +125,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private static final int MSG_IGNORE_PROXIMITY = 8; private static final int MSG_STOP = 9; private static final int MSG_UPDATE_BRIGHTNESS = 10; + private static final int MSG_UPDATE_RBC = 11; private static final int PROXIMITY_UNKNOWN = -1; private static final int PROXIMITY_NEGATIVE = 0; @@ -422,13 +423,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set. private float mTemporaryAutoBrightnessAdjustment; - // Whether a reduce bright colors (rbc) change has been initiated by the user. We want to - // retain the current backlight level when rbc is toggled, since rbc additionally makes the - // screen appear dimmer using screen colors rather than backlight levels, and therefore we - // don't actually want to compensate for this by then in/decreasing the backlight when - // toggling this feature. + // Whether reduce bright colors (rbc) has been turned on, or a change in strength has been + // requested. We want to retain the current backlight level when rbc is toggled, since rbc + // additionally makes the screen appear dimmer using screen colors rather than backlight levels, + // and therefore we don't actually want to compensate for this by then in/decreasing the + // backlight when toggling this feature. // This should be false during system start up. - private boolean mPendingUserRbcChange; + private boolean mPendingRbcOnOrChanged = false; // Animators. private ObjectAnimator mColorFadeOnAnimator; @@ -564,23 +565,35 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void onReduceBrightColorsActivationChanged(boolean activated, boolean userInitiated) { - applyReduceBrightColorsSplineAdjustment(userInitiated); + applyReduceBrightColorsSplineAdjustment( + /* rbcStrengthChanged= */ false, activated); + } @Override public void onReduceBrightColorsStrengthChanged(int strength) { - applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false); + applyReduceBrightColorsSplineAdjustment( + /* rbcStrengthChanged= */ true, /* justActivated= */ false); } }); if (active) { - applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false); + applyReduceBrightColorsSplineAdjustment( + /* rbcStrengthChanged= */ false, /* justActivated= */ false); } } else { mCdsi = null; } } - private void applyReduceBrightColorsSplineAdjustment(boolean userInitiated) { + private void applyReduceBrightColorsSplineAdjustment( + boolean rbcStrengthChanged, boolean justActivated) { + final int strengthChanged = rbcStrengthChanged ? 1 : 0; + final int activated = justActivated ? 1 : 0; + mHandler.obtainMessage(MSG_UPDATE_RBC, strengthChanged, activated).sendToTarget(); + sendUpdatePowerState(); + } + + private void handleRbcChanged(boolean strengthChanged, boolean justActivated) { if (mBrightnessMapper == null) { Log.w(TAG, "No brightness mapping available to recalculate splines"); return; @@ -591,8 +604,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]); } mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits); - mPendingUserRbcChange = userInitiated; - sendUpdatePowerState(); + + mPendingRbcOnOrChanged = strengthChanged || justActivated; + + // Reset model if strength changed OR rbc is turned off + if (strengthChanged || !justActivated && mAutomaticBrightnessController != null) { + mAutomaticBrightnessController.resetShortTermModel(); + } } /** @@ -926,7 +944,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void reloadReduceBrightColours() { if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) { - applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false); + applyReduceBrightColorsSplineAdjustment( + /* rbcStrengthChanged= */ false, /* justActivated= */ false); } } @@ -1259,10 +1278,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true); } - // We save the brightness info *after* the brightness setting has been changed so that - // the brightness info reflects the latest value. - saveBrightnessInfo(getScreenBrightnessSetting()); - // Apply dimming by at least some minimum amount when user activity // timeout is about to expire. if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { @@ -1394,6 +1409,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call hadUserBrightnessPoint); } + // We save the brightness info *after* the brightness setting has been changed and + // adjustments made so that the brightness info reflects the latest value. + saveBrightnessInfo(getScreenBrightnessSetting(), animateValue); + } else { + saveBrightnessInfo(getScreenBrightnessSetting()); } // Log any changes to what is currently driving the brightness setting. @@ -1510,18 +1530,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call synchronized (mCachedBrightnessInfo) { return new BrightnessInfo( mCachedBrightnessInfo.brightness, + mCachedBrightnessInfo.adjustedBrightness, mCachedBrightnessInfo.brightnessMin, mCachedBrightnessInfo.brightnessMax, - mCachedBrightnessInfo.hbmMode); + mCachedBrightnessInfo.hbmMode, + mCachedBrightnessInfo.highBrightnessTransitionPoint); } } private void saveBrightnessInfo(float brightness) { + saveBrightnessInfo(brightness, brightness); + } + + private void saveBrightnessInfo(float brightness, float adjustedBrightness) { synchronized (mCachedBrightnessInfo) { mCachedBrightnessInfo.brightness = brightness; + mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness; mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin(); mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax(); mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode(); + mCachedBrightnessInfo.highBrightnessTransitionPoint = + mHbmController.getTransitionPoint(); } } @@ -2061,22 +2090,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return true; } + // We want to return true if the user has set the screen brightness. + // If they have just turned RBC on (and therefore added that interaction to the curve), + // or changed the brightness another way, then we should return true. private boolean updateUserSetScreenBrightness() { - final boolean brightnessSplineChanged = mPendingUserRbcChange; - if (mPendingUserRbcChange && !Float.isNaN(mCurrentScreenBrightnessSetting)) { + final boolean treatAsIfUserChanged = mPendingRbcOnOrChanged; + if (treatAsIfUserChanged && !Float.isNaN(mCurrentScreenBrightnessSetting)) { mLastUserSetScreenBrightness = mCurrentScreenBrightnessSetting; } - mPendingUserRbcChange = false; + mPendingRbcOnOrChanged = false; if ((Float.isNaN(mPendingScreenBrightnessSetting) || mPendingScreenBrightnessSetting < 0.0f)) { - return brightnessSplineChanged; + return treatAsIfUserChanged; } if (BrightnessSynchronizer.floatEquals( mCurrentScreenBrightnessSetting, mPendingScreenBrightnessSetting)) { mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT; mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; - return brightnessSplineChanged; + return treatAsIfUserChanged; } setCurrentScreenBrightness(mPendingScreenBrightnessSetting); mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting; @@ -2195,6 +2227,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp); pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig); pw.println(" mColorFadeEnabled=" + mColorFadeEnabled); + synchronized (mCachedBrightnessInfo) { + pw.println(" mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness); + pw.println(" mCachedBrightnessInfo.adjustedBrightness=" + + mCachedBrightnessInfo.adjustedBrightness); + pw.println(" mCachedBrightnessInfo.brightnessMin=" + + mCachedBrightnessInfo.brightnessMin); + pw.println(" mCachedBrightnessInfo.brightnessMax=" + + mCachedBrightnessInfo.brightnessMax); + pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode); + pw.println(" mCachedBrightnessInfo.highBrightnessTransitionPoint=" + + mCachedBrightnessInfo.highBrightnessTransitionPoint); + } pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig); pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig); @@ -2406,6 +2450,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } handleSettingsChange(false /*userSwitch*/); break; + + case MSG_UPDATE_RBC: + final int strengthChanged = msg.arg1; + final int justActivated = msg.arg2; + handleRbcChanged(strengthChanged == 1, justActivated == 1); + break; } } } @@ -2606,8 +2656,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call static class CachedBrightnessInfo { public float brightness; + public float adjustedBrightness; public float brightnessMin; public float brightnessMax; public int hbmMode; + public float highBrightnessTransitionPoint; } } diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java index 2791f6a409be..1e1cfeb5b9dd 100644 --- a/services/core/java/com/android/server/display/HighBrightnessModeController.java +++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java @@ -59,6 +59,9 @@ class HighBrightnessModeController { private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f; + @VisibleForTesting + static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY; + private final float mBrightnessMin; private final float mBrightnessMax; private final Handler mHandler; @@ -214,6 +217,14 @@ class HighBrightnessModeController { return mHbmMode; } + float getTransitionPoint() { + if (deviceSupportsHbm()) { + return mHbmData.transitionPoint; + } else { + return HBM_TRANSITION_POINT_INVALID; + } + } + void stop() { registerHdrListener(null /*displayToken*/); mSkinThermalStatusObserver.stopObserving(); diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java index fa33338a61e7..03e421bfed67 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java @@ -209,6 +209,12 @@ public class ContextHubClientBroker extends IContextHubClient.Stub */ private AtomicBoolean mIsPendingIntentCancelled = new AtomicBoolean(false); + /** + * True if a permissions query has been issued and is being processed. Used to prevent too many + * queries from being issued by a single client at once. + */ + private AtomicBoolean mIsPermQueryIssued = new AtomicBoolean(false); + /* * True if the application creating the client has the ACCESS_CONTEXT_HUB permission. */ @@ -240,11 +246,11 @@ public class ContextHubClientBroker extends IContextHubClient.Stub private final IContextHubTransactionCallback mQueryPermsCallback = new IContextHubTransactionCallback.Stub() { @Override - public void onTransactionComplete(int result) { - } + public void onTransactionComplete(int result) {} @Override public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) { + mIsPermQueryIssued.set(false); if (result != ContextHubTransaction.RESULT_SUCCESS && nanoAppStateList != null) { Log.e(TAG, "Permissions query failed, but still received nanoapp state"); } else if (nanoAppStateList != null) { @@ -656,9 +662,11 @@ public class ContextHubClientBroker extends IContextHubClient.Stub * communicated with in the past. */ private void checkNanoappPermsAsync() { - ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction( - mAttachedContextHubInfo.getId(), mQueryPermsCallback, mPackage); - mTransactionManager.addTransaction(transaction); + if (!mIsPermQueryIssued.getAndSet(true)) { + ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction( + mAttachedContextHubInfo.getId(), mQueryPermsCallback, mPackage); + mTransactionManager.addTransaction(transaction); + } } private int updateNanoAppAuthState( diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index f3dcfbbf2c0a..9956da274263 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -16,6 +16,7 @@ package com.android.server.location.gnss; +import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.location.provider.ProviderProperties.ACCURACY_FINE; import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH; @@ -43,6 +44,8 @@ import static com.android.server.location.gnss.hal.GnssNative.GNSS_POSITION_MODE import static com.android.server.location.gnss.hal.GnssNative.GNSS_POSITION_MODE_STANDALONE; import static com.android.server.location.gnss.hal.GnssNative.GNSS_POSITION_RECURRENCE_PERIODIC; +import static java.lang.Math.abs; +import static java.lang.Math.max; import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.app.AlarmManager; @@ -85,6 +88,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import android.text.format.DateUtils; import android.util.Log; import android.util.TimeUtils; @@ -103,7 +107,9 @@ import com.android.server.location.provider.AbstractLocationProvider; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -156,6 +162,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000; // Update duration extension multiplier for emergency REQUEST_LOCATION. private static final int EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER = 3; + // maximum length gnss batching may go for (1 day) + private static final int MIN_BATCH_INTERVAL_MS = (int) DateUtils.SECOND_IN_MILLIS; + private static final long MAX_BATCH_LENGTH_MS = DateUtils.DAY_IN_MILLIS; + private static final long MAX_BATCH_TIMESTAMP_DELTA_MS = 500; // Threadsafe class to hold stats reported in the Extras Bundle private static class LocationExtras { @@ -245,6 +255,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private boolean mShutdown; private boolean mStarted; private boolean mBatchingStarted; + private AlarmManager.OnAlarmListener mBatchingAlarm; private long mStartedChangedElapsedRealtime; private int mFixInterval = 1000; @@ -845,18 +856,15 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mFixInterval = Integer.MAX_VALUE; } - // requested batch size, or zero to disable batching - long batchSize = - mBatchingEnabled ? mProviderRequest.getMaxUpdateDelayMillis() / Math.max( - mFixInterval, 1) : 0; - if (batchSize < getBatchSize()) { - batchSize = 0; - } + int batchIntervalMs = max(mFixInterval, MIN_BATCH_INTERVAL_MS); + long batchLengthMs = Math.min(mProviderRequest.getMaxUpdateDelayMillis(), + MAX_BATCH_LENGTH_MS); // apply request to GPS engine - if (batchSize > 0) { + if (mBatchingEnabled && batchLengthMs / 2 >= batchIntervalMs) { stopNavigating(); - startBatching(); + mFixInterval = batchIntervalMs; + startBatching(batchLengthMs); } else { stopBatching(); @@ -875,7 +883,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements if (mFixInterval >= NO_FIX_TIMEOUT) { // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT // and our fix interval is not short - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG, mTimeoutListener, mHandler); } @@ -1066,7 +1074,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT // and our fix interval is not short if (mFixInterval >= NO_FIX_TIMEOUT) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG, mTimeoutListener, mHandler); } @@ -1090,12 +1098,37 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mAlarmManager.cancel(mWakeupListener); } - private void startBatching() { + private void startBatching(long batchLengthMs) { + long batchSize = batchLengthMs / mFixInterval; + if (DEBUG) { - Log.d(TAG, "startBatching " + mFixInterval); + Log.d(TAG, "startBatching " + mFixInterval + " " + batchLengthMs); } if (mGnssNative.startBatch(MILLISECONDS.toNanos(mFixInterval), true)) { mBatchingStarted = true; + + if (batchSize < getBatchSize()) { + // if the batch size is smaller than the hardware batch size, use an alarm to flush + // locations as appropriate + mBatchingAlarm = () -> { + boolean flush = false; + synchronized (mLock) { + if (mBatchingAlarm != null) { + flush = true; + mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + batchLengthMs, TAG, + mBatchingAlarm, FgThread.getHandler()); + } + } + + if (flush) { + mGnssNative.flushBatch(); + } + }; + mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + batchLengthMs, TAG, + mBatchingAlarm, FgThread.getHandler()); + } } else { Log.e(TAG, "native_start_batch failed in startBatching()"); } @@ -1104,6 +1137,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private void stopBatching() { if (DEBUG) Log.d(TAG, "stopBatching"); if (mBatchingStarted) { + if (mBatchingAlarm != null) { + mAlarmManager.cancel(mBatchingAlarm); + mBatchingAlarm = null; + } mGnssNative.stopBatch(); mBatchingStarted = false; } @@ -1120,7 +1157,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // stop GPS until our next fix interval arrives stopNavigating(); long now = SystemClock.elapsedRealtime(); - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, TAG, + mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, now + mFixInterval, TAG, mWakeupListener, mHandler); } @@ -1485,16 +1522,50 @@ public class GnssLocationProvider extends AbstractLocationProvider implements Log.d(TAG, "Location batch of size " + locations.length + " reported"); } + if (locations.length > 0) { + // attempt to fix up timestamps if necessary + if (locations.length > 1) { + // check any realtimes outside of expected bounds + boolean fixRealtime = false; + for (int i = locations.length - 2; i >= 0; i--) { + long timeDeltaMs = locations[i + 1].getTime() - locations[i].getTime(); + long realtimeDeltaMs = locations[i + 1].getElapsedRealtimeMillis() + - locations[i].getElapsedRealtimeMillis(); + if (abs(timeDeltaMs - realtimeDeltaMs) > MAX_BATCH_TIMESTAMP_DELTA_MS) { + fixRealtime = true; + break; + } + } + + if (fixRealtime) { + // sort for monotonically increasing time before fixing realtime - realtime will + // thus also be monotonically increasing + Arrays.sort(locations, + Comparator.comparingLong(Location::getTime)); + + long expectedDeltaMs = + locations[locations.length - 1].getTime() + - locations[locations.length - 1].getElapsedRealtimeMillis(); + for (int i = locations.length - 2; i >= 0; i--) { + locations[i].setElapsedRealtimeNanos( + MILLISECONDS.toNanos( + max(locations[i].getTime() - expectedDeltaMs, 0))); + } + } else { + // sort for monotonically increasing realttime + Arrays.sort(locations, + Comparator.comparingLong(Location::getElapsedRealtimeNanos)); + } + } + + reportLocation(LocationResult.wrap(locations).validate()); + } + Runnable[] listeners; synchronized (mLock) { listeners = mFlushListeners.toArray(new Runnable[0]); mFlushListeners.clear(); } - - if (locations.length > 0) { - reportLocation(LocationResult.wrap(locations).validate()); - } - for (Runnable listener : listeners) { listener.run(); } diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java index 222750629802..4d9253eff69e 100644 --- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java @@ -444,12 +444,11 @@ class GnssNetworkConnectivityHandler { capabilities = networkAttributes.mCapabilities; Log.i(TAG, String.format( "updateNetworkState, state=%s, connected=%s, network=%s, capabilities=%s" - + ", apn: %s, availableNetworkCount: %d", + + ", availableNetworkCount: %d", agpsDataConnStateAsString(), isConnected, network, capabilities, - apn, mAvailableNetworkAttributes.size())); if (native_is_agps_ril_supported()) { diff --git a/services/core/java/com/android/server/location/injector/LocationPermissionsHelper.java b/services/core/java/com/android/server/location/injector/LocationPermissionsHelper.java index a47c48fa16d4..2df21017156d 100644 --- a/services/core/java/com/android/server/location/injector/LocationPermissionsHelper.java +++ b/services/core/java/com/android/server/location/injector/LocationPermissionsHelper.java @@ -100,7 +100,7 @@ public abstract class LocationPermissionsHelper { return false; } - return mAppOps.checkOpNoThrow(permissionLevel, identity); + return mAppOps.checkOpNoThrow(LocationPermissions.asAppOp(permissionLevel), identity); } protected abstract boolean hasPermission(String permission, CallerIdentity callerIdentity); diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 8955c288391f..345dc217110b 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -243,15 +243,24 @@ public class LocationProviderManager extends intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0])); } + // send() SHOULD only run the completion callback if it completes successfully. however, + // b/199464864 (which could not be fixed in the S timeframe) means that it's possible + // for send() to throw an exception AND run the completion callback. if this happens, we + // would over-release the wakelock... we take matters into our own hands to ensure that + // the completion callback can only be run if send() completes successfully. this means + // the completion callback may be run inline - but as we've never specified what thread + // the callback is run on, this is fine. + GatedCallback gatedCallback = new GatedCallback(onCompleteCallback); + mPendingIntent.send( mContext, 0, intent, - onCompleteCallback != null ? (pI, i, rC, rD, rE) -> onCompleteCallback.run() - : null, + (pI, i, rC, rD, rE) -> gatedCallback.run(), null, null, options.toBundle()); + gatedCallback.allow(); } @Override @@ -1078,7 +1087,7 @@ public class LocationProviderManager extends } private void onTransportFailure(Exception e) { - if (e instanceof RemoteException) { + if (e instanceof PendingIntent.CanceledException) { Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e); synchronized (mLock) { remove(); @@ -1960,11 +1969,6 @@ public class LocationProviderManager extends Preconditions.checkState(Thread.holdsLock(mLock)); } - if (mDelayedRegister != null) { - mAlarmHelper.cancel(mDelayedRegister); - mDelayedRegister = null; - } - // calculate how long the new request should be delayed before sending it off to the // provider, under the assumption that once we send the request off, the provider will // immediately attempt to deliver a new location satisfying that request. @@ -1997,8 +2001,8 @@ public class LocationProviderManager extends public void onAlarm() { synchronized (mLock) { if (mDelayedRegister == this) { - setProviderRequest(newRequest); mDelayedRegister = null; + setProviderRequest(newRequest); } } } @@ -2025,6 +2029,11 @@ public class LocationProviderManager extends @GuardedBy("mLock") void setProviderRequest(ProviderRequest request) { + if (mDelayedRegister != null) { + mAlarmHelper.cancel(mDelayedRegister); + mDelayedRegister = null; + } + EVENT_LOG.logProviderUpdateRequest(mName, request); mProvider.getController().setRequest(request); @@ -2734,4 +2743,49 @@ public class LocationProviderManager extends } } } + + private static class GatedCallback implements Runnable { + + private @Nullable Runnable mCallback; + + @GuardedBy("this") + private boolean mGate; + @GuardedBy("this") + private boolean mRun; + + GatedCallback(Runnable callback) { + mCallback = callback; + } + + public void allow() { + Runnable callback = null; + synchronized (this) { + mGate = true; + if (mRun && mCallback != null) { + callback = mCallback; + mCallback = null; + } + } + + if (callback != null) { + callback.run(); + } + } + + @Override + public void run() { + Runnable callback = null; + synchronized (this) { + mRun = true; + if (mGate && mCallback != null) { + callback = mCallback; + mCallback = null; + } + } + + if (callback != null) { + callback.run(); + } + } + } } diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 9f02c3caa388..a57d7db0ec54 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -903,26 +903,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub if (intent.getAction().equals(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) { BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); synchronized (mLock) { - boolean wasA2dpOn = mGlobalBluetoothA2dpOn; mActiveBluetoothDevice = btDevice; mGlobalBluetoothA2dpOn = btDevice != null; - if (wasA2dpOn != mGlobalBluetoothA2dpOn) { - Slog.d(TAG, "GlobalBluetoothA2dpOn is changed to '" - + mGlobalBluetoothA2dpOn + "'"); - UserRecord userRecord = mUserRecords.get(mCurrentUserId); - if (userRecord != null) { - for (ClientRecord cr : userRecord.mClientRecords) { - // mSelectedRouteId will be null for BT and phone speaker. - if (cr.mSelectedRouteId == null) { - try { - cr.mClient.onGlobalA2dpChanged(mGlobalBluetoothA2dpOn); - } catch (RemoteException e) { - // Ignore exception - } - } - } - } - } } } } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 557fa8944445..df372b1459af 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -290,7 +290,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W combined.getValues(augmentStart, augmentEnd, entry); } - final long rawBytes = entry.rxBytes + entry.txBytes; + final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 : + (entry.rxBytes + entry.txBytes); final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes; final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index bccc52fe350a..ddaaa1eeff4a 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -1536,7 +1536,7 @@ abstract public class ManagedServices { @Override public void onNullBinding(ComponentName name) { Slog.v(TAG, "onNullBinding() called with: name = [" + name + "]"); - mServicesBound.remove(servicesBindingTag); + mContext.unbindService(this); } }; if (!mContext.bindServiceAsUser(intent, diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index b54e8f973bd6..7ba0f04a435f 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -4363,8 +4363,7 @@ public class NotificationManagerService extends SystemService { final int userId = r.getSbn().getUserId(); if (userId != info.userid && userId != UserHandle.USER_ALL && !mUserProfiles.isCurrentProfile(userId)) { - throw new SecurityException("Disallowed call from listener: " - + info.service); + continue; } cancelNotificationFromListenerLocked(info, callingUid, callingPid, r.getSbn().getPackageName(), r.getSbn().getTag(), @@ -4431,8 +4430,7 @@ public class NotificationManagerService extends SystemService { final int userId = r.getSbn().getUserId(); if (userId != info.userid && userId != UserHandle.USER_ALL && !mUserProfiles.isCurrentProfile(userId)) { - throw new SecurityException("Disallowed call from listener: " - + info.service); + continue; } seen.add(r); if (!r.isSeen()) { @@ -5399,6 +5397,7 @@ public class NotificationManagerService extends SystemService { == IMPORTANCE_NONE) { cancelNotificationsFromListener(token, new String[]{r.getKey()}); } else { + r.setPendingLogUpdate(true); needsSort = true; } } @@ -7451,15 +7450,21 @@ public class NotificationManagerService extends SystemService { sentAccessibilityEvent = true; } if (DBG) Slog.v(TAG, "Interrupting!"); + boolean isInsistentUpdate = isInsistentUpdate(record); if (hasValidSound) { - if (isInCall()) { - playInCallNotification(); + if (isInsistentUpdate) { + // don't reset insistent sound, it's jarring beep = true; } else { - beep = playSound(record, soundUri); - } - if(beep) { - mSoundNotificationKey = key; + if (isInCall()) { + playInCallNotification(); + beep = true; + } else { + beep = playSound(record, soundUri); + } + if (beep) { + mSoundNotificationKey = key; + } } } @@ -7467,9 +7472,13 @@ public class NotificationManagerService extends SystemService { mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT; if (!isInCall() && hasValidVibrate && !ringerModeSilent) { - buzz = playVibration(record, vibration, hasValidSound); - if(buzz) { - mVibrateNotificationKey = key; + if (isInsistentUpdate) { + buzz = true; + } else { + buzz = playVibration(record, vibration, hasValidSound); + if (buzz) { + mVibrateNotificationKey = key; + } } } } else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) { @@ -7573,6 +7582,19 @@ public class NotificationManagerService extends SystemService { } @GuardedBy("mNotificationLock") + boolean isInsistentUpdate(final NotificationRecord record) { + return (Objects.equals(record.getKey(), mSoundNotificationKey) + || Objects.equals(record.getKey(), mVibrateNotificationKey)) + && isCurrentlyInsistent(); + } + + @GuardedBy("mNotificationLock") + boolean isCurrentlyInsistent() { + return isLoopingRingtoneNotification(mNotificationsByKey.get(mSoundNotificationKey)) + || isLoopingRingtoneNotification(mNotificationsByKey.get(mVibrateNotificationKey)); + } + + @GuardedBy("mNotificationLock") boolean shouldMuteNotificationLocked(final NotificationRecord record) { // Suppressed because it's a silent update final Notification notification = record.getNotification(); @@ -7611,10 +7633,8 @@ public class NotificationManagerService extends SystemService { return true; } - // A looping ringtone, such as an incoming call is playing - if (isLoopingRingtoneNotification(mNotificationsByKey.get(mSoundNotificationKey)) - || isLoopingRingtoneNotification( - mNotificationsByKey.get(mVibrateNotificationKey))) { + // A different looping ringtone, such as an incoming call is playing + if (isCurrentlyInsistent() && !isInsistentUpdate(record)) { return true; } @@ -8038,64 +8058,151 @@ public class NotificationManagerService extends SystemService { } } + static class NotificationRecordExtractorData { + // Class that stores any field in a NotificationRecord that can change via an extractor. + // Used to cache previous data used in a sort. + int mPosition; + int mVisibility; + boolean mShowBadge; + boolean mAllowBubble; + boolean mIsBubble; + NotificationChannel mChannel; + String mGroupKey; + ArrayList<String> mOverridePeople; + ArrayList<SnoozeCriterion> mSnoozeCriteria; + Integer mUserSentiment; + Integer mSuppressVisually; + ArrayList<Notification.Action> mSystemSmartActions; + ArrayList<CharSequence> mSmartReplies; + int mImportance; + + // These fields may not trigger a reranking but diffs here may be logged. + float mRankingScore; + boolean mIsConversation; + + NotificationRecordExtractorData(int position, int visibility, boolean showBadge, + boolean allowBubble, boolean isBubble, NotificationChannel channel, String groupKey, + ArrayList<String> overridePeople, ArrayList<SnoozeCriterion> snoozeCriteria, + Integer userSentiment, Integer suppressVisually, + ArrayList<Notification.Action> systemSmartActions, + ArrayList<CharSequence> smartReplies, int importance, float rankingScore, + boolean isConversation) { + mPosition = position; + mVisibility = visibility; + mShowBadge = showBadge; + mAllowBubble = allowBubble; + mIsBubble = isBubble; + mChannel = channel; + mGroupKey = groupKey; + mOverridePeople = overridePeople; + mSnoozeCriteria = snoozeCriteria; + mUserSentiment = userSentiment; + mSuppressVisually = suppressVisually; + mSystemSmartActions = systemSmartActions; + mSmartReplies = smartReplies; + mImportance = importance; + mRankingScore = rankingScore; + mIsConversation = isConversation; + } + + // Returns whether the provided NotificationRecord differs from the cached data in any way. + // Should be guarded by mNotificationLock; not annotated here as this class is static. + boolean hasDiffForRankingLocked(NotificationRecord r, int newPosition) { + return mPosition != newPosition + || mVisibility != r.getPackageVisibilityOverride() + || mShowBadge != r.canShowBadge() + || mAllowBubble != r.canBubble() + || mIsBubble != r.getNotification().isBubbleNotification() + || !Objects.equals(mChannel, r.getChannel()) + || !Objects.equals(mGroupKey, r.getGroupKey()) + || !Objects.equals(mOverridePeople, r.getPeopleOverride()) + || !Objects.equals(mSnoozeCriteria, r.getSnoozeCriteria()) + || !Objects.equals(mUserSentiment, r.getUserSentiment()) + || !Objects.equals(mSuppressVisually, r.getSuppressedVisualEffects()) + || !Objects.equals(mSystemSmartActions, r.getSystemGeneratedSmartActions()) + || !Objects.equals(mSmartReplies, r.getSmartReplies()) + || mImportance != r.getImportance(); + } + + // Returns whether the NotificationRecord has a change from this data for which we should + // log an update. This method specifically targets fields that may be changed via + // adjustments from the assistant. + // + // Fields here are the union of things in NotificationRecordLogger.shouldLogReported + // and NotificationRecord.applyAdjustments. + // + // Should be guarded by mNotificationLock; not annotated here as this class is static. + boolean hasDiffForLoggingLocked(NotificationRecord r, int newPosition) { + return mPosition != newPosition + || !Objects.equals(mChannel, r.getChannel()) + || !Objects.equals(mGroupKey, r.getGroupKey()) + || !Objects.equals(mOverridePeople, r.getPeopleOverride()) + || !Objects.equals(mSnoozeCriteria, r.getSnoozeCriteria()) + || !Objects.equals(mUserSentiment, r.getUserSentiment()) + || !Objects.equals(mSystemSmartActions, r.getSystemGeneratedSmartActions()) + || !Objects.equals(mSmartReplies, r.getSmartReplies()) + || mImportance != r.getImportance() + || !r.rankingScoreMatches(mRankingScore) + || mIsConversation != r.isConversation(); + } + } + void handleRankingSort() { if (mRankingHelper == null) return; synchronized (mNotificationLock) { final int N = mNotificationList.size(); // Any field that can change via one of the extractors needs to be added here. - ArrayList<String> orderBefore = new ArrayList<>(N); - int[] visibilities = new int[N]; - boolean[] showBadges = new boolean[N]; - boolean[] allowBubbles = new boolean[N]; - boolean[] isBubble = new boolean[N]; - ArrayList<NotificationChannel> channelBefore = new ArrayList<>(N); - ArrayList<String> groupKeyBefore = new ArrayList<>(N); - ArrayList<ArrayList<String>> overridePeopleBefore = new ArrayList<>(N); - ArrayList<ArrayList<SnoozeCriterion>> snoozeCriteriaBefore = new ArrayList<>(N); - ArrayList<Integer> userSentimentBefore = new ArrayList<>(N); - ArrayList<Integer> suppressVisuallyBefore = new ArrayList<>(N); - ArrayList<ArrayList<Notification.Action>> systemSmartActionsBefore = new ArrayList<>(N); - ArrayList<ArrayList<CharSequence>> smartRepliesBefore = new ArrayList<>(N); - int[] importancesBefore = new int[N]; + ArrayMap<String, NotificationRecordExtractorData> extractorDataBefore = + new ArrayMap<>(N); for (int i = 0; i < N; i++) { final NotificationRecord r = mNotificationList.get(i); - orderBefore.add(r.getKey()); - visibilities[i] = r.getPackageVisibilityOverride(); - showBadges[i] = r.canShowBadge(); - allowBubbles[i] = r.canBubble(); - isBubble[i] = r.getNotification().isBubbleNotification(); - channelBefore.add(r.getChannel()); - groupKeyBefore.add(r.getGroupKey()); - overridePeopleBefore.add(r.getPeopleOverride()); - snoozeCriteriaBefore.add(r.getSnoozeCriteria()); - userSentimentBefore.add(r.getUserSentiment()); - suppressVisuallyBefore.add(r.getSuppressedVisualEffects()); - systemSmartActionsBefore.add(r.getSystemGeneratedSmartActions()); - smartRepliesBefore.add(r.getSmartReplies()); - importancesBefore[i] = r.getImportance(); + NotificationRecordExtractorData extractorData = new NotificationRecordExtractorData( + i, + r.getPackageVisibilityOverride(), + r.canShowBadge(), + r.canBubble(), + r.getNotification().isBubbleNotification(), + r.getChannel(), + r.getGroupKey(), + r.getPeopleOverride(), + r.getSnoozeCriteria(), + r.getUserSentiment(), + r.getSuppressedVisualEffects(), + r.getSystemGeneratedSmartActions(), + r.getSmartReplies(), + r.getImportance(), + r.getRankingScore(), + r.isConversation()); + extractorDataBefore.put(r.getKey(), extractorData); mRankingHelper.extractSignals(r); } mRankingHelper.sort(mNotificationList); for (int i = 0; i < N; i++) { final NotificationRecord r = mNotificationList.get(i); - if (!orderBefore.get(i).equals(r.getKey()) - || visibilities[i] != r.getPackageVisibilityOverride() - || showBadges[i] != r.canShowBadge() - || allowBubbles[i] != r.canBubble() - || isBubble[i] != r.getNotification().isBubbleNotification() - || !Objects.equals(channelBefore.get(i), r.getChannel()) - || !Objects.equals(groupKeyBefore.get(i), r.getGroupKey()) - || !Objects.equals(overridePeopleBefore.get(i), r.getPeopleOverride()) - || !Objects.equals(snoozeCriteriaBefore.get(i), r.getSnoozeCriteria()) - || !Objects.equals(userSentimentBefore.get(i), r.getUserSentiment()) - || !Objects.equals(suppressVisuallyBefore.get(i), - r.getSuppressedVisualEffects()) - || !Objects.equals(systemSmartActionsBefore.get(i), - r.getSystemGeneratedSmartActions()) - || !Objects.equals(smartRepliesBefore.get(i), r.getSmartReplies()) - || importancesBefore[i] != r.getImportance()) { + if (!extractorDataBefore.containsKey(r.getKey())) { + // This shouldn't happen given that we just built this with all the + // notifications, but check just to be safe. + continue; + } + if (extractorDataBefore.get(r.getKey()).hasDiffForRankingLocked(r, i)) { mHandler.scheduleSendRankingUpdate(); - return; + } + + // If this notification is one for which we wanted to log an update, and + // sufficient relevant bits are different, log update. + if (r.hasPendingLogUpdate()) { + // We need to acquire the previous data associated with this specific + // notification, as the one at the current index may be unrelated if + // notification order has changed. + NotificationRecordExtractorData prevData = extractorDataBefore.get(r.getKey()); + if (prevData.hasDiffForLoggingLocked(r, i)) { + mNotificationRecordLogger.logNotificationAdjusted(r, i, 0, + getGroupInstanceId(r.getSbn().getGroupKey())); + } + + // Remove whether there was a diff or not; we've sorted the key, so if it + // turns out there was nothing to log, that's fine too. + r.setPendingLogUpdate(false); } } } @@ -8758,10 +8865,22 @@ public class NotificationManagerService extends SystemService { void snoozeNotificationInt(String key, long duration, String snoozeCriterionId, ManagedServiceInfo listener) { - String listenerName = listener == null ? null : listener.component.toShortString(); + if (listener == null) { + return; + } + String listenerName = listener.component.toShortString(); if ((duration <= 0 && snoozeCriterionId == null) || key == null) { return; } + synchronized (mNotificationLock) { + final NotificationRecord r = findInCurrentAndSnoozedNotificationByKeyLocked(key); + if (r == null) { + return; + } + if (!listener.enabledAndUserMatches(r.getSbn().getNormalizedUserId())){ + return; + } + } if (DBG) { Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, duration, diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index f66cfa99ce98..b4ca5118e10f 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -200,6 +200,10 @@ public final class NotificationRecord { private boolean mIsAppImportanceLocked; private ArraySet<Uri> mGrantableUris; + // Whether this notification record should have an update logged the next time notifications + // are sorted. + private boolean mPendingLogUpdate = false; + public NotificationRecord(Context context, StatusBarNotification sbn, NotificationChannel channel) { this.sbn = sbn; @@ -648,17 +652,23 @@ public final class NotificationRecord { final ArrayList<String> people = adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE); setPeopleOverride(people); + EventLogTags.writeNotificationAdjusted( + getKey(), Adjustment.KEY_PEOPLE, people.toString()); } if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) { final ArrayList<SnoozeCriterion> snoozeCriterionList = adjustment.getSignals().getParcelableArrayList( Adjustment.KEY_SNOOZE_CRITERIA); setSnoozeCriteria(snoozeCriterionList); + EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SNOOZE_CRITERIA, + snoozeCriterionList.toString()); } if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) { final String groupOverrideKey = adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY); setOverrideGroupKey(groupOverrideKey); + EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_GROUP_KEY, + groupOverrideKey); } if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) { // Only allow user sentiment update from assistant if user hasn't already @@ -667,27 +677,42 @@ public final class NotificationRecord { && (getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) { setUserSentiment(adjustment.getSignals().getInt( Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL)); + EventLogTags.writeNotificationAdjusted(getKey(), + Adjustment.KEY_USER_SENTIMENT, + Integer.toString(getUserSentiment())); } } if (signals.containsKey(Adjustment.KEY_CONTEXTUAL_ACTIONS)) { setSystemGeneratedSmartActions( signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS)); + EventLogTags.writeNotificationAdjusted(getKey(), + Adjustment.KEY_CONTEXTUAL_ACTIONS, + getSystemGeneratedSmartActions().toString()); } if (signals.containsKey(Adjustment.KEY_TEXT_REPLIES)) { setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_TEXT_REPLIES)); + EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TEXT_REPLIES, + getSmartReplies().toString()); } if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) { int importance = signals.getInt(Adjustment.KEY_IMPORTANCE); importance = Math.max(IMPORTANCE_UNSPECIFIED, importance); importance = Math.min(IMPORTANCE_HIGH, importance); setAssistantImportance(importance); + EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_IMPORTANCE, + Integer.toString(importance)); } if (signals.containsKey(Adjustment.KEY_RANKING_SCORE)) { mRankingScore = signals.getFloat(Adjustment.KEY_RANKING_SCORE); + EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_RANKING_SCORE, + Float.toString(mRankingScore)); } if (signals.containsKey(Adjustment.KEY_NOT_CONVERSATION)) { mIsNotConversationOverride = signals.getBoolean( Adjustment.KEY_NOT_CONVERSATION); + EventLogTags.writeNotificationAdjusted(getKey(), + Adjustment.KEY_NOT_CONVERSATION, + Boolean.toString(mIsNotConversationOverride)); } if (!signals.isEmpty() && adjustment.getIssuer() != null) { mAdjustmentIssuer = adjustment.getIssuer(); @@ -1478,6 +1503,24 @@ public final class NotificationRecord { return sbn; } + /** + * Returns whether this record's ranking score is approximately equal to otherScore + * (the difference must be within 0.0001). + */ + public boolean rankingScoreMatches(float otherScore) { + return Math.abs(mRankingScore - otherScore) < 0.0001; + } + + protected void setPendingLogUpdate(boolean pendingLogUpdate) { + mPendingLogUpdate = pendingLogUpdate; + } + + // If a caller of this function subsequently logs the update, they should also call + // setPendingLogUpdate to false to make sure other callers don't also do so. + protected boolean hasPendingLogUpdate() { + return mPendingLogUpdate; + } + @VisibleForTesting static final class Light { public final int color; diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java index 0e2ff7523c85..7d8564fe1190 100644 --- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java +++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java @@ -59,6 +59,20 @@ public interface NotificationRecordLogger { InstanceId groupId); /** + * Logs a NotificationReported atom reflecting an adjustment to a notification. + * Unlike maybeLogNotificationPosted, this method is guaranteed to log a notification update, + * so the caller must take responsibility for checking that that logging update is necessary, + * and that the notification is meaningfully changed. + * @param r The NotificationRecord. If null, no action is taken. + * @param position The position at which this notification is ranked. + * @param buzzBeepBlink Logging code reflecting whether this notification alerted the user. + * @param groupId The instance Id of the group summary notification, or null. + */ + void logNotificationAdjusted(@Nullable NotificationRecord r, + int position, int buzzBeepBlink, + InstanceId groupId); + + /** * Logs a notification cancel / dismiss event using UiEventReported (event ids from the * NotificationCancelledEvents enum). * @param r The NotificationRecord. If null, no action is taken. @@ -96,7 +110,9 @@ public interface NotificationRecordLogger { @UiEvent(doc = "New notification enqueued to post") NOTIFICATION_POSTED(162), @UiEvent(doc = "Notification substantially updated, or alerted again.") - NOTIFICATION_UPDATED(163); + NOTIFICATION_UPDATED(163), + @UiEvent(doc = "Notification adjusted by assistant.") + NOTIFICATION_ADJUSTED(908); private final int mId; NotificationReportedEvent(int id) { @@ -349,7 +365,8 @@ public interface NotificationRecordLogger { && Objects.equals(r.getSbn().getNotification().category, old.getSbn().getNotification().category) && (r.getImportance() == old.getImportance()) - && (getLoggingImportance(r) == getLoggingImportance(old))); + && (getLoggingImportance(r) == getLoggingImportance(old)) + && r.rankingScoreMatches(old.getRankingScore())); } /** diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java index 1a99fb0e55f3..1859ec4816a3 100644 --- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java +++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java @@ -16,6 +16,8 @@ package com.android.server.notification; +import android.annotation.Nullable; + import com.android.internal.logging.InstanceId; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLoggerImpl; @@ -37,33 +39,49 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger { if (!p.shouldLogReported(buzzBeepBlink)) { return; } + writeNotificationReportedAtom(p, NotificationReportedEvent.fromRecordPair(p), + position, buzzBeepBlink, groupId); + } + + @Override + public void logNotificationAdjusted(@Nullable NotificationRecord r, + int position, int buzzBeepBlink, + InstanceId groupId) { + NotificationRecordPair p = new NotificationRecordPair(r, null); + writeNotificationReportedAtom(p, NotificationReportedEvent.NOTIFICATION_ADJUSTED, + position, buzzBeepBlink, groupId); + } + + private void writeNotificationReportedAtom(NotificationRecordPair p, + NotificationReportedEvent eventType, int position, int buzzBeepBlink, + InstanceId groupId) { FrameworkStatsLog.write(FrameworkStatsLog.NOTIFICATION_REPORTED, - /* int32 event_id = 1 */ NotificationReportedEvent.fromRecordPair(p).getId(), - /* int32 uid = 2 */ r.getUid(), - /* string package_name = 3 */ r.getSbn().getPackageName(), + /* int32 event_id = 1 */ eventType.getId(), + /* int32 uid = 2 */ p.r.getUid(), + /* string package_name = 3 */ p.r.getSbn().getPackageName(), /* int32 instance_id = 4 */ p.getInstanceId(), /* int32 notification_id_hash = 5 */ p.getNotificationIdHash(), /* int32 channel_id_hash = 6 */ p.getChannelIdHash(), /* string group_id_hash = 7 */ p.getGroupIdHash(), /* int32 group_instance_id = 8 */ (groupId == null) ? 0 : groupId.getId(), - /* bool is_group_summary = 9 */ r.getSbn().getNotification().isGroupSummary(), - /* string category = 10 */ r.getSbn().getNotification().category, + /* bool is_group_summary = 9 */ p.r.getSbn().getNotification().isGroupSummary(), + /* string category = 10 */ p.r.getSbn().getNotification().category, /* int32 style = 11 */ p.getStyle(), /* int32 num_people = 12 */ p.getNumPeople(), /* int32 position = 13 */ position, /* android.stats.sysui.NotificationImportance importance = 14 */ - NotificationRecordLogger.getLoggingImportance(r), + NotificationRecordLogger.getLoggingImportance(p.r), /* int32 alerting = 15 */ buzzBeepBlink, /* NotificationImportanceExplanation importance_source = 16 */ - r.getImportanceExplanationCode(), + p.r.getImportanceExplanationCode(), /* android.stats.sysui.NotificationImportance importance_initial = 17 */ - r.getInitialImportance(), + p.r.getInitialImportance(), /* NotificationImportanceExplanation importance_initial_source = 18 */ - r.getInitialImportanceExplanationCode(), + p.r.getInitialImportanceExplanationCode(), /* android.stats.sysui.NotificationImportance importance_asst = 19 */ - r.getAssistantImportance(), + p.r.getAssistantImportance(), /* int32 assistant_hash = 20 */ p.getAssistantHash(), - /* float assistant_ranking_score = 21 */ r.getRankingScore() + /* float assistant_ranking_score = 21 */ p.r.getRankingScore() ); } diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java index 7112ae16c363..628a322bf8cd 100644 --- a/services/core/java/com/android/server/notification/NotificationShellCmd.java +++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java @@ -22,6 +22,7 @@ import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN; +import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.INotificationManager; import android.app.Notification; @@ -44,6 +45,8 @@ import android.os.Process; import android.os.RemoteException; import android.os.ShellCommand; import android.os.UserHandle; +import android.service.notification.NotificationListenerService; +import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Slog; @@ -392,19 +395,28 @@ public class NotificationShellCmd extends ShellCommand { + "--context <snooze-criterion-id>) <key>"); return 1; } - if (null == mDirectService.getNotificationRecord(key)) { - pw.println("error: no notification matching key: " + key); - return 1; - } if (duration > 0 || criterion != null) { + ShellNls nls = new ShellNls(); + nls.registerAsSystemService(mDirectService.getContext(), + new ComponentName(nls.getClass().getPackageName(), + nls.getClass().getName()), + ActivityManager.getCurrentUser()); + if (!waitForBind(nls)) { + pw.println("error: could not bind a listener in time"); + return 1; + } if (duration > 0) { pw.println(String.format("snoozing <%s> until time: %s", key, new Date(System.currentTimeMillis() + duration))); + nls.snoozeNotification(key, duration); } else { pw.println(String.format("snoozing <%s> until criterion: %s", key, criterion)); + nls.snoozeNotification(key, criterion); } - mDirectService.snoozeNotificationInt(key, duration, criterion, null); + waitForSnooze(nls, key); + nls.unregisterAsSystemService(); + waitForUnbind(nls); } else { pw.println("error: invalid value for --" + subflag + ": " + flagarg); return 1; @@ -527,14 +539,17 @@ public class NotificationShellCmd extends ShellCommand { final PendingIntent pi; if ("broadcast".equals(intentKind)) { pi = PendingIntent.getBroadcastAsUser( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED, + context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT + | PendingIntent.FLAG_MUTABLE_UNAUDITED, UserHandle.CURRENT); } else if ("service".equals(intentKind)) { pi = PendingIntent.getService( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED); + context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT + | PendingIntent.FLAG_MUTABLE_UNAUDITED); } else { pi = PendingIntent.getActivityAsUser( - context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED, null, + context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT + | PendingIntent.FLAG_MUTABLE_UNAUDITED, null, UserHandle.CURRENT); } builder.setContentIntent(pi); @@ -685,9 +700,79 @@ public class NotificationShellCmd extends ShellCommand { return 0; } + private void waitForSnooze(ShellNls nls, String key) { + for (int i = 0; i < 20; i++) { + StatusBarNotification[] sbns = nls.getSnoozedNotifications(); + for (StatusBarNotification sbn : sbns) { + if (sbn.getKey().equals(key)) { + return; + } + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return; + } + + private boolean waitForBind(ShellNls nls) { + for (int i = 0; i < 20; i++) { + if (nls.isConnected) { + Slog.i(TAG, "Bound Shell NLS"); + return true; + } else { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + return false; + } + + private void waitForUnbind(ShellNls nls) { + for (int i = 0; i < 10; i++) { + if (!nls.isConnected) { + Slog.i(TAG, "Unbound Shell NLS"); + return; + } else { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + @Override public void onHelp() { getOutPrintWriter().println(USAGE); } + + @SuppressLint("OverrideAbstract") + private static class ShellNls extends NotificationListenerService { + private static ShellNls + sNotificationListenerInstance = null; + boolean isConnected; + + @Override + public void onListenerConnected() { + super.onListenerConnected(); + sNotificationListenerInstance = this; + isConnected = true; + } + @Override + public void onListenerDisconnected() { + isConnected = false; + } + + public static ShellNls getInstance() { + return sNotificationListenerInstance; + } + } } diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 96bde3df1e68..e8a3a8150377 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -330,8 +330,7 @@ public class PreferencesHelper implements RankingConfig { } } - if (isShortcutOk(channel) && isDeletionOk(channel) - && !channel.isSoundMissing()) { + if (isShortcutOk(channel) && isDeletionOk(channel)) { r.channels.put(id, channel); } } diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java index 947405ed2a78..b276c6f37201 100644 --- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java +++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java @@ -19,10 +19,13 @@ package com.android.server.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Binder; import android.os.Build; import android.os.IDeviceIdentifiersPolicyService; import android.os.RemoteException; import android.os.SystemProperties; +import android.os.UserHandle; import com.android.internal.telephony.TelephonyPermissions; import com.android.server.SystemService; @@ -65,11 +68,31 @@ public final class DeviceIdentifiersPolicyService extends SystemService { @Override public @Nullable String getSerialForPackage(String callingPackage, String callingFeatureId) throws RemoteException { + if (!checkPackageBelongsToCaller(callingPackage)) { + throw new IllegalArgumentException( + "Invalid callingPackage or callingPackage does not belong to caller's uid:" + + Binder.getCallingUid()); + } + if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext, callingPackage, callingFeatureId, "getSerial")) { return Build.UNKNOWN; } return SystemProperties.get("ro.serialno", Build.UNKNOWN); } + + private boolean checkPackageBelongsToCaller(String callingPackage) { + int callingUid = Binder.getCallingUid(); + int callingUserId = UserHandle.getUserId(callingUid); + int callingPackageUid; + try { + callingPackageUid = mContext.getPackageManager().getPackageUidAsUser( + callingPackage, callingUserId); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + + return callingPackageUid == callingUid; + } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4925c73ef79c..3da669145363 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2146,6 +2146,13 @@ public class PackageManagerService extends IPackageManager.Stub boolean filterAppAccess(String packageName, int callingUid, int userId); @LiveImplementation(override = LiveImplementation.MANDATORY) void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState); + @LiveImplementation(override = LiveImplementation.NOT_ALLOWED) + FindPreferredActivityBodyResult findPreferredActivityInternal(Intent intent, + String resolvedType, int flags, List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered); + @LiveImplementation(override = LiveImplementation.NOT_ALLOWED) + ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, int flags, + List<ResolveInfo> query, boolean debug, int userId); } /** @@ -2928,7 +2935,24 @@ public class PackageManagerService extends IPackageManager.Stub } allHomeCandidates.addAll(resolveInfos); - final String packageName = mDefaultAppProvider.getDefaultHome(userId); + String packageName = mDefaultAppProvider.getDefaultHome(userId); + if (packageName == null) { + // Role changes are not and cannot be atomic because its implementation lives inside + // a system app, so when the home role changes, there is a window when the previous + // role holder is removed and the new role holder is granted the preferred activity, + // but hasn't become the role holder yet. However, this case may be easily hit + // because the preferred activity change triggers a broadcast and receivers may try + // to get the default home activity there. So we need to fix it for this time + // window, and an easy workaround is to fallback to the current preferred activity. + final int appId = UserHandle.getAppId(Binder.getCallingUid()); + final boolean filtered = appId >= Process.FIRST_APPLICATION_UID; + FindPreferredActivityBodyResult result = findPreferredActivityInternal( + intent, null, 0, resolveInfos, true, false, false, userId, filtered); + ResolveInfo preferredResolveInfo = result.mPreferredResolveInfo; + if (preferredResolveInfo != null && preferredResolveInfo.activityInfo != null) { + packageName = preferredResolveInfo.activityInfo.packageName; + } + } if (packageName == null) { return null; } @@ -4860,6 +4884,284 @@ public class PackageManagerService extends IPackageManager.Stub } } // switch } + + // The body of findPreferredActivity. + protected FindPreferredActivityBodyResult findPreferredActivityBody( + Intent intent, String resolvedType, int flags, + List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered, + int callingUid, boolean isDeviceProvisioned) { + FindPreferredActivityBodyResult result = new FindPreferredActivityBodyResult(); + + flags = updateFlagsForResolve( + flags, userId, callingUid, false /*includeInstantApps*/, + isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, + resolvedType, flags)); + intent = updateIntentForResolve(intent); + + // Try to find a matching persistent preferred activity. + result.mPreferredResolveInfo = findPersistentPreferredActivityLP(intent, + resolvedType, flags, query, debug, userId); + + // If a persistent preferred activity matched, use it. + if (result.mPreferredResolveInfo != null) { + return result; + } + + PreferredIntentResolver pir = mSettings.getPreferredActivities(userId); + // Get the list of preferred activities that handle the intent + if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities..."); + List<PreferredActivity> prefs = pir != null + ? pir.queryIntent(intent, resolvedType, + (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, + userId) + : null; + if (prefs != null && prefs.size() > 0) { + + // First figure out how good the original match set is. + // We will only allow preferred activities that came + // from the same match quality. + int match = 0; + + if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match..."); + + final int N = query.size(); + for (int j = 0; j < N; j++) { + final ResolveInfo ri = query.get(j); + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Match for " + ri.activityInfo + + ": 0x" + Integer.toHexString(match)); + } + if (ri.match > match) { + match = ri.match; + } + } + + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Best match: 0x" + Integer.toHexString(match)); + } + match &= IntentFilter.MATCH_CATEGORY_MASK; + final int M = prefs.size(); + for (int i = 0; i < M; i++) { + final PreferredActivity pa = prefs.get(i); + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Checking PreferredActivity ds=" + + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>") + + "\n component=" + pa.mPref.mComponent); + pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); + } + if (pa.mPref.mMatch != match) { + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Skipping bad match " + + Integer.toHexString(pa.mPref.mMatch)); + } + continue; + } + // If it's not an "always" type preferred activity and that's what we're + // looking for, skip it. + if (always && !pa.mPref.mAlways) { + if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry"); + continue; + } + final ActivityInfo ai = getActivityInfo( + pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS + | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, + userId); + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Found preferred activity:"); + if (ai != null) { + ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); + } else { + Slog.v(TAG, " null"); + } + } + final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent) + && !isDeviceProvisioned; + final boolean allowSetMutation = !excludeSetupWizardHomeActivity + && !queryMayBeFiltered; + if (ai == null) { + // Do not remove launcher's preferred activity during SetupWizard + // due to it may not install yet + if (!allowSetMutation) { + continue; + } + + // This previously registered preferred activity + // component is no longer known. Most likely an update + // to the app was installed and in the new version this + // component no longer exists. Clean it up by removing + // it from the preferred activities list, and skip it. + Slog.w(TAG, "Removing dangling preferred activity: " + + pa.mPref.mComponent); + pir.removeFilter(pa); + result.mChanged = true; + continue; + } + for (int j = 0; j < N; j++) { + final ResolveInfo ri = query.get(j); + if (!ri.activityInfo.applicationInfo.packageName + .equals(ai.applicationInfo.packageName)) { + continue; + } + if (!ri.activityInfo.name.equals(ai.name)) { + continue; + } + + if (removeMatches && allowSetMutation) { + pir.removeFilter(pa); + result.mChanged = true; + if (DEBUG_PREFERRED) { + Slog.v(TAG, "Removing match " + pa.mPref.mComponent); + } + break; + } + + // Okay we found a previously set preferred or last chosen app. + // If the result set is different from when this + // was created, and is not a subset of the preferred set, we need to + // clear it and re-ask the user their preference, if we're looking for + // an "always" type entry. + + if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity)) { + if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) { + if (allowSetMutation) { + // some components of the set are no longer present in + // the query, but the preferred activity can still be reused + if (DEBUG_PREFERRED) { + Slog.i(TAG, "Result set changed, but PreferredActivity" + + " is still valid as only non-preferred" + + " components were removed for " + intent + + " type " + resolvedType); + } + // remove obsolete components and re-add the up-to-date + // filter + PreferredActivity freshPa = new PreferredActivity(pa, + pa.mPref.mMatch, + pa.mPref.discardObsoleteComponents(query), + pa.mPref.mComponent, + pa.mPref.mAlways); + pir.removeFilter(pa); + pir.addFilter(freshPa); + result.mChanged = true; + } else { + if (DEBUG_PREFERRED) { + Slog.i(TAG, "Do not remove preferred activity"); + } + } + } else { + if (allowSetMutation) { + Slog.i(TAG, + "Result set changed, dropping preferred activity " + + "for " + intent + " type " + + resolvedType); + if (DEBUG_PREFERRED) { + Slog.v(TAG, + "Removing preferred activity since set changed " + + pa.mPref.mComponent); + } + pir.removeFilter(pa); + // Re-add the filter as a "last chosen" entry (!always) + PreferredActivity lastChosen = new PreferredActivity( + pa, pa.mPref.mMatch, null, pa.mPref.mComponent, + false); + pir.addFilter(lastChosen); + result.mChanged = true; + } + result.mPreferredResolveInfo = null; + return result; + } + } + + // Yay! Either the set matched or we're looking for the last chosen + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Returning preferred activity: " + + ri.activityInfo.packageName + "/" + ri.activityInfo.name); + } + result.mPreferredResolveInfo = ri; + return result; + } + } + } + return result; + } + + public final FindPreferredActivityBodyResult findPreferredActivityInternal( + Intent intent, String resolvedType, int flags, + List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { + + final int callingUid = Binder.getCallingUid(); + // Do NOT hold the packages lock; this calls up into the settings provider which + // could cause a deadlock. + final boolean isDeviceProvisioned = + android.provider.Settings.Global.getInt(mContext.getContentResolver(), + android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1; + // Find the preferred activity - the lock is held inside the method. + return findPreferredActivityBody( + intent, resolvedType, flags, query, always, removeMatches, debug, + userId, queryMayBeFiltered, callingUid, isDeviceProvisioned); + } + + public final ResolveInfo findPersistentPreferredActivityLP(Intent intent, + String resolvedType, + int flags, List<ResolveInfo> query, boolean debug, int userId) { + final int N = query.size(); + PersistentPreferredIntentResolver ppir = + mSettings.getPersistentPreferredActivities(userId); + // Get the list of persistent preferred activities that handle the intent + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Looking for persistent preferred activities..."); + } + List<PersistentPreferredActivity> pprefs = ppir != null + ? ppir.queryIntent(intent, resolvedType, + (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, + userId) + : null; + if (pprefs != null && pprefs.size() > 0) { + final int M = pprefs.size(); + for (int i = 0; i < M; i++) { + final PersistentPreferredActivity ppa = pprefs.get(i); + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Checking PersistentPreferredActivity ds=" + + (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>") + + "\n component=" + ppa.mComponent); + ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); + } + final ActivityInfo ai = getActivityInfo(ppa.mComponent, + flags | MATCH_DISABLED_COMPONENTS, userId); + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Found persistent preferred activity:"); + if (ai != null) { + ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); + } else { + Slog.v(TAG, " null"); + } + } + if (ai == null) { + // This previously registered persistent preferred activity + // component is no longer known. Ignore it and do NOT remove it. + continue; + } + for (int j = 0; j < N; j++) { + final ResolveInfo ri = query.get(j); + if (!ri.activityInfo.applicationInfo.packageName + .equals(ai.applicationInfo.packageName)) { + continue; + } + if (!ri.activityInfo.name.equals(ai.name)) { + continue; + } + // Found a persistent preference that can handle the intent. + if (DEBUG_PREFERRED || debug) { + Slog.v(TAG, "Returning persistent preferred activity: " + + ri.activityInfo.packageName + "/" + ri.activityInfo.name); + } + return ri; + } + } + } + return null; + } } /** @@ -5019,6 +5321,16 @@ public class PackageManagerService extends IPackageManager.Stub super.dump(type, fd, pw, dumpState); } } + public final FindPreferredActivityBodyResult findPreferredActivityBody(Intent intent, + String resolvedType, int flags, List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered, + int callingUid, boolean isDeviceProvisioned) { + synchronized (mLock) { + return super.findPreferredActivityBody(intent, resolvedType, flags, query, always, + removeMatches, debug, userId, queryMayBeFiltered, callingUid, + isDeviceProvisioned); + } + } } /** @@ -5586,6 +5898,28 @@ public class PackageManagerService extends IPackageManager.Stub current.release(); } } + public final FindPreferredActivityBodyResult findPreferredActivityInternal(Intent intent, + String resolvedType, int flags, List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { + ThreadComputer current = live(); + try { + return current.mComputer.findPreferredActivityInternal(intent, resolvedType, flags, + query, always, removeMatches, debug, userId, queryMayBeFiltered); + } finally { + current.release(); + } + } + public final ResolveInfo findPersistentPreferredActivityLP(Intent intent, + String resolvedType, int flags, List<ResolveInfo> query, boolean debug, + int userId) { + ThreadComputer current = live(); + try { + return current.mComputer.findPersistentPreferredActivityLP(intent, resolvedType, + flags, query, debug, userId); + } finally { + current.release(); + } + } } @@ -7239,6 +7573,7 @@ public class PackageManagerService extends IPackageManager.Stub t.traceEnd(); mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions); + mPermissionManager.readLegacyPermissionStateTEMP(); if (!mOnlyCore && mFirstBoot) { requestCopyPreoptedFiles(mInjector); @@ -7654,7 +7989,6 @@ public class PackageManagerService extends IPackageManager.Stub + ((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 @@ -9185,7 +9519,7 @@ public class PackageManagerService extends IPackageManager.Stub /** * Update given intent when being used to request {@link ResolveInfo}. */ - private Intent updateIntentForResolve(Intent intent) { + private static Intent updateIntentForResolve(Intent intent) { if (intent.getSelector() != null) { intent = intent.getSelector(); } @@ -10357,7 +10691,7 @@ public class PackageManagerService extends IPackageManager.Stub userId); // Find any earlier preferred or last chosen entries and nuke them findPreferredActivityNotLocked( - intent, resolvedType, flags, query, 0, false, true, false, userId); + intent, resolvedType, flags, query, false, true, false, userId); // Add the new activity as the last chosen for this filter addPreferredActivity(filter, match, null, activity, false, userId, "Setting last chosen", false); @@ -10373,7 +10707,7 @@ public class PackageManagerService extends IPackageManager.Stub final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, userId); return findPreferredActivityNotLocked( - intent, resolvedType, flags, query, 0, false, false, false, userId); + intent, resolvedType, flags, query, false, false, false, userId); } private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, @@ -10415,7 +10749,7 @@ public class PackageManagerService extends IPackageManager.Stub // If we have saved a preference for a preferred activity for // this Intent, use that. ResolveInfo ri = findPreferredActivityNotLocked(intent, resolvedType, - flags, query, r0.priority, true, false, debug, userId, queryMayBeFiltered); + flags, query, true, false, debug, userId, queryMayBeFiltered); if (ri != null) { return ri; } @@ -10528,287 +10862,72 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy("mLock") - private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, + private ResolveInfo findPersistentPreferredActivityLP(Intent intent, + String resolvedType, int flags, List<ResolveInfo> query, boolean debug, int userId) { - final int N = query.size(); - PersistentPreferredIntentResolver ppir = mSettings.getPersistentPreferredActivities(userId); - // Get the list of persistent preferred activities that handle the intent - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for presistent preferred activities..."); - List<PersistentPreferredActivity> pprefs = ppir != null - ? ppir.queryIntent(intent, resolvedType, - (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, - userId) - : null; - if (pprefs != null && pprefs.size() > 0) { - final int M = pprefs.size(); - for (int i=0; i<M; i++) { - final PersistentPreferredActivity ppa = pprefs.get(i); - if (DEBUG_PREFERRED || debug) { - Slog.v(TAG, "Checking PersistentPreferredActivity ds=" - + (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>") - + "\n component=" + ppa.mComponent); - ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - } - final ActivityInfo ai = getActivityInfo(ppa.mComponent, - flags | MATCH_DISABLED_COMPONENTS, userId); - if (DEBUG_PREFERRED || debug) { - Slog.v(TAG, "Found persistent preferred activity:"); - if (ai != null) { - ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - } else { - Slog.v(TAG, " null"); - } - } - if (ai == null) { - // This previously registered persistent preferred activity - // component is no longer known. Ignore it and do NOT remove it. - continue; - } - for (int j=0; j<N; j++) { - final ResolveInfo ri = query.get(j); - if (!ri.activityInfo.applicationInfo.packageName - .equals(ai.applicationInfo.packageName)) { - continue; - } - if (!ri.activityInfo.name.equals(ai.name)) { - continue; - } - // Found a persistent preference that can handle the intent. - if (DEBUG_PREFERRED || debug) { - Slog.v(TAG, "Returning persistent preferred activity: " + - ri.activityInfo.packageName + "/" + ri.activityInfo.name); - } - return ri; - } - } - } - return null; + return mComputer.findPersistentPreferredActivityLP(intent, + resolvedType, + flags, query, debug, userId); } - private boolean isHomeIntent(Intent intent) { + private static boolean isHomeIntent(Intent intent) { return ACTION_MAIN.equals(intent.getAction()) && intent.hasCategory(CATEGORY_HOME) && intent.hasCategory(CATEGORY_DEFAULT); } + + // findPreferredActivityBody returns two items: a "things changed" flag and a + // ResolveInfo, which is the preferred activity itself. + private static class FindPreferredActivityBodyResult { + boolean mChanged; + ResolveInfo mPreferredResolveInfo; + } + + private FindPreferredActivityBodyResult findPreferredActivityInternal( + Intent intent, String resolvedType, int flags, + List<ResolveInfo> query, boolean always, + boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { + return mComputer.findPreferredActivityInternal( + intent, resolvedType, flags, + query, always, + removeMatches, debug, userId, queryMayBeFiltered); + } + ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags, - List<ResolveInfo> query, int priority, boolean always, + List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, int userId) { return findPreferredActivityNotLocked( - intent, resolvedType, flags, query, priority, always, removeMatches, debug, userId, + intent, resolvedType, flags, query, always, removeMatches, debug, userId, UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID); } // TODO: handle preferred activities missing while user has amnesia /** <b>must not hold {@link #mLock}</b> */ ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags, - List<ResolveInfo> query, int priority, boolean always, + List<ResolveInfo> query, boolean always, boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) { if (Thread.holdsLock(mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mLock", new Throwable()); } if (!mUserManager.exists(userId)) return null; - final int callingUid = Binder.getCallingUid(); - // Do NOT hold the packages lock; this calls up into the settings provider which - // could cause a deadlock. - final boolean isDeviceProvisioned = - android.provider.Settings.Global.getInt(mContext.getContentResolver(), - android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1; - flags = updateFlagsForResolve( - flags, userId, callingUid, false /*includeInstantApps*/, - isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType, - flags)); - intent = updateIntentForResolve(intent); - // writer - synchronized (mLock) { - // Try to find a matching persistent preferred activity. - ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query, - debug, userId); - // If a persistent preferred activity matched, use it. - if (pri != null) { - return pri; + FindPreferredActivityBodyResult body = findPreferredActivityInternal( + intent, resolvedType, flags, query, always, + removeMatches, debug, userId, queryMayBeFiltered); + if (body.mChanged) { + if (DEBUG_PREFERRED) { + Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions"); } - - PreferredIntentResolver pir = mSettings.getPreferredActivities(userId); - // Get the list of preferred activities that handle the intent - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities..."); - List<PreferredActivity> prefs = pir != null - ? pir.queryIntent(intent, resolvedType, - (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, - userId) - : null; - if (prefs != null && prefs.size() > 0) { - boolean changed = false; - try { - // First figure out how good the original match set is. - // We will only allow preferred activities that came - // from the same match quality. - int match = 0; - - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match..."); - - final int N = query.size(); - for (int j=0; j<N; j++) { - final ResolveInfo ri = query.get(j); - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo - + ": 0x" + Integer.toHexString(match)); - if (ri.match > match) { - match = ri.match; - } - } - - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x" - + Integer.toHexString(match)); - - match &= IntentFilter.MATCH_CATEGORY_MASK; - final int M = prefs.size(); - for (int i=0; i<M; i++) { - final PreferredActivity pa = prefs.get(i); - if (DEBUG_PREFERRED || debug) { - Slog.v(TAG, "Checking PreferredActivity ds=" - + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>") - + "\n component=" + pa.mPref.mComponent); - pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - } - if (pa.mPref.mMatch != match) { - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match " - + Integer.toHexString(pa.mPref.mMatch)); - continue; - } - // If it's not an "always" type preferred activity and that's what we're - // looking for, skip it. - if (always && !pa.mPref.mAlways) { - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry"); - continue; - } - final ActivityInfo ai = getActivityInfo( - pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS - | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, - userId); - if (DEBUG_PREFERRED || debug) { - Slog.v(TAG, "Found preferred activity:"); - if (ai != null) { - ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); - } else { - Slog.v(TAG, " null"); - } - } - final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent) - && !isDeviceProvisioned; - final boolean allowSetMutation = !excludeSetupWizardHomeActivity - && !queryMayBeFiltered; - if (ai == null) { - // Do not remove launcher's preferred activity during SetupWizard - // due to it may not install yet - if (!allowSetMutation) { - continue; - } - - // This previously registered preferred activity - // component is no longer known. Most likely an update - // to the app was installed and in the new version this - // component no longer exists. Clean it up by removing - // it from the preferred activities list, and skip it. - Slog.w(TAG, "Removing dangling preferred activity: " - + pa.mPref.mComponent); - pir.removeFilter(pa); - changed = true; - continue; - } - for (int j=0; j<N; j++) { - final ResolveInfo ri = query.get(j); - if (!ri.activityInfo.applicationInfo.packageName - .equals(ai.applicationInfo.packageName)) { - continue; - } - if (!ri.activityInfo.name.equals(ai.name)) { - continue; - } - - if (removeMatches && allowSetMutation) { - pir.removeFilter(pa); - changed = true; - if (DEBUG_PREFERRED) { - Slog.v(TAG, "Removing match " + pa.mPref.mComponent); - } - break; - } - - // Okay we found a previously set preferred or last chosen app. - // If the result set is different from when this - // was created, and is not a subset of the preferred set, we need to - // clear it and re-ask the user their preference, if we're looking for - // an "always" type entry. - - if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity)) { - if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) { - if (allowSetMutation) { - // some components of the set are no longer present in - // the query, but the preferred activity can still be reused - if (DEBUG_PREFERRED) { - Slog.i(TAG, "Result set changed, but PreferredActivity" - + " is still valid as only non-preferred" - + " components were removed for " + intent - + " type " + resolvedType); - } - // remove obsolete components and re-add the up-to-date - // filter - PreferredActivity freshPa = new PreferredActivity(pa, - pa.mPref.mMatch, - pa.mPref.discardObsoleteComponents(query), - pa.mPref.mComponent, - pa.mPref.mAlways); - pir.removeFilter(pa); - pir.addFilter(freshPa); - changed = true; - } else { - if (DEBUG_PREFERRED) { - Slog.i(TAG, "Do not remove preferred activity"); - } - } - } else { - if (allowSetMutation) { - Slog.i(TAG, - "Result set changed, dropping preferred activity " - + "for " + intent + " type " - + resolvedType); - if (DEBUG_PREFERRED) { - Slog.v(TAG, - "Removing preferred activity since set changed " - + pa.mPref.mComponent); - } - pir.removeFilter(pa); - // Re-add the filter as a "last chosen" entry (!always) - PreferredActivity lastChosen = new PreferredActivity( - pa, pa.mPref.mMatch, null, pa.mPref.mComponent, - false); - pir.addFilter(lastChosen); - changed = true; - } - return null; - } - } - - // Yay! Either the set matched or we're looking for the last chosen - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: " - + ri.activityInfo.packageName + "/" + ri.activityInfo.name); - return ri; - } - } - } finally { - if (changed) { - if (DEBUG_PREFERRED) { - Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions"); - } - scheduleWritePackageRestrictionsLocked(userId); - } - } + synchronized (mLock) { + scheduleWritePackageRestrictionsLocked(userId); } } - if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return"); - return null; + if ((DEBUG_PREFERRED || debug) && body.mPreferredResolveInfo == null) { + Slog.v(TAG, "No preferred activity to return"); + } + return body.mPreferredResolveInfo; } /* @@ -16169,8 +16288,7 @@ public class PackageManagerService extends IPackageManager.Stub } @VisibleForTesting(visibility = Visibility.PRIVATE) - void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId, - boolean suspended) { + void sendPackagesSuspendedForUser(String intent, String[] pkgList, int[] uidList, int userId) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); @@ -16211,11 +16329,8 @@ public class PackageManagerService extends IPackageManager.Stub extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); - sendPackageBroadcast( - suspended ? Intent.ACTION_PACKAGES_SUSPENDED - : Intent.ACTION_PACKAGES_UNSUSPENDED, - null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, - userIds, null, allowList, null); + sendPackageBroadcast(intent, null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, + null, userIds, null, allowList, null); } } @@ -16529,6 +16644,8 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> changedPackagesList = new ArrayList<>(packageNames.length); final IntArray changedUids = new IntArray(packageNames.length); + final List<String> modifiedPackagesList = new ArrayList<>(packageNames.length); + final IntArray modifiedUids = new IntArray(packageNames.length); final List<String> unactionedPackages = new ArrayList<>(packageNames.length); final boolean[] canSuspend = suspended ? canSuspendPackageForUserInternal(packageNames, userId) : null; @@ -16556,13 +16673,14 @@ public class PackageManagerService extends IPackageManager.Stub unactionedPackages.add(packageName); continue; } - boolean packageUnsuspended; + final boolean packageUnsuspended; + final boolean packageModified; synchronized (mLock) { if (suspended) { - pkgSetting.addOrUpdateSuspension(callingPackage, dialogInfo, appExtras, - launcherExtras, userId); + packageModified = pkgSetting.addOrUpdateSuspension(callingPackage, + dialogInfo, appExtras, launcherExtras, userId); } else { - pkgSetting.removeSuspension(callingPackage, userId); + packageModified = pkgSetting.removeSuspension(callingPackage, userId); } packageUnsuspended = !suspended && !pkgSetting.getSuspended(userId); } @@ -16570,18 +16688,29 @@ public class PackageManagerService extends IPackageManager.Stub changedPackagesList.add(packageName); changedUids.add(UserHandle.getUid(userId, pkgSetting.appId)); } + if (packageModified) { + modifiedPackagesList.add(packageName); + modifiedUids.add(UserHandle.getUid(userId, pkgSetting.appId)); + } } if (!changedPackagesList.isEmpty()) { - final String[] changedPackages = changedPackagesList.toArray( - new String[changedPackagesList.size()]); - sendPackagesSuspendedForUser(changedPackages, changedUids.toArray(), userId, suspended); + final String[] changedPackages = changedPackagesList.toArray(new String[0]); + sendPackagesSuspendedForUser( + suspended ? Intent.ACTION_PACKAGES_SUSPENDED + : Intent.ACTION_PACKAGES_UNSUSPENDED, + changedPackages, changedUids.toArray(), userId); sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, userId); synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } - return unactionedPackages.toArray(new String[unactionedPackages.size()]); + // Send the suspension changed broadcast to ensure suspension state is not stale. + if (!modifiedPackagesList.isEmpty()) { + sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, + modifiedPackagesList.toArray(new String[0]), modifiedUids.toArray(), userId); + } + return unactionedPackages.toArray(new String[0]); } @Override @@ -16710,7 +16839,8 @@ public class PackageManagerService extends IPackageManager.Stub final String[] packageArray = unsuspendedPackages.toArray( new String[unsuspendedPackages.size()]); sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId); - sendPackagesSuspendedForUser(packageArray, unsuspendedUids.toArray(), userId, false); + sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_UNSUSPENDED, + packageArray, unsuspendedUids.toArray(), userId); } } @@ -22700,8 +22830,9 @@ public class PackageManagerService extends IPackageManager.Stub removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), userId, appId); UserManagerInternal umInternal = mInjector.getUserManagerInternal(); + StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class); final int flags; - if (umInternal.isUserUnlockingOrUnlocked(userId)) { + if (StorageManager.isUserKeyUnlocked(userId) && smInternal.isCeStoragePrepared(userId)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(userId)) { flags = StorageManager.FLAG_STORAGE_DE; @@ -23641,7 +23772,7 @@ public class PackageManagerService extends IPackageManager.Stub final List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId); final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked( - intent, null, 0, resolveInfos, 0, true, false, false, userId); + intent, null, 0, resolveInfos, true, false, false, userId); final String packageName = preferredResolveInfo != null && preferredResolveInfo.activityInfo != null ? preferredResolveInfo.activityInfo.packageName : null; @@ -25567,9 +25698,11 @@ public class PackageManagerService extends IPackageManager.Stub // Reconcile app data for all started/unlocked users final StorageManager sm = mInjector.getSystemService(StorageManager.class); UserManagerInternal umInternal = mInjector.getUserManagerInternal(); + StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class); for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) { int flags; - if (umInternal.isUserUnlockingOrUnlocked(user.id)) { + if (StorageManager.isUserKeyUnlocked(user.id) + && smInternal.isCeStoragePrepared(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { flags = StorageManager.FLAG_STORAGE_DE; @@ -25912,7 +26045,8 @@ public class PackageManagerService extends IPackageManager.Stub StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class); for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) { final int flags; - if (umInternal.isUserUnlockingOrUnlocked(user.id)) { + if (StorageManager.isUserKeyUnlocked(user.id) + && smInternal.isCeStoragePrepared(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { flags = StorageManager.FLAG_STORAGE_DE; diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 88dd03333262..5536fc5aa506 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -455,7 +455,7 @@ public abstract class PackageSettingBase extends SettingBase { return state.suspendParams != null && state.suspendParams.containsKey(suspendingPackage); } - void addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo, + boolean addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) { final PackageUserState existingUserState = modifyUserState(userId); final PackageUserState.SuspendParams newSuspendParams = @@ -464,21 +464,27 @@ public abstract class PackageSettingBase extends SettingBase { if (existingUserState.suspendParams == null) { existingUserState.suspendParams = new ArrayMap<>(); } - existingUserState.suspendParams.put(suspendingPackage, newSuspendParams); + final PackageUserState.SuspendParams oldSuspendParams = + existingUserState.suspendParams.put(suspendingPackage, newSuspendParams); existingUserState.suspended = true; onChanged(); + return !Objects.equals(oldSuspendParams, newSuspendParams); } - void removeSuspension(String suspendingPackage, int userId) { + boolean removeSuspension(String suspendingPackage, int userId) { + boolean wasModified = false; final PackageUserState existingUserState = modifyUserState(userId); if (existingUserState.suspendParams != null) { - existingUserState.suspendParams.remove(suspendingPackage); + if (existingUserState.suspendParams.remove(suspendingPackage) != null) { + wasModified = true; + } if (existingUserState.suspendParams.size() == 0) { existingUserState.suspendParams = null; } } existingUserState.suspended = (existingUserState.suspendParams != null); onChanged(); + return wasModified; } void removeSuspension(Predicate<String> suspendingPackagePredicate, int userId) { diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index fcbf40e29933..62d6717e847a 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 @@ public class ShortcutService extends IShortcutService.Stub { 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 @@ public class ShortcutService extends IShortcutService.Stub { @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/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index d4feb3a728c8..6d8137e74061 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -80,6 +80,7 @@ import android.os.UserManager; import android.os.UserManager.EnforcingUser; import android.os.UserManager.QuietModeFlag; import android.os.storage.StorageManager; +import android.os.storage.StorageManagerInternal; import android.provider.Settings; import android.security.GateKeeper; import android.service.gatekeeper.IGateKeeperService; @@ -4815,6 +4816,10 @@ public class UserManagerService extends IUserManager.Stub { // Migrate only if build fingerprints mismatch boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint); mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE); + + StorageManagerInternal smInternal = LocalServices.getService(StorageManagerInternal.class); + smInternal.markCeStoragePrepared(userId); + mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData); } diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index dab980a9e4b2..301914615562 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -557,11 +557,14 @@ final class DefaultPermissionGrantPolicy { grantPermissionsToSystemPackage(pm, verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS); // SetupWizard - grantPermissionsToSystemPackage(pm, - ArrayUtils.firstOrNull(getKnownPackages( - PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId, - PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, - CAMERA_PERMISSIONS); + final String setupWizardPackage = ArrayUtils.firstOrNull(getKnownPackages( + PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)); + grantPermissionsToSystemPackage(pm, setupWizardPackage, userId, PHONE_PERMISSIONS, + CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CAMERA_PERMISSIONS); + if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) { + grantPermissionsToSystemPackage( + pm, setupWizardPackage, userId, NEARBY_DEVICES_PERMISSIONS); + } // Camera grantPermissionsToSystemPackage(pm, diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java index b1676d0e545f..ea554d3d7996 100644 --- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java @@ -30,6 +30,7 @@ import android.os.Process; import android.os.ServiceManager; import android.os.UserHandle; import android.permission.ILegacyPermissionManager; +import android.util.EventLog; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -187,10 +188,25 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu private void verifyCallerCanCheckAccess(String packageName, String message, int pid, int uid) { // If the check is being requested by an app then only allow the app to query its own // access status. + boolean reportError = false; int callingUid = mInjector.getCallingUid(); int callingPid = mInjector.getCallingPid(); if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid || callingPid != pid)) { + reportError = true; + } + // If the query is against an app on the device, then the check should only be allowed if + // the provided uid matches that of the specified package. + if (packageName != null && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) { + int packageUid = mInjector.getPackageUidForUser(packageName, UserHandle.getUserId(uid)); + if (uid != packageUid) { + EventLog.writeEvent(0x534e4554, "193441322", + UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID + ? callingUid : uid, "Package uid mismatch"); + reportError = true; + } + } + if (reportError) { String response = String.format( "Calling uid %d, pid %d cannot access for package %s (uid=%d, pid=%d): %s", callingUid, callingPid, packageName, uid, pid, message); @@ -385,12 +401,14 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu @VisibleForTesting public static class Injector { private final Context mContext; + private final PackageManagerInternal mPackageManagerInternal; /** * Public constructor that accepts a {@code context} within which to operate. */ public Injector(@NonNull Context context) { mContext = context; + mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); } /** @@ -453,5 +471,12 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, UserHandle.getUserHandleForUid(uid)); } + + /** + * Returns the uid for the specified {@code packageName} under the provided {@code userId}. + */ + public int getPackageUidForUser(String packageName, int userId) { + return mPackageManagerInternal.getPackageUid(packageName, 0, userId); + } } } 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 7b12709e4efd..54a6c678e0da 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission( @NonNull String permName) { + final String permissionPackageName; final boolean isImmutablyRestrictedPermission; synchronized (mLock) { final Permission bp = mRegistry.getPermission(permName); @@ -1222,15 +1223,25 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 3bdf9da5bd4d..2648e1b6d2c9 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidNavigationAccessibility; int mShortPressOnPowerBehavior; int mLongPressOnPowerBehavior; + long mLongPressOnPowerAssistantTimeoutMs; int mVeryLongPressOnPowerBehavior; int mDoublePressOnPowerBehavior; int mTriplePressOnPowerBehavior; @@ -748,6 +749,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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( @@ -1748,6 +1752,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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( @@ -1971,7 +1977,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { */ private final class PowerKeyRule extends SingleKeyGestureDetector.SingleKeyRule { PowerKeyRule(int gestures) { - super(KEYCODE_POWER, gestures); + super(mContext, KEYCODE_POWER, gestures); } @Override @@ -1986,6 +1992,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + long getLongPressTimeoutMs() { + if (getResolvedLongPressOnPowerBehavior() == LONG_PRESS_POWER_ASSISTANT) { + return mLongPressOnPowerAssistantTimeoutMs; + } else { + return super.getLongPressTimeoutMs(); + } + } + + @Override void onLongPress(long eventTime) { if (mSingleKeyGestureDetector.beganFromNonInteractive() && !mSupportLongPressPowerWhenNonInteractive) { @@ -2013,7 +2028,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { */ private final class BackKeyRule extends SingleKeyGestureDetector.SingleKeyRule { BackKeyRule(int gestures) { - super(KEYCODE_BACK, gestures); + super(mContext, KEYCODE_BACK, gestures); } @Override @@ -2033,7 +2048,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void initSingleKeyGestureRules() { - mSingleKeyGestureDetector = new SingleKeyGestureDetector(mContext); + mSingleKeyGestureDetector = new SingleKeyGestureDetector(); int powerKeyGestures = 0; if (hasVeryLongPressOnPowerBehavior()) { @@ -2131,6 +2146,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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( @@ -5347,6 +5367,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 1ef2bf9151e0..6fee69bf0472 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 @@ public final class SingleKeyGestureDetector { 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 @@ public final class SingleKeyGestureDetector { * </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 @@ public final class SingleKeyGestureDetector { */ 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 final class SingleKeyGestureDetector { } } - 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 @@ public final class SingleKeyGestureDetector { 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 7555a7f2920b..c91d8dedc41b 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 @@ public class Notifier { 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 @@ public class Notifier { 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 class Notifier { 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 @@ public class Notifier { } /** + * 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 @@ public class Notifier { tm.notifyUserActivity(); mPolicy.userActivity(); mFaceDownDetector.userActivity(event); + mScreenUndimDetector.userActivity(); } void postEnhancedDischargePredictionBroadcast(long delayMs) { @@ -812,6 +832,10 @@ public class Notifier { 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 @@ public class Notifier { 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 3d47dcf4eadb..688a3b2f1d59 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 @@ public final class PowerManagerService extends SystemService 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; @@ -837,9 +838,10 @@ public final class PowerManagerService extends SystemService 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) { @@ -960,6 +962,7 @@ public final class PowerManagerService extends SystemService mInjector.createAmbientDisplaySuppressionController(context); mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock); mFaceDownDetector = new FaceDownDetector(this::onFlip); + mScreenUndimDetector = new ScreenUndimDetector(); mBatterySavingStats = new BatterySavingStats(mLock); mBatterySaverPolicy = @@ -1146,7 +1149,7 @@ public final class PowerManagerService extends SystemService 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( @@ -1181,6 +1184,7 @@ public final class PowerManagerService extends SystemService mBatterySaverController.systemReady(); mBatterySaverPolicy.systemReady(); mFaceDownDetector.systemReady(mContext); + mScreenUndimDetector.systemReady(mContext); // Register for settings changes. resolver.registerContentObserver(Settings.Secure.getUriFor( @@ -3190,6 +3194,7 @@ public final class PowerManagerService extends SystemService final boolean ready = mDisplayManagerInternal.requestPowerState(groupId, displayPowerRequest, mRequestWaitForNegativeProximity); + mNotifier.onScreenPolicyUpdate(displayPowerRequest.policy); if (DEBUG_SPEW) { Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready 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 000000000000..951bc1f76e6d --- /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/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 0ddb90ad63b9..45b83cf0454d 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -784,13 +784,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, - int userId, String opPackageName, long operationId, + int userId, long operationId, String opPackageName, long requestId, @BiometricMultiSensorMode int multiSensorConfig) { enforceBiometricDialog(); if (mBar != null) { try { mBar.showAuthenticationDialog(promptInfo, receiver, sensorIds, credentialAllowed, - requireConfirmation, userId, opPackageName, operationId, multiSensorConfig); + requireConfirmation, userId, operationId, opPackageName, requestId, + multiSensorConfig); } catch (RemoteException ex) { } } diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index 382398a210bb..e0cc8e182079 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -352,7 +352,7 @@ public class Vcn extends Handler { } private void handleSafeModeStatusChanged() { - logDbg("VcnGatewayConnection safe mode status changed"); + logVdbg("VcnGatewayConnection safe mode status changed"); boolean hasSafeModeGatewayConnection = false; // If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode @@ -368,7 +368,7 @@ public class Vcn extends Handler { hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE; if (oldStatus != mCurrentStatus) { mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection); - logDbg( + logInfo( "Safe mode " + (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE ? "entered" : "exited")); } @@ -539,6 +539,16 @@ public class Vcn extends Handler { Slog.d(TAG, getLogPrefix() + msg, tr); } + private void logInfo(String msg) { + Slog.i(TAG, getLogPrefix() + msg); + LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg); + } + + private void logInfo(String msg, Throwable tr) { + Slog.i(TAG, getLogPrefix() + msg, tr); + LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg + tr); + } + private void logErr(String msg) { Slog.e(TAG, getLogPrefix() + msg); LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg); diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 450257fcdecb..7dec4e785f5c 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -1677,10 +1677,8 @@ public class VcnGatewayConnection extends StateMachine { mFailedAttempts = 0; cancelSafeModeAlarm(); - if (mIsInSafeMode) { - mIsInSafeMode = false; - mGatewayStatusCallback.onSafeModeStatusChanged(); - } + mIsInSafeMode = false; + mGatewayStatusCallback.onSafeModeStatusChanged(); } protected void applyTransform( diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 771332071756..a51ed09790a4 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; @@ -207,7 +208,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered * every time the wallpaper is changed. */ - private class WallpaperObserver extends FileObserver { + class WallpaperObserver extends FileObserver { final int mUserId; final WallpaperData mWallpaper; @@ -225,7 +226,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG); } - private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) { + WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) { WallpaperData wallpaper = null; synchronized (mLock) { if (lockChanged) { @@ -308,9 +309,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } wallpaper.imageWallpaperPending = false; if (sysWallpaperChanged) { + IRemoteCallback.Stub callback = new IRemoteCallback.Stub() { + @Override + public void sendResult(Bundle data) throws RemoteException { + if (DEBUG) { + Slog.d(TAG, "publish system wallpaper changed!"); + } + notifyWallpaperChanged(wallpaper); + } + }; // If this was the system wallpaper, rebind... bindWallpaperComponentLocked(mImageWallpaper, true, - false, wallpaper, null); + false, wallpaper, callback); notifyColorsWhich |= FLAG_SYSTEM; } if (lockWallpaperChanged @@ -330,15 +340,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } saveSettingsLocked(wallpaper.userId); - - // Publish completion *after* we've persisted the changes - if (wallpaper.setComplete != null) { - try { - wallpaper.setComplete.onWallpaperChanged(); - } catch (RemoteException e) { - // if this fails we don't really care; the setting app may just - // have crashed and that sort of thing is a fact of life. - } + // Notify the client immediately if only lockscreen wallpaper changed. + if (lockWallpaperChanged && !sysWallpaperChanged) { + notifyWallpaperChanged(wallpaper); } } } @@ -352,6 +356,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + private void notifyWallpaperChanged(WallpaperData wallpaper) { + // Publish completion *after* we've persisted the changes + if (wallpaper.setComplete != null) { + try { + wallpaper.setComplete.onWallpaperChanged(); + } catch (RemoteException e) { + // if this fails we don't really care; the setting app may just + // have crashed and that sort of thing is a fact of life. + } + } + } + private void notifyLockWallpaperChanged() { final IWallpaperManagerCallback cb = mKeyguardListener; if (cb != null) { @@ -363,7 +379,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } - private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) { + void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) { if (wallpaper.connection != null) { wallpaper.connection.forEachDisplayConnector(connector -> { notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId); @@ -567,7 +583,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped * for display. */ - private void generateCrop(WallpaperData wallpaper) { + void generateCrop(WallpaperData wallpaper) { boolean success = false; // Only generate crop for default display. @@ -2045,7 +2061,21 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + 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 +2085,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub 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; @@ -2814,7 +2849,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return false; } - private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force, + boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force, boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) { if (DEBUG_LIVE) { Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName); @@ -3101,7 +3136,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return new JournaledFile(new File(base), new File(base + ".tmp")); } - private void saveSettingsLocked(int userId) { + void saveSettingsLocked(int userId) { JournaledFile journal = makeJournaledFile(userId); FileOutputStream fstream = null; try { @@ -3250,7 +3285,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub * Important: this method loads settings to initialize the given user's wallpaper data if * there is no current in-memory state. */ - private WallpaperData getWallpaperSafeLocked(int userId, int which) { + WallpaperData getWallpaperSafeLocked(int userId, int which) { // We're setting either just system (work with the system wallpaper), // both (also work with the system wallpaper), or just the lock // wallpaper (update against the existing lock wallpaper if any). diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 3a4faf73bfe1..e02e8671f211 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.ActivityTaskManager.INVALID_TASK_ID; 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; @@ -53,6 +55,7 @@ import android.content.ComponentName; 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; @@ -64,6 +67,7 @@ import android.os.PersistableBundle; 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; @@ -74,6 +78,7 @@ import com.android.internal.policy.IKeyguardDismissCallback; 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; @@ -557,20 +562,45 @@ class ActivityClientController extends IActivityClientController.Stub { @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 f6858e50d3c0..319d97869461 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4176,7 +4176,7 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe // The activity now gets access to the data associated with this Intent. mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants, getUriPermissionsLocked()); - final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); + final ReferrerIntent rintent = new ReferrerIntent(intent, getFilteredReferrer(referrer)); boolean unsent = true; final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping(); @@ -8631,6 +8631,19 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe } /** + * Gets the referrer package name with respect to package visibility. This method returns null + * if the given package is not visible to this activity. + */ + String getFilteredReferrer(String referrerPackage) { + if (referrerPackage == null || (!referrerPackage.equals(packageName) + && mWmService.mPmInternal.filterAppAccess( + referrerPackage, info.applicationInfo.uid, mUserId))) { + return null; + } + return referrerPackage; + } + + /** * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord * should be visible depending on Keyguard state. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index d45861f303a9..ca4c1257323a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3387,9 +3387,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); mRootWindowContainer.moveActivityToPinnedRootTask( r, "enterPictureInPictureMode"); - final Task rootTask = r.getRootTask(); - rootTask.setPictureInPictureAspectRatio(aspectRatio); - rootTask.setPictureInPictureActions(actions); + final Task task = r.getTask(); + task.setPictureInPictureAspectRatio(aspectRatio); + task.setPictureInPictureActions(actions); + + // Continue the pausing process after entering pip. + if (task.getPausingActivity() == r) { + task.schedulePauseActivity(r, false /* userLeaving */, + false /* pauseImmediately */, "auto-pip"); + } } }; diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 49c8bee275bb..b7c67a98792d 100755 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -895,9 +895,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, - r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), - r.getSavedState(), r.getPersistentSavedState(), results, newIntents, - r.takeOptions(), isTransitionForward, + r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor, + proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), + results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken, r.getLaunchedFromBubble())); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index e696e2c13a03..05356f54b61f 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -3144,6 +3144,7 @@ public class DisplayPolicy { pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars="); pw.println(mDisplayContent.getInsetsPolicy().getRemoteInsetsControllerControlsSystemBars()); + mSystemGestures.dump(pw, prefix); pw.print(prefix); pw.println("Looper state:"); mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " "); diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index ad0583992795..a9b37c08adfe 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -505,7 +505,9 @@ public class DisplayRotation { } if (mDisplayContent.mFixedRotationTransitionListener - .isTopFixedOrientationRecentsAnimating()) { + .isTopFixedOrientationRecentsAnimating() + // If screen is off or the device is going to sleep, then still allow to update. + && mService.mPolicy.okToAnimate(false /* ignoreScreenOn */)) { // During the recents animation, the closing app might still be considered on top. // In order to ignore its requested orientation to avoid a sensor led rotation (e.g // user rotating the device while the recents animation is running), we ignore diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 18ea738b08ce..aa257f847e25 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -464,7 +464,8 @@ class DragState { if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) { // Only allow the extras to be dispatched to a global-intercepting drag target ClipData data = interceptsGlobalDrag ? mData.copyForTransferWithActivityInfo() : null; - DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY, + DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, + newWin.translateToWindowX(touchX), newWin.translateToWindowY(touchY), data, false /* includeDragSurface */, null /* dragAndDropPermission */); try { diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 8c781a13f7db..d417d56b6d31 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -39,6 +39,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -650,6 +651,7 @@ final class InputMonitor { || type == TYPE_DOCK_DIVIDER || type == TYPE_ACCESSIBILITY_OVERLAY || type == TYPE_INPUT_CONSUMER - || type == TYPE_VOICE_INTERACTION; + || type == TYPE_VOICE_INTERACTION + || type == TYPE_STATUS_BAR_ADDITIONAL; } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 5215de12af1c..d5439499328f 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2133,6 +2133,9 @@ public class RootWindowContainer extends WindowContainer<DisplayContent> final Task rootTask; if (singleActivity) { rootTask = task; + + // Apply the last recents animation leash transform to the task entering PIP + rootTask.maybeApplyLastRecentsAnimationTransaction(); } else { // In the case of multiple activities, we will create a new task for it and then // move the PIP activity into the task. Note that we explicitly defer the task diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 3c6c23b08091..c7bf8ecfe949 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -59,11 +59,30 @@ class SurfaceAnimator { @VisibleForTesting final Animatable mAnimatable; private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback; + + /** + * Static callback to run on all animations started through this SurfaceAnimator + * when an animation on a Surface is finished or cancelled without restart. + */ @VisibleForTesting @Nullable final OnAnimationFinishedCallback mStaticAnimationFinishedCallback; + + /** + * Callback unique to each animation (i.e. AnimationAdapter). To be run when an animation on a + * Surface is finished or cancelled without restart. + */ + @Nullable + private OnAnimationFinishedCallback mSurfaceAnimationFinishedCallback; + + /** + * The callback is triggered after the SurfaceAnimator sends a cancel call to the underlying + * AnimationAdapter. + * NOTE: Must be called wherever we call onAnimationCancelled on mAnimation. + */ @Nullable - private OnAnimationFinishedCallback mAnimationFinishedCallback; + private Runnable mAnimationCancelledCallback; + private boolean mAnimationStartDelayed; /** @@ -100,7 +119,7 @@ class SurfaceAnimator { return; } final OnAnimationFinishedCallback animationFinishCallback = - mAnimationFinishedCallback; + mSurfaceAnimationFinishedCallback; reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */); if (staticAnimationFinishedCallback != null) { staticAnimationFinishedCallback.onAnimationFinished(type, anim); @@ -130,15 +149,19 @@ class SurfaceAnimator { * This is important as it will start with the leash hidden or visible before * handing it to the component that is responsible to run the animation. * @param animationFinishedCallback The callback being triggered when the animation finishes. + * @param animationCancelledCallback The callback is triggered after the SurfaceAnimator sends a + * cancel call to the underlying AnimationAdapter. */ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type, @Nullable OnAnimationFinishedCallback animationFinishedCallback, + @Nullable Runnable animationCancelledCallback, @Nullable SurfaceFreezer freezer) { cancelAnimation(t, true /* restarting */, true /* forwardCancel */); mAnimation = anim; mAnimationType = type; - mAnimationFinishedCallback = animationFinishedCallback; + mSurfaceAnimationFinishedCallback = animationFinishedCallback; + mAnimationCancelledCallback = animationCancelledCallback; final SurfaceControl surface = mAnimatable.getSurfaceControl(); if (surface == null) { Slog.w(TAG, "Unable to start animation, surface is null or no children."); @@ -161,14 +184,9 @@ class SurfaceAnimator { } void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, - @AnimationType int type, - @Nullable OnAnimationFinishedCallback animationFinishedCallback) { - startAnimation(t, anim, hidden, type, animationFinishedCallback, null /* freezer */); - } - - void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type) { - startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */); + startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */, + null /* animationCancelledCallback */, null /* freezer */); } /** @@ -278,7 +296,8 @@ class SurfaceAnimator { mLeash = from.mLeash; mAnimation = from.mAnimation; mAnimationType = from.mAnimationType; - mAnimationFinishedCallback = from.mAnimationFinishedCallback; + mSurfaceAnimationFinishedCallback = from.mSurfaceAnimationFinishedCallback; + mAnimationCancelledCallback = from.mAnimationCancelledCallback; // Cancel source animation, but don't let animation runner cancel the animation. from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */); @@ -306,11 +325,16 @@ class SurfaceAnimator { final SurfaceControl leash = mLeash; final AnimationAdapter animation = mAnimation; final @AnimationType int animationType = mAnimationType; - final OnAnimationFinishedCallback animationFinishedCallback = mAnimationFinishedCallback; + final OnAnimationFinishedCallback animationFinishedCallback = + mSurfaceAnimationFinishedCallback; + final Runnable animationCancelledCallback = mAnimationCancelledCallback; reset(t, false); if (animation != null) { if (!mAnimationStartDelayed && forwardCancel) { animation.onAnimationCancelled(leash); + if (animationCancelledCallback != null) { + animationCancelledCallback.run(); + } } if (!restarting) { if (mStaticAnimationFinishedCallback != null) { @@ -335,7 +359,7 @@ class SurfaceAnimator { private void reset(Transaction t, boolean destroyLeash) { mService.mAnimationTransferMap.remove(mAnimation); mAnimation = null; - mAnimationFinishedCallback = null; + mSurfaceAnimationFinishedCallback = null; mAnimationType = ANIMATION_TYPE_NONE; if (mLeash == null) { return; diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java index b55cc9d06041..02d8c2a1413f 100644 --- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java +++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java @@ -16,6 +16,12 @@ package com.android.server.wm; +import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM; +import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; +import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT; +import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; + +import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; @@ -33,6 +39,8 @@ import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; import android.widget.OverScroller; +import java.io.PrintWriter; + /** * Listens for system-wide input gestures, firing callbacks when detected. * @hide @@ -54,7 +62,8 @@ class SystemGesturesPointerEventListener implements PointerEventListener { private final Context mContext; private final Handler mHandler; private int mDisplayCutoutTouchableRegionSize; - private int mSwipeStartThreshold; + // The thresholds for each edge of the display + private final Rect mSwipeStartThreshold = new Rect(); private int mSwipeDistanceThreshold; private final Callbacks mCallbacks; private final int[] mDownPointerId = new int[MAX_TRACKED_POINTERS]; @@ -66,7 +75,6 @@ class SystemGesturesPointerEventListener implements PointerEventListener { int screenHeight; int screenWidth; - private DisplayInfo mTmpDisplayInfo = new DisplayInfo(); private int mDownPointers; private boolean mSwipeFireable; private boolean mDebugFireable; @@ -89,27 +97,41 @@ class SystemGesturesPointerEventListener implements PointerEventListener { void onConfigurationChanged() { final Resources r = mContext.getResources(); + final int defaultThreshold = r.getDimensionPixelSize( + com.android.internal.R.dimen.system_gestures_start_threshold); + mSwipeStartThreshold.set(defaultThreshold, defaultThreshold, defaultThreshold, + defaultThreshold); + mSwipeDistanceThreshold = defaultThreshold; + final Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(Display.DEFAULT_DISPLAY); - display.getDisplayInfo(mTmpDisplayInfo); - mSwipeStartThreshold = mTmpDisplayInfo.logicalWidth > mTmpDisplayInfo.logicalHeight - ? r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_landscape) - : r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_portrait); - final DisplayCutout displayCutout = display.getCutout(); if (displayCutout != null) { - final Rect bounds = displayCutout.getBoundingRectTop(); - if (!bounds.isEmpty()) { - // Expand swipe start threshold such that we can catch touches that just start below - // the notch area - mDisplayCutoutTouchableRegionSize = r.getDimensionPixelSize( - com.android.internal.R.dimen.display_cutout_touchable_region_size); - mSwipeStartThreshold += mDisplayCutoutTouchableRegionSize; + // Expand swipe start threshold such that we can catch touches that just start beyond + // the notch area + mDisplayCutoutTouchableRegionSize = r.getDimensionPixelSize( + com.android.internal.R.dimen.display_cutout_touchable_region_size); + final Rect[] bounds = displayCutout.getBoundingRectsAll(); + if (bounds[BOUNDS_POSITION_LEFT] != null) { + mSwipeStartThreshold.left = Math.max(mSwipeStartThreshold.left, + bounds[BOUNDS_POSITION_LEFT].width() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_TOP] != null) { + mSwipeStartThreshold.top = Math.max(mSwipeStartThreshold.top, + bounds[BOUNDS_POSITION_TOP].height() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_RIGHT] != null) { + mSwipeStartThreshold.right = Math.max(mSwipeStartThreshold.right, + bounds[BOUNDS_POSITION_RIGHT].width() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_BOTTOM] != null) { + mSwipeStartThreshold.bottom = Math.max(mSwipeStartThreshold.bottom, + bounds[BOUNDS_POSITION_BOTTOM].height() + + mDisplayCutoutTouchableRegionSize); } } - mSwipeDistanceThreshold = mSwipeStartThreshold; if (DEBUG) Slog.d(TAG, "mSwipeStartThreshold=" + mSwipeStartThreshold - + " mSwipeDistanceThreshold=" + mSwipeDistanceThreshold); + + " mSwipeDistanceThreshold=" + mSwipeDistanceThreshold); } private static <T> T checkNull(String name, T arg) { @@ -280,22 +302,22 @@ class SystemGesturesPointerEventListener implements PointerEventListener { final long elapsed = time - mDownTime[i]; if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i] + " moved (" + fromX + "->" + x + "," + fromY + "->" + y + ") in " + elapsed); - if (fromY <= mSwipeStartThreshold + if (fromY <= mSwipeStartThreshold.top && y > fromY + mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_TOP; } - if (fromY >= screenHeight - mSwipeStartThreshold + if (fromY >= screenHeight - mSwipeStartThreshold.bottom && y < fromY - mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_BOTTOM; } - if (fromX >= screenWidth - mSwipeStartThreshold + if (fromX >= screenWidth - mSwipeStartThreshold.right && x < fromX - mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_RIGHT; } - if (fromX <= mSwipeStartThreshold + if (fromX <= mSwipeStartThreshold.left && x > fromX + mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_LEFT; @@ -303,6 +325,15 @@ class SystemGesturesPointerEventListener implements PointerEventListener { return SWIPE_NONE; } + public void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + final String inner = prefix + " "; + pw.println(prefix + TAG + ":"); + pw.print(inner); pw.print("mDisplayCutoutTouchableRegionSize="); + pw.println(mDisplayCutoutTouchableRegionSize); + pw.print(inner); pw.print("mSwipeStartThreshold="); pw.println(mSwipeStartThreshold); + pw.print(inner); pw.print("mSwipeDistanceThreshold="); pw.println(mSwipeDistanceThreshold); + } + private final class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener { private OverScroller mOverscroller; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 3b43412f117e..cc36e9e2282b 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -5791,23 +5791,8 @@ class Task extends WindowContainer<WindowContainer> { + "directly: %s", prev); didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs); - mPausingActivity = null; } else { - ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev); - try { - EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), - prev.shortComponentName, "userLeaving=" + userLeaving, reason); - - mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), - prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, - prev.configChangeFlags, pauseImmediately)); - } catch (Exception e) { - // Ignore exception, if process died other code will cleanup. - Slog.w(TAG, "Exception thrown during pause", e); - mPausingActivity = null; - mLastPausedActivity = null; - mTaskSupervisor.mNoHistoryActivities.remove(prev); - } + schedulePauseActivity(prev, userLeaving, pauseImmediately, reason); } } else { mPausingActivity = null; @@ -5822,7 +5807,7 @@ class Task extends WindowContainer<WindowContainer> { } // If already entered PIP mode, no need to keep pausing. - if (mPausingActivity != null && !didAutoPip) { + if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt @@ -5855,6 +5840,25 @@ class Task extends WindowContainer<WindowContainer> { } } + void schedulePauseActivity(ActivityRecord prev, boolean userLeaving, + boolean pauseImmediately, String reason) { + ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev); + try { + EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), + prev.shortComponentName, "userLeaving=" + userLeaving, reason); + + mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), + prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, + prev.configChangeFlags, pauseImmediately)); + } catch (Exception e) { + // Ignore exception, if process died other code will cleanup. + Slog.w(TAG, "Exception thrown during pause", e); + mPausingActivity = null; + mLastPausedActivity = null; + mTaskSupervisor.mNoHistoryActivities.remove(prev); + } + } + @VisibleForTesting void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { // Complete the pausing process of a pausing activity, so it doesn't make sense to diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 256259d26684..89db2ff83e6f 100755 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -44,6 +44,9 @@ import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static java.lang.Integer.MIN_VALUE; + +import android.annotation.ColorInt; import android.annotation.Nullable; import android.app.ActivityOptions; import android.app.WindowConfiguration; @@ -82,6 +85,22 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { DisplayContent mDisplayContent; /** + * A color layer that serves as a solid color background to certain animations. + */ + private SurfaceControl mColorBackgroundLayer; + + /** + * This counter is used to make sure we don't prematurely clear the background color in the + * case that background color animations are interleaved. + * NOTE: The last set color will remain until the counter is reset to 0, which means that an + * animation background color may sometime remain after the animation has finished through an + * animation with a different background color if an animation starts after and ends before + * another where both set different background colors. However, this is not a concern as + * currently all task animation backgrounds are the same color. + */ + private int mColorLayerCounter = 0; + + /** * A control placed at the appropriate level for transitions to occur. */ private SurfaceControl mAppAnimationLayer; @@ -963,6 +982,11 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { if (getParent() != null) { super.onParentChanged(newParent, oldParent, () -> { + mColorBackgroundLayer = makeChildSurface(null) + .setColorLayer() + .setName("colorBackgroundLayer") + .setCallsite("TaskDisplayArea.onParentChanged") + .build(); mAppAnimationLayer = makeChildSurface(null) .setName("animationLayer") .setCallsite("TaskDisplayArea.onParentChanged") @@ -979,6 +1003,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { .setName("splitScreenDividerAnchor") .setCallsite("TaskDisplayArea.onParentChanged") .build(); + getSyncTransaction() .show(mAppAnimationLayer) .show(mBoostedAppAnimationLayer) @@ -988,11 +1013,13 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } else { super.onParentChanged(newParent, oldParent); mWmService.mTransactionFactory.get() + .remove(mColorBackgroundLayer) .remove(mAppAnimationLayer) .remove(mBoostedAppAnimationLayer) .remove(mHomeAppAnimationLayer) .remove(mSplitScreenDividerAnchor) .apply(); + mColorBackgroundLayer = null; mAppAnimationLayer = null; mBoostedAppAnimationLayer = null; mHomeAppAnimationLayer = null; @@ -1000,6 +1027,39 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } } + void setBackgroundColor(@ColorInt int color) { + if (mColorBackgroundLayer == null) { + return; + } + + float r = ((color >> 16) & 0xff) / 255.0f; + float g = ((color >> 8) & 0xff) / 255.0f; + float b = ((color >> 0) & 0xff) / 255.0f; + float a = ((color >> 24) & 0xff) / 255.0f; + + mColorLayerCounter++; + + getPendingTransaction().setLayer(mColorBackgroundLayer, MIN_VALUE) + .setColor(mColorBackgroundLayer, new float[]{r, g, b}) + .setAlpha(mColorBackgroundLayer, a) + .setWindowCrop(mColorBackgroundLayer, getSurfaceWidth(), getSurfaceHeight()) + .setPosition(mColorBackgroundLayer, 0, 0) + .show(mColorBackgroundLayer); + + scheduleAnimation(); + } + + void clearBackgroundColor() { + mColorLayerCounter--; + + // Only clear the color layer if we have received the same amounts of clear as set + // requests. + if (mColorLayerCounter == 0) { + getPendingTransaction().hide(mColorBackgroundLayer); + scheduleAnimation(); + } + } + @Override void migrateToNewSurfaceControl(SurfaceControl.Transaction t) { super.migrateToNewSurfaceControl(t); @@ -1008,6 +1068,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } // As TaskDisplayArea is getting a new surface, reparent and reorder the child surfaces. + t.reparent(mColorBackgroundLayer, mSurfaceControl); t.reparent(mAppAnimationLayer, mSurfaceControl); t.reparent(mBoostedAppAnimationLayer, mSurfaceControl); t.reparent(mHomeAppAnimationLayer, mSurfaceControl); @@ -2151,6 +2212,11 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } @Override + TaskDisplayArea getTaskDisplayArea() { + return this; + } + + @Override boolean isTaskDisplayArea() { return true; } diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java index ec4eb5dc85de..073a508083f0 100644 --- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java +++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java @@ -118,16 +118,30 @@ public class WindowAnimationSpec implements AnimationSpec { @Override public long calculateStatusBarTransitionStartTime() { TranslateAnimation openTranslateAnimation = findTranslateAnimation(mAnimation); - if (openTranslateAnimation != null) { - // Some interpolators are extremely quickly mostly finished, but not completely. For - // our purposes, we need to find the fraction for which ther interpolator is mostly - // there, and use that value for the calculation. - float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator()); - return SystemClock.uptimeMillis() - + openTranslateAnimation.getStartOffset() - + (long)(openTranslateAnimation.getDuration() * t) - - STATUS_BAR_TRANSITION_DURATION; + if (openTranslateAnimation != null) { + if (openTranslateAnimation.isXAxisTransition() + && openTranslateAnimation.isFullWidthTranslate()) { + // On X axis transitions that are fullscreen (heuristic for task like transitions) + // we want the status bar to animate right in the middle of the translation when + // the windows/tasks have each moved half way across. + float t = findMiddleOfTranslationFraction(openTranslateAnimation.getInterpolator()); + + return SystemClock.uptimeMillis() + + openTranslateAnimation.getStartOffset() + + (long) (openTranslateAnimation.getDuration() * t) + - (long) (STATUS_BAR_TRANSITION_DURATION * 0.5); + } else { + // Some interpolators are extremely quickly mostly finished, but not completely. For + // our purposes, we need to find the fraction for which their interpolator is mostly + // there, and use that value for the calculation. + float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator()); + + return SystemClock.uptimeMillis() + + openTranslateAnimation.getStartOffset() + + (long) (openTranslateAnimation.getDuration() * t) + - STATUS_BAR_TRANSITION_DURATION; + } } else { return SystemClock.uptimeMillis(); } @@ -176,20 +190,39 @@ public class WindowAnimationSpec implements AnimationSpec { } /** - * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which - * {@code interpolator(t + eps) > 0.99}. + * Finds the fraction of the animation's duration at which the transition is almost done with a + * maximal error of 0.01 when it is animated with {@code interpolator}. */ private static float findAlmostThereFraction(Interpolator interpolator) { + return findInterpolationAdjustedTargetFraction(interpolator, 0.99f, 0.01f); + } + + /** + * Finds the fraction of the animation's duration at which the transition is spacially half way + * done with a maximal error of 0.01 when it is animated with {@code interpolator}. + */ + private float findMiddleOfTranslationFraction(Interpolator interpolator) { + return findInterpolationAdjustedTargetFraction(interpolator, 0.5f, 0.01f); + } + + /** + * Binary searches for a {@code val} such that there exists an {@code -0.01 < epsilon < 0.01} + * for which {@code interpolator(val + epsilon) > target}. + */ + private static float findInterpolationAdjustedTargetFraction( + Interpolator interpolator, float target, float epsilon) { float val = 0.5f; float adj = 0.25f; - while (adj >= 0.01f) { - if (interpolator.getInterpolation(val) < 0.99f) { + + while (adj >= epsilon) { + if (interpolator.getInterpolation(val) < target) { val += adj; } else { val -= adj; } adj /= 2; } + return val; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index b1c7e196b70c..d99aed1b409a 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -30,6 +30,10 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.UserHandle.USER_NULL; import static android.view.SurfaceControl.Transaction; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; +import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK; +import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; @@ -59,10 +63,13 @@ import static com.android.server.wm.WindowManagerService.logWithStack; import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM; import android.annotation.CallSuper; +import android.annotation.ColorInt; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityThread; import android.app.WindowConfiguration; +import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; @@ -88,6 +95,7 @@ import android.view.animation.Animation; import android.window.IWindowContainerToken; import android.window.WindowContainerToken; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; @@ -850,6 +858,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return parent != null ? parent.getRootDisplayArea() : null; } + @Nullable + TaskDisplayArea getTaskDisplayArea() { + WindowContainer parent = getParent(); + return parent != null ? parent.getTaskDisplayArea() : null; + } + boolean isAttached() { return getDisplayArea() != null; } @@ -2495,10 +2509,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * some point but the meaning is too weird to work for all containers. * @param type The type of animation defined as {@link AnimationType}. * @param animationFinishedCallback The callback being triggered when the animation finishes. + * @param animationCancelledCallback The callback is triggered after the SurfaceAnimator sends a + * cancel call to the underlying AnimationAdapter. */ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type, - @Nullable OnAnimationFinishedCallback animationFinishedCallback) { + @Nullable OnAnimationFinishedCallback animationFinishedCallback, + @Nullable Runnable animationCancelledCallback) { if (DEBUG_ANIM) { Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim); } @@ -2506,7 +2523,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // TODO: This should use isVisible() but because isVisible has a really weird meaning at // the moment this doesn't work for all animatable window containers. mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback, - mSurfaceFreezer); + animationCancelledCallback, mSurfaceFreezer); + } + + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, + @AnimationType int type, + @Nullable OnAnimationFinishedCallback animationFinishedCallback) { + startAnimation(t, anim, hidden, type, animationFinishedCallback, + null /* adapterAnimationCancelledCallback */); } void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @@ -2714,8 +2738,26 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (sources != null) { mSurfaceAnimationSources.addAll(sources); } + + TaskDisplayArea taskDisplayArea = getTaskDisplayArea(); + boolean isSettingBackgroundColor = taskDisplayArea != null + && isTransitionWithBackgroundColor(transit); + + if (isSettingBackgroundColor) { + Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext(); + @ColorInt int backgroundColor = uiContext.getColor(R.color.overview_background); + + taskDisplayArea.setBackgroundColor(backgroundColor); + } + + final Runnable cleanUpCallback = isSettingBackgroundColor + ? taskDisplayArea::clearBackgroundColor : () -> {}; + startAnimation(getPendingTransaction(), adapter, !isVisible(), - ANIMATION_TYPE_APP_TRANSITION); + ANIMATION_TYPE_APP_TRANSITION, + (type, anim) -> cleanUpCallback.run(), + cleanUpCallback); + if (adapter.getShowWallpaper()) { getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } @@ -2726,6 +2768,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } } + private boolean isTransitionWithBackgroundColor(@TransitionOldType int transit) { + return transit == TRANSIT_OLD_TASK_OPEN + || transit == TRANSIT_OLD_TASK_CLOSE + || transit == TRANSIT_OLD_TASK_TO_FRONT + || transit == TRANSIT_OLD_TASK_TO_BACK; + } + final SurfaceAnimationRunner getSurfaceAnimationRunner() { return mWmService.mSurfaceAnimationRunner; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c9e596d106ca..f779381568ad 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2721,8 +2721,8 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, - Bundle options) { + public Configuration attachWindowContextToDisplayArea(IBinder clientToken, int + type, int displayId, Bundle options) { final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, "attachWindowContextToDisplayArea", false /* printLog */); final int callingUid = Binder.getCallingUid(); @@ -2733,15 +2733,17 @@ public class WindowManagerService extends IWindowManager.Stub if (dc == null) { ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayArea: trying to attach" + " to a non-existing display:%d", displayId); - return false; + return null; } // TODO(b/155340867): Investigate if we still need roundedCornerOverlay after // the feature b/155340867 is completed. final DisplayArea da = dc.findAreaForWindowType(type, options, callerCanManageAppTokens, false /* roundedCornerOverlay */); + // TODO(b/190019118): Avoid to send onConfigurationChanged because it has been done + // in return value of attachWindowContextToDisplayArea. mWindowContextListenerController.registerWindowContainerListener(clientToken, da, callingUid, type, options); - return true; + return da.getConfiguration(); } } finally { Binder.restoreCallingIdentity(origId); @@ -7099,6 +7101,7 @@ public class WindowManagerService extends IWindowManager.Stub "requestScrollCapture: caught exception dispatching to window." + "token=%s", targetWindow.mClient.asBinder()); responseBuilder.setWindowTitle(targetWindow.getName()); + responseBuilder.setPackageName(targetWindow.getOwningPackage()); responseBuilder.setDescription(String.format("caught exception: %s", e)); listener.onScrollCaptureResponse(responseBuilder.build()); } @@ -8626,8 +8629,9 @@ public class WindowManagerService extends IWindowManager.Stub if (imeTargetWindowTask == null) { return false; } - final TaskSnapshot snapshot = mAtmService.getTaskSnapshot(imeTargetWindowTask.mTaskId, - false /* isLowResolution */); + final TaskSnapshot snapshot = getTaskSnapshot(imeTargetWindowTask.mTaskId, + imeTargetWindowTask.mUserId, false /* isLowResolution */, + false /* restoreFromDisk */); return snapshot != null && snapshot.hasImeSurface(); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 5e042efa2f11..0af6a29fad10 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -26,7 +26,6 @@ import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.graphics.GraphicsProtos.dumpPointProto; import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE; -import static android.hardware.input.InputManager.BLOCK_UNTRUSTED_TOUCHES; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.PowerManager.DRAW_WAKE_LOCK; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -194,7 +193,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.admin.DevicePolicyCache; -import android.app.compat.CompatChanges; import android.content.Context; import android.content.res.Configuration; import android.graphics.Matrix; @@ -1156,9 +1154,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } int getTouchOcclusionMode() { - if (!CompatChanges.isChangeEnabled(BLOCK_UNTRUSTED_TOUCHES, mOwnerUid)) { - return TouchOcclusionMode.ALLOW; - } if (WindowManager.LayoutParams.isSystemAlertWindowType(mAttrs.type)) { return TouchOcclusionMode.USE_OPACITY; } diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp index e319e3febc21..4190a91710fc 100644 --- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp +++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp @@ -55,6 +55,7 @@ using android::base::unique_fd; #define SYNC_RECEIVED_WHILE_FROZEN (1) #define ASYNC_RECEIVED_WHILE_FROZEN (2) +#define TXNS_PENDING_WHILE_FROZEN (4) namespace android { @@ -232,17 +233,20 @@ static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, job compactProcessOrFallback(pid, compactionFlags); } -static void com_android_server_am_CachedAppOptimizer_freezeBinder( +static jint com_android_server_am_CachedAppOptimizer_freezeBinder( JNIEnv *env, jobject clazz, jint pid, jboolean freeze) { - if (IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */) != 0) { + jint retVal = IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */); + if (retVal != 0 && retVal != -EAGAIN) { jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder"); } + + return retVal; } static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv *env, jobject clazz, jint pid) { - bool syncReceived = false, asyncReceived = false; + uint32_t syncReceived = 0, asyncReceived = 0; int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived); @@ -252,13 +256,12 @@ static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv jint retVal = 0; - if(syncReceived) { - retVal |= SYNC_RECEIVED_WHILE_FROZEN;; - } - - if(asyncReceived) { - retVal |= ASYNC_RECEIVED_WHILE_FROZEN; - } + // bit 0 of sync_recv goes to bit 0 of retVal + retVal |= syncReceived & SYNC_RECEIVED_WHILE_FROZEN; + // bit 0 of async_recv goes to bit 1 of retVal + retVal |= (asyncReceived << 1) & ASYNC_RECEIVED_WHILE_FROZEN; + // bit 1 of sync_recv goes to bit 2 of retVal + retVal |= (syncReceived << 1) & TXNS_PENDING_WHILE_FROZEN; return retVal; } @@ -278,7 +281,7 @@ static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem}, {"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess}, - {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}, + {"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}, {"getBinderFreezeInfo", "(I)I", (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo}, {"getFreezerCheckPath", "()Ljava/lang/String;", diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index a94ad4ad7ef2..bb9740b60f78 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -337,7 +337,7 @@ public: void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override; bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override; void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override; - void setPointerCapture(bool enabled) override; + void setPointerCapture(const PointerCaptureRequest& request) override; void notifyDropWindow(const sp<IBinder>& token, float x, float y) override; /* --- PointerControllerPolicyInterface implementation --- */ @@ -372,8 +372,8 @@ private: // Show touches feature enable/disable. bool showTouches; - // Pointer capture feature enable/disable. - bool pointerCapture; + // The latest request to enable or disable Pointer Capture. + PointerCaptureRequest pointerCaptureRequest; // Sprite controller singleton, created on first use. sp<SpriteController> spriteController; @@ -417,7 +417,6 @@ NativeInputManager::NativeInputManager(jobject contextObj, mLocked.pointerSpeed = 0; mLocked.pointerGesturesEnabled = true; mLocked.showTouches = false; - mLocked.pointerCapture = false; mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT; } mInteractive = true; @@ -446,7 +445,9 @@ void NativeInputManager::dump(std::string& dump) { dump += StringPrintf(INDENT "Pointer Gestures Enabled: %s\n", toString(mLocked.pointerGesturesEnabled)); dump += StringPrintf(INDENT "Show Touches: %s\n", toString(mLocked.showTouches)); - dump += StringPrintf(INDENT "Pointer Capture Enabled: %s\n", toString(mLocked.pointerCapture)); + dump += StringPrintf(INDENT "Pointer Capture: %s, seq=%" PRIu32 "\n", + mLocked.pointerCaptureRequest.enable ? "Enabled" : "Disabled", + mLocked.pointerCaptureRequest.seq); } dump += "\n"; @@ -634,7 +635,7 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon outConfig->showTouches = mLocked.showTouches; - outConfig->pointerCapture = mLocked.pointerCapture; + outConfig->pointerCaptureRequest = mLocked.pointerCaptureRequest; outConfig->setDisplayViewports(mLocked.viewports); @@ -1383,16 +1384,16 @@ void NativeInputManager::onPointerDownOutsideFocus(const sp<IBinder>& touchedTok checkAndClearExceptionFromCallback(env, "onPointerDownOutsideFocus"); } -void NativeInputManager::setPointerCapture(bool enabled) { +void NativeInputManager::setPointerCapture(const PointerCaptureRequest& request) { { // acquire lock AutoMutex _l(mLock); - if (mLocked.pointerCapture == enabled) { + if (mLocked.pointerCaptureRequest == request) { return; } - ALOGV("%s pointer capture.", enabled ? "Enabling" : "Disabling"); - mLocked.pointerCapture = enabled; + ALOGV("%s pointer capture.", request.enable ? "Enabling" : "Disabling"); + mLocked.pointerCaptureRequest = request; } // release lock mInputManager->getReader()->requestRefreshConfiguration( diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 193d92a3b2ff..d48c9ea4831c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3599,6 +3599,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + Preconditions.checkCallAuthorization( + isCallingFromPackage(adminReceiver.getPackageName(), caller.getUid()) + || isSystemUid(caller)); synchronized (getLockObject()) { ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle); @@ -12694,74 +12697,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // This method is called from AM with its lock held, so don't take the DPMS lock. // b/29242568 - ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); - if (profileOwner != null) { - return DevicePolicyManagerService.this - .createShowAdminSupportIntent(profileOwner, userId); - } - - final Pair<Integer, ComponentName> deviceOwner = - mOwners.getDeviceOwnerUserIdAndComponent(); - if (deviceOwner != null && deviceOwner.first == userId) { - return DevicePolicyManagerService.this - .createShowAdminSupportIntent(deviceOwner.second, userId); - } - - // We're not specifying the device admin because there isn't one. - if (useDefaultIfNoAdmin) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent(null, userId); + if (getEnforcingAdminAndUserDetailsInternal(userId, null) != null + || useDefaultIfNoAdmin) { + return DevicePolicyManagerService.this.createShowAdminSupportIntent(userId); } return null; } @Override public Intent createUserRestrictionSupportIntent(int userId, String userRestriction) { - final long ident = mInjector.binderClearCallingIdentity(); - try { - final List<UserManager.EnforcingUser> sources = mUserManager - .getUserRestrictionSources(userRestriction, UserHandle.of(userId)); - if (sources == null || sources.isEmpty()) { - // The restriction is not enforced. - return null; - } else if (sources.size() > 1) { - // In this case, we'll show an admin support dialog that does not - // specify the admin. - // TODO(b/128928355): if this restriction is enforced by multiple DPCs, return - // the admin for the calling user. - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - null, userId); - } - final UserManager.EnforcingUser enforcingUser = sources.get(0); - final int sourceType = enforcingUser.getUserRestrictionSource(); - final int enforcingUserId = enforcingUser.getUserHandle().getIdentifier(); - if (sourceType == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) { - // Restriction was enforced by PO - final ComponentName profileOwner = mOwners.getProfileOwnerComponent( - enforcingUserId); - if (profileOwner != null) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - profileOwner, enforcingUserId); - } - } else if (sourceType == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) { - // Restriction was enforced by DO - final Pair<Integer, ComponentName> deviceOwner = - mOwners.getDeviceOwnerUserIdAndComponent(); - if (deviceOwner != null) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - deviceOwner.second, deviceOwner.first); - } - } else if (sourceType == UserManager.RESTRICTION_SOURCE_SYSTEM) { - /* - * In this case, the user restriction is enforced by the system. - * So we won't show an admin support intent, even if it is also - * enforced by a profile/device owner. - */ - return null; - } - } finally { - mInjector.binderRestoreCallingIdentity(ident); + Intent intent = null; + if (getEnforcingAdminAndUserDetailsInternal(userId, userRestriction) != null) { + intent = DevicePolicyManagerService.this.createShowAdminSupportIntent(userId); + intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, userRestriction); } - return null; + return intent; } @Override @@ -13056,53 +13006,153 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private Intent createShowAdminSupportIntent(ComponentName admin, int userId) { + private Intent createShowAdminSupportIntent(int userId) { // This method is called with AMS lock held, so don't take DPMS lock final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); intent.putExtra(Intent.EXTRA_USER_ID, userId); - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin); intent.setFlags(FLAG_ACTIVITY_NEW_TASK); return intent; } - @Override - public Intent createAdminSupportIntent(String restriction) { - Objects.requireNonNull(restriction); - final CallerIdentity caller = getCallerIdentity(); - Intent intent = null; - if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) || - DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + */ + private Bundle getEnforcingAdminAndUserDetailsInternal(int userId, String restriction) { + Bundle result = null; + if (restriction == null) { + ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); + if (profileOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + profileOwner); + return result; + } + final Pair<Integer, ComponentName> deviceOwner = + mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null && deviceOwner.first == userId) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + deviceOwner.second); + return result; + } + } else if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) + || DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { synchronized (getLockObject()) { - final DevicePolicyData policy = getUserData(caller.getUserId()); + final DevicePolicyData policy = getUserData(userId); final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { final ActiveAdmin admin = policy.mAdminList.get(i); if ((admin.disableCamera && - DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) || - (admin.disableScreenCapture && DevicePolicyManager - .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) { - intent = createShowAdminSupportIntent(admin.info.getComponent(), - caller.getUserId()); - break; + DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) + || (admin.disableScreenCapture && DevicePolicyManager + .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + admin.info.getComponent()); + return result; } } // For the camera, a device owner on a different user can disable it globally, // so we need an additional check. - if (intent == null + if (result == null && DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) { final ActiveAdmin admin = getDeviceOwnerAdminLocked(); if (admin != null && admin.disableCamera) { - intent = createShowAdminSupportIntent(admin.info.getComponent(), - mOwners.getDeviceOwnerUserId()); + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, mOwners.getDeviceOwnerUserId()); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + admin.info.getComponent()); + return result; } } } } else { - // if valid, |restriction| can only be a user restriction - intent = mLocalService.createUserRestrictionSupportIntent(caller.getUserId(), - restriction); + long ident = mInjector.binderClearCallingIdentity(); + try { + List<UserManager.EnforcingUser> sources = mUserManager + .getUserRestrictionSources(restriction, UserHandle.of(userId)); + if (sources == null || sources.isEmpty()) { + // The restriction is not enforced. + return null; + } else if (sources.size() > 1) { + // In this case, we'll show an admin support dialog that does not + // specify the admin. + // TODO(b/128928355): if this restriction is enforced by multiple DPCs, return + // the admin for the calling user. + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + return result; + } + final UserManager.EnforcingUser enforcingUser = sources.get(0); + final int sourceType = enforcingUser.getUserRestrictionSource(); + final int enforcingUserId = enforcingUser.getUserHandle().getIdentifier(); + if (sourceType == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) { + // Restriction was enforced by PO + final ComponentName profileOwner = mOwners.getProfileOwnerComponent( + enforcingUserId); + if (profileOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, enforcingUserId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + profileOwner); + return result; + } + } else if (sourceType == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) { + // Restriction was enforced by DO + final Pair<Integer, ComponentName> deviceOwner = + mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, deviceOwner.first); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + deviceOwner.second); + return result; + } + } else if (sourceType == UserManager.RESTRICTION_SOURCE_SYSTEM) { + /* + * In this case, the user restriction is enforced by the system. + * So we won't show an admin support intent, even if it is also + * enforced by a profile/device owner. + */ + return null; + } + } finally { + mInjector.binderRestoreCallingIdentity(ident); + } } - if (intent != null) { + return null; + } + + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + * @return Details of admin and user which enforced the restriction for the userId. + */ + @Override + public Bundle getEnforcingAdminAndUserDetails(int userId, String restriction) { + Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity())); + return getEnforcingAdminAndUserDetailsInternal(userId, restriction); + } + + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + */ + @Override + public Intent createAdminSupportIntent(String restriction) { + Objects.requireNonNull(restriction); + final CallerIdentity caller = getCallerIdentity(); + final int userId = caller.getUserId(); + Intent intent = null; + if (getEnforcingAdminAndUserDetailsInternal(userId, restriction) != null) { + intent = createShowAdminSupportIntent(userId); intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction); } return intent; @@ -14060,6 +14110,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + Preconditions.checkCallAuthorization(canManageUsers(caller)); Preconditions.checkCallAuthorization(isManagedProfile(userHandle), "You can not get organization name outside a managed profile, userId = %d", userHandle); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index c2885c848077..db6323c4100f 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -439,7 +439,6 @@ public final class SystemServer implements Dumpable { private static final String SYSPROP_START_UPTIME = "sys.system_server.start_uptime"; private Future<?> mZygotePreload; - private Future<?> mBlobStoreServiceStart; private final SystemServerDumper mDumper = new SystemServerDumper(); @@ -2287,12 +2286,9 @@ public final class SystemServer implements Dumpable { t.traceEnd(); } - mBlobStoreServiceStart = SystemServerInitThreadPool.submit(() -> { - final TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); - traceLog.traceBegin(START_BLOB_STORE_SERVICE); - mSystemServiceManager.startService(BLOB_STORE_MANAGER_SERVICE_CLASS); - traceLog.traceEnd(); - }, START_BLOB_STORE_SERVICE); + t.traceBegin(START_BLOB_STORE_SERVICE); + mSystemServiceManager.startService(BLOB_STORE_MANAGER_SERVICE_CLASS); + t.traceEnd(); // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode) t.traceBegin("StartDreamManager"); @@ -2706,9 +2702,6 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS); t.traceEnd(); - ConcurrentUtils.waitForFutureNoInterrupt(mBlobStoreServiceStart, - START_BLOB_STORE_SERVICE); - // These are needed to propagate to the runnable below. final NetworkManagementService networkManagementF = networkManagement; final NetworkStatsService networkStatsF = networkStats; diff --git a/services/net/Android.bp b/services/net/Android.bp index a822257e1a74..53ce6b264651 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -52,7 +52,6 @@ java_library { // classes generated by netd_aidl_interfaces-platform-java above. "netd_aidl_interface-V3-java", "networkstack-client", - "modules-utils-build_system", ], apex_available: [ "com.android.wifi", diff --git a/services/tests/PackageManager/packageinstaller/Android.bp b/services/tests/PackageManager/packageinstaller/Android.bp new file mode 100644 index 000000000000..35d754b4adc5 --- /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 000000000000..d7062587c4bc --- /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 000000000000..c39285ffca38 --- /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 000000000000..d7d2726c1583 --- /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 17a5dccb57da..3cab5ecd3de1 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/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camMute.xml b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camMute.xml new file mode 100644 index 000000000000..a4de08a85487 --- /dev/null +++ b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camMute.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<sensor-privacy persistence-version="1" version="1"> + <user id="0" enabled="false"> + <individual-sensor-privacy sensor="1" enabled="true" /> + <individual-sensor-privacy sensor="2" enabled="true" /> + </user> +</sensor-privacy> diff --git a/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camUnmute.xml b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camUnmute.xml new file mode 100644 index 000000000000..47649d7392e6 --- /dev/null +++ b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micMute_camUnmute.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<sensor-privacy persistence-version="1" version="1"> + <user id="0" enabled="false"> + <individual-sensor-privacy sensor="1" enabled="true" /> + <individual-sensor-privacy sensor="2" enabled="false" /> + </user> +</sensor-privacy> diff --git a/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camMute.xml b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camMute.xml new file mode 100644 index 000000000000..4fd9ebf98717 --- /dev/null +++ b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camMute.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<sensor-privacy persistence-version="1" version="1"> + <user id="0" enabled="false"> + <individual-sensor-privacy sensor="1" enabled="false" /> + <individual-sensor-privacy sensor="2" enabled="true" /> + </user> +</sensor-privacy> diff --git a/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camUnmute.xml b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camUnmute.xml new file mode 100644 index 000000000000..e8f9edfde2d7 --- /dev/null +++ b/services/tests/mockingservicestests/assets/SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camUnmute.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<sensor-privacy persistence-version="1" version="1"> + <user id="0" enabled="false"> + <individual-sensor-privacy sensor="1" enabled="false" /> + <individual-sensor-privacy sensor="2" enabled="false" /> + </user> +</sensor-privacy> diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java index 022fadcc6dd0..609768c0e62a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java @@ -21,12 +21,16 @@ import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import android.app.ActivityManager; +import android.app.IApplicationThread; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; +import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; @@ -48,8 +52,14 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import java.io.File; -import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -60,8 +70,11 @@ import java.util.concurrent.TimeUnit; * Build/Install/Run: * atest FrameworksMockingServicesTests:CacheOomRankerTest */ +@SuppressWarnings("GuardedBy") // No tests are concurrent, so no need to test locking. @RunWith(MockitoJUnitRunner.class) public class CacheOomRankerTest { + private static final Instant NOW = LocalDate.of(2021, 1, 1).atStartOfDay( + ZoneOffset.UTC).toInstant(); @Mock private AppOpsService mAppOpsService; @@ -82,6 +95,7 @@ public class CacheOomRankerTest { private int mNextUid = 30000; private int mNextPackageUid = 40000; private int mNextPackageName = 1; + private Map<Integer, Long> mPidToRss; private TestExecutor mExecutor = new TestExecutor(); private CacheOomRanker mCacheOomRanker; @@ -107,7 +121,15 @@ public class CacheOomRankerTest { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); - mCacheOomRanker = new CacheOomRanker(mAms); + mPidToRss = new HashMap<>(); + mCacheOomRanker = new CacheOomRanker( + mAms, + pid -> { + Long rss = mPidToRss.get(pid); + assertThat(rss).isNotNull(); + return new long[]{rss}; + } + ); mCacheOomRanker.init(mExecutor); } @@ -136,6 +158,15 @@ public class CacheOomRankerTest { mExecutor.init(); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + CacheOomRanker.KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS, + Integer.toString(CacheOomRanker.DEFAULT_PRESERVE_TOP_N_APPS + 1), + false); + mExecutor.waitForLatch(); + assertThat(mCacheOomRanker.mPreserveTopNApps) + .isEqualTo(CacheOomRanker.DEFAULT_PRESERVE_TOP_N_APPS + 1); + + mExecutor.init(); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT, Float.toString(CacheOomRanker.DEFAULT_OOM_RE_RANKING_LRU_WEIGHT + 0.1f), false); @@ -165,6 +196,9 @@ public class CacheOomRankerTest { @Test public void reRankLruCachedApps_lruImpactsOrdering() throws InterruptedException { setConfig(/* numberToReRank= */ 5, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, /* usesWeight= */ 0.0f, /* pssWeight= */ 0.0f, /* lruWeight= */1.0f); @@ -172,36 +206,40 @@ public class CacheOomRankerTest { ProcessList list = new ProcessList(); ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); ProcessRecord lastUsed40MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000); + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); processList.add(lastUsed40MinutesAgo); ProcessRecord lastUsed42MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(42).toMillis(), 20 * 1024L, 2000); + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); processList.add(lastUsed42MinutesAgo); ProcessRecord lastUsed60MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(60).toMillis(), 1024L, 10000); + NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 10000); processList.add(lastUsed60MinutesAgo); ProcessRecord lastUsed15MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(15).toMillis(), 100 * 1024L, 10); + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); processList.add(lastUsed15MinutesAgo); ProcessRecord lastUsed17MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(17).toMillis(), 1024L, 20); + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 20); processList.add(lastUsed17MinutesAgo); // Only re-ranking 5 entries so this should stay in most recent position. ProcessRecord lastUsed30MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 1024L, 20); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 20); processList.add(lastUsed30MinutesAgo); + list.setLruProcessServiceStartLSP(processList.size()); mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); // First 5 ordered by least recently used first, then last processes position unchanged. assertThat(processList).containsExactly(lastUsed60MinutesAgo, lastUsed42MinutesAgo, lastUsed40MinutesAgo, lastUsed17MinutesAgo, lastUsed15MinutesAgo, - lastUsed30MinutesAgo); + lastUsed30MinutesAgo).inOrder(); } @Test public void reRankLruCachedApps_rssImpactsOrdering() throws InterruptedException { setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, /* usesWeight= */ 0.0f, /* pssWeight= */ 1.0f, /* lruWeight= */ 0.0f); @@ -209,145 +247,459 @@ public class CacheOomRankerTest { ProcessList list = new ProcessList(); ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000); + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); processList.add(rss10k); ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(42).toMillis(), 20 * 1024L, 2000); + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); processList.add(rss20k); ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(60).toMillis(), 1024L, 10000); + NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 10000); processList.add(rss1k); ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(15).toMillis(), 100 * 1024L, 10); + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); processList.add(rss100k); ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(17).toMillis(), 2 * 1024L, 20); + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); processList.add(rss2k); ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 15 * 1024L, 20); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20); processList.add(rss15k); // Only re-ranking 6 entries so this should stay in most recent position. ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 16 * 1024L, 20); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20); processList.add(rss16k); + list.setLruProcessServiceStartLSP(processList.size()); mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); // First 6 ordered by largest pss, then last processes position unchanged. assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k, - rss16k); + rss16k).inOrder(); } @Test + public void reRankLruCachedApps_rssImpactsOrdering_cachedRssValues() + throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 10000000, + /* usesWeight= */ 0.0f, + /* pssWeight= */ 1.0f, + /* lruWeight= */ 0.0f); + + ProcessList list = new ProcessList(); + ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); + ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + processList.add(rss10k); + ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + processList.add(rss20k); + ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 10000); + processList.add(rss1k); + ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + processList.add(rss100k); + ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + processList.add(rss2k); + ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20); + processList.add(rss15k); + // Only re-ranking 6 entries so this should stay in most recent position. + ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20); + processList.add(rss16k); + list.setLruProcessServiceStartLSP(processList.size()); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + // First 6 ordered by largest pss, then last processes position unchanged. + assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k, + rss16k).inOrder(); + + // Clear mPidToRss so that Process.getRss calls fail. + mPidToRss.clear(); + // Mix up the process list to ensure that CacheOomRanker actually re-ranks. + Collections.swap(processList, 0, 1); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + // Re ranking is the same. + assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k, + rss16k).inOrder(); + } + + @Test + public void reRankLruCachedApps_rssImpactsOrdering_profileRss() + throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ false, + /* rssUpdateRateMs= */ 10000000, + /* usesWeight= */ 0.0f, + /* pssWeight= */ 1.0f, + /* lruWeight= */ 0.0f); + + ProcessList list = new ProcessList(); + ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); + ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 0L, 1000); + rss10k.mProfile.setLastRss(10 * 1024L); + processList.add(rss10k); + ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 0L, 2000); + rss20k.mProfile.setLastRss(20 * 1024L); + processList.add(rss20k); + ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10000); + rss1k.mProfile.setLastRss(1024L); + processList.add(rss1k); + ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10); + rss100k.mProfile.setLastRss(100 * 1024L); + processList.add(rss100k); + ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 0L, 20); + rss2k.mProfile.setLastRss(2 * 1024L); + processList.add(rss2k); + ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20); + rss15k.mProfile.setLastRss(15 * 1024L); + processList.add(rss15k); + // Only re-ranking 6 entries so this should stay in most recent position. + ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20); + rss16k.mProfile.setLastRss(16 * 1024L); + processList.add(rss16k); + list.setLruProcessServiceStartLSP(processList.size()); + + // This should not be used, as RSS values are taken from mProfile. + mPidToRss.clear(); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + // First 6 ordered by largest pss, then last processes position unchanged. + assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k, + rss16k).inOrder(); + + // Clear mPidToRss so that Process.getRss calls fail. + mPidToRss.clear(); + // Mix up the process list to ensure that CacheOomRanker actually re-ranks. + Collections.swap(processList, 0, 1); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + // Re ranking is the same. + assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k, + rss16k).inOrder(); + } + + + @Test public void reRankLruCachedApps_usesImpactsOrdering() throws InterruptedException { setConfig(/* numberToReRank= */ 4, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, /* usesWeight= */ 1.0f, /* pssWeight= */ 0.0f, /* lruWeight= */ 0.0f); ProcessList list = new ProcessList(); - list.setLruProcessServiceStartLSP(1); ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000); + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); processList.add(used1000); ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(42).toMillis(), 20 * 1024L, 2000); + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); processList.add(used2000); ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(15).toMillis(), 100 * 1024L, 10); + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); processList.add(used10); ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(17).toMillis(), 2 * 1024L, 20); + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); processList.add(used20); // Only re-ranking 6 entries so last two should stay in most recent position. ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 15 * 1024L, 500); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); processList.add(used500); ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 16 * 1024L, 200); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); processList.add(used200); + list.setLruProcessServiceStartLSP(processList.size()); mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); // First 4 ordered by uses, then last processes position unchanged. assertThat(processList).containsExactly(used10, used20, used1000, used2000, used500, - used200); + used200).inOrder(); } @Test - public void reRankLruCachedApps_notEnoughProcesses() throws InterruptedException { + public void reRankLruCachedApps_fewProcesses() throws InterruptedException { setConfig(/* numberToReRank= */ 4, - /* usesWeight= */ 0.5f, - /* pssWeight= */ 0.2f, - /* lruWeight= */ 0.3f); + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, + /* usesWeight= */ 1.0f, + /* pssWeight= */ 0.0f, + /* lruWeight= */ 0.0f); ProcessList list = new ProcessList(); ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); - ProcessRecord unknownAdj1 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000); - processList.add(unknownAdj1); - ProcessRecord unknownAdj2 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(42).toMillis(), 20 * 1024L, 2000); - processList.add(unknownAdj2); - ProcessRecord unknownAdj3 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(15).toMillis(), 100 * 1024L, 10); - processList.add(unknownAdj3); + ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + processList.add(used1000); + ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + processList.add(used2000); + ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + processList.add(used10); ProcessRecord foregroundAdj = nextProcessRecord(ProcessList.FOREGROUND_APP_ADJ, - Duration.ofMinutes(17).toMillis(), 2 * 1024L, 20); + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); processList.add(foregroundAdj); ProcessRecord serviceAdj = nextProcessRecord(ProcessList.SERVICE_ADJ, - Duration.ofMinutes(30).toMillis(), 15 * 1024L, 500); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); processList.add(serviceAdj); ProcessRecord systemAdj = nextProcessRecord(ProcessList.SYSTEM_ADJ, - Duration.ofMinutes(30).toMillis(), 16 * 1024L, 200); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); processList.add(systemAdj); + list.setLruProcessServiceStartLSP(processList.size()); - // 6 Processes but only 3 in eligible for cache so no re-ranking. mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); - // All positions unchanged. - assertThat(processList).containsExactly(unknownAdj1, unknownAdj2, unknownAdj3, - foregroundAdj, serviceAdj, systemAdj); + // 6 processes, only 3 in eligible for cache, so only those are re-ranked. + assertThat(processList).containsExactly(used10, used1000, used2000, + foregroundAdj, serviceAdj, systemAdj).inOrder(); } @Test - public void reRankLruCachedApps_notEnoughNonServiceProcesses() throws InterruptedException { + public void reRankLruCachedApps_fewNonServiceProcesses() throws InterruptedException { setConfig(/* numberToReRank= */ 4, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, /* usesWeight= */ 1.0f, /* pssWeight= */ 0.0f, /* lruWeight= */ 0.0f); ProcessList list = new ProcessList(); - list.setLruProcessServiceStartLSP(4); ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000); + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); processList.add(used1000); ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(42).toMillis(), 20 * 1024L, 2000); + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); processList.add(used2000); ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(15).toMillis(), 100 * 1024L, 10); + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + processList.add(used10); + ProcessRecord service1 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + processList.add(service1); + ProcessRecord service2 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); + processList.add(service2); + ProcessRecord service3 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); + processList.add(service3); + list.setLruProcessServiceStartLSP(3); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + + // Services unchanged, rest re-ranked. + assertThat(processList).containsExactly(used10, used1000, used2000, service1, service2, + service3).inOrder(); + } + + @Test + public void reRankLruCachedApps_manyProcessesThenFew() throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 0, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, + /* usesWeight= */ 1.0f, + /* pssWeight= */ 0.0f, + /* lruWeight= */ 0.0f); + + ProcessList set1List = new ProcessList(); + ArrayList<ProcessRecord> set1ProcessList = set1List.getLruProcessesLSP(); + ProcessRecord set1Used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + set1ProcessList.add(set1Used1000); + ProcessRecord set1Used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + set1ProcessList.add(set1Used2000); + ProcessRecord set1Used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + set1ProcessList.add(set1Used10); + ProcessRecord set1Uses20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + set1ProcessList.add(set1Uses20); + ProcessRecord set1Uses500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); + set1ProcessList.add(set1Uses500); + ProcessRecord set1Uses200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); + set1ProcessList.add(set1Uses200); + set1List.setLruProcessServiceStartLSP(set1ProcessList.size()); + + mCacheOomRanker.reRankLruCachedAppsLSP(set1ProcessList, + set1List.getLruProcessServiceStartLOSP()); + assertThat(set1ProcessList).containsExactly(set1Used10, set1Uses20, set1Uses200, + set1Uses500, set1Used1000, set1Used2000).inOrder(); + + ProcessList set2List = new ProcessList(); + ArrayList<ProcessRecord> set2ProcessList = set2List.getLruProcessesLSP(); + ProcessRecord set2Used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + set2ProcessList.add(set2Used1000); + ProcessRecord set2Used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + set2ProcessList.add(set2Used2000); + ProcessRecord set2Used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + set2ProcessList.add(set2Used10); + ProcessRecord set2ForegroundAdj = nextProcessRecord(ProcessList.FOREGROUND_APP_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + set2ProcessList.add(set2ForegroundAdj); + ProcessRecord set2ServiceAdj = nextProcessRecord(ProcessList.SERVICE_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); + set2ProcessList.add(set2ServiceAdj); + ProcessRecord set2SystemAdj = nextProcessRecord(ProcessList.SYSTEM_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); + set2ProcessList.add(set2SystemAdj); + set2List.setLruProcessServiceStartLSP(set2ProcessList.size()); + + mCacheOomRanker.reRankLruCachedAppsLSP(set2ProcessList, + set2List.getLruProcessServiceStartLOSP()); + assertThat(set2ProcessList).containsExactly(set2Used10, set2Used1000, set2Used2000, + set2ForegroundAdj, set2ServiceAdj, set2SystemAdj).inOrder(); + } + + @Test + public void reRankLruCachedApps_preservesTopNApps() throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 3, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, + /* usesWeight= */ 1.0f, + /* pssWeight= */ 0.0f, + /* lruWeight= */ 0.0f); + + ProcessList list = new ProcessList(); + ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); + ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + processList.add(used1000); + ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + processList.add(used2000); + ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + processList.add(used10); + // Preserving the top 3 processes, so these should not be re-ranked. + ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + processList.add(used20); + ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); + processList.add(used500); + ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); + processList.add(used200); + list.setLruProcessServiceStartLSP(processList.size()); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + + // First 3 ordered by uses, then last processes position unchanged. + assertThat(processList).containsExactly(used10, used1000, used2000, used20, used500, + used200).inOrder(); + } + + @Test + public void reRankLruCachedApps_preservesTopNApps_allAppsUnchanged() + throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ 100, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, + /* usesWeight= */ 1.0f, + /* pssWeight= */ 0.0f, + /* lruWeight= */ 0.0f); + + ProcessList list = new ProcessList(); + ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); + ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + processList.add(used1000); + ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + processList.add(used2000); + ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); processList.add(used10); ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(17).toMillis(), 2 * 1024L, 20); + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); processList.add(used20); ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 15 * 1024L, 500); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); processList.add(used500); ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, - Duration.ofMinutes(30).toMillis(), 16 * 1024L, 200); + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); processList.add(used200); + list.setLruProcessServiceStartLSP(processList.size()); mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); - // All positions unchanged. + // Nothing reordered, as we preserve the top 100 apps. assertThat(processList).containsExactly(used1000, used2000, used10, used20, used500, - used200); + used200).inOrder(); + } + + @Test + public void reRankLruCachedApps_preservesTopNApps_negativeReplacedWithDefault() + throws InterruptedException { + setConfig(/* numberToReRank= */ 6, + /* preserveTopNApps= */ -100, + /* useFrequentRss= */ true, + /* rssUpdateRateMs= */ 0, + /* usesWeight= */ 1.0f, + /* pssWeight= */ 0.0f, + /* lruWeight= */ 0.0f); + + ProcessList list = new ProcessList(); + ArrayList<ProcessRecord> processList = list.getLruProcessesLSP(); + ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000); + processList.add(used1000); + ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000); + processList.add(used2000); + ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10); + processList.add(used10); + // Negative preserveTopNApps interpreted as the default (3), so the last three are unranked. + ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20); + processList.add(used20); + ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500); + processList.add(used500); + ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ, + NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200); + processList.add(used200); + list.setLruProcessServiceStartLSP(processList.size()); + + mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP()); + + // First 3 apps re-ranked, as preserveTopNApps is interpreted as 3. + assertThat(processList).containsExactly(used10, used1000, used2000, used20, used500, + used200).inOrder(); } - private void setConfig(int numberToReRank, float useWeight, float pssWeight, float lruWeight) + private void setConfig(int numberToReRank, int preserveTopNApps, boolean useFrequentRss, + long rssUpdateRateMs, float usesWeight, float pssWeight, float lruWeight) throws InterruptedException { mExecutor.init(4); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -355,6 +707,18 @@ public class CacheOomRankerTest { Integer.toString(numberToReRank), false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + CacheOomRanker.KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS, + Integer.toString(preserveTopNApps), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + CacheOomRanker.KEY_OOM_RE_RANKING_USE_FREQUENT_RSS, + Boolean.toString(useFrequentRss), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + CacheOomRanker.KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS, + Long.toString(rssUpdateRateMs), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT, Float.toString(lruWeight), false); @@ -364,17 +728,19 @@ public class CacheOomRankerTest { false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CacheOomRanker.KEY_OOM_RE_RANKING_USES_WEIGHT, - Float.toString(useWeight), + Float.toString(usesWeight), false); mExecutor.waitForLatch(); assertThat(mCacheOomRanker.getNumberToReRank()).isEqualTo(numberToReRank); + assertThat(mCacheOomRanker.mUseFrequentRss).isEqualTo(useFrequentRss); + assertThat(mCacheOomRanker.mRssUpdateRateMs).isEqualTo(rssUpdateRateMs); assertThat(mCacheOomRanker.mRssWeight).isEqualTo(pssWeight); - assertThat(mCacheOomRanker.mUsesWeight).isEqualTo(useWeight); + assertThat(mCacheOomRanker.mUsesWeight).isEqualTo(usesWeight); assertThat(mCacheOomRanker.mLruWeight).isEqualTo(lruWeight); } private ProcessRecord nextProcessRecord(int setAdj, long lastActivityTime, long lastRss, - int returnedToCacheCount) { + int wentToForegroundCount) { ApplicationInfo ai = new ApplicationInfo(); ai.packageName = "a.package.name" + mNextPackageName++; ProcessRecord app = new ProcessRecord(mAms, ai, ai.packageName + ":process", mNextUid++); @@ -382,14 +748,20 @@ public class CacheOomRankerTest { app.info.uid = mNextPackageUid++; // Exact value does not mater, it can be any state for which compaction is allowed. app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); - app.mState.setSetAdj(setAdj); + app.mState.setCurAdj(setAdj); app.setLastActivityTime(lastActivityTime); - app.mProfile.setLastRss(lastRss); + mPidToRss.put(app.getPid(), lastRss); app.mState.setCached(false); - for (int i = 0; i < returnedToCacheCount; ++i) { - app.mState.setCached(false); - app.mState.setCached(true); + for (int i = 0; i < wentToForegroundCount; ++i) { + app.mState.setSetProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); + app.mState.setSetProcState(ActivityManager.PROCESS_STATE_CACHED_RECENT); } + // Sets the thread returned by ProcessRecord#getThread, which we use to check whether the + // app is currently launching. + ProcessStatsService processStatsService = new ProcessStatsService( + mock(ActivityManagerService.class), new File(Environment.getDataSystemCeDirectory(), + "procstats")); + app.makeActive(mock(IApplicationThread.class), processStatsService); return app; } diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java index 4d86c8716bf1..85ef8f73534c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java @@ -182,7 +182,14 @@ public class GameManagerServiceTests { } private void mockDeviceConfigPerformance() { - String configString = "mode=2,downscaleFactor=0.5"; + String configString = "mode=2,downscaleFactor=0.5,useAngle=false"; + when(DeviceConfig.getProperty(anyString(), anyString())) + .thenReturn(configString); + } + + // ANGLE will be disabled for most apps, so treat enabling ANGLE as a special case. + private void mockDeviceConfigPerformanceEnableAngle() { + String configString = "mode=2,downscaleFactor=0.5,useAngle=true"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); } @@ -200,7 +207,7 @@ public class GameManagerServiceTests { } private void mockDeviceConfigInvalid() { - String configString = "mode=2,downscaleFactor=0.55"; + String configString = ""; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); } @@ -212,7 +219,8 @@ public class GameManagerServiceTests { } private void mockGameModeOptInAll() throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); Bundle metaDataBundle = new Bundle(); metaDataBundle.putBoolean( GameManagerService.GamePackageConfiguration.METADATA_PERFORMANCE_MODE_ENABLE, true); @@ -224,7 +232,8 @@ public class GameManagerServiceTests { } private void mockGameModeOptInPerformance() throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); Bundle metaDataBundle = new Bundle(); metaDataBundle.putBoolean( GameManagerService.GamePackageConfiguration.METADATA_PERFORMANCE_MODE_ENABLE, true); @@ -234,7 +243,8 @@ public class GameManagerServiceTests { } private void mockGameModeOptInBattery() throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); Bundle metaDataBundle = new Bundle(); metaDataBundle.putBoolean( GameManagerService.GamePackageConfiguration.METADATA_BATTERY_MODE_ENABLE, true); @@ -244,7 +254,8 @@ public class GameManagerServiceTests { } private void mockInterventionAllowDownscaleTrue() throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); Bundle metaDataBundle = new Bundle(); metaDataBundle.putBoolean( GameManagerService.GamePackageConfiguration.METADATA_WM_ALLOW_DOWNSCALE, true); @@ -254,7 +265,8 @@ public class GameManagerServiceTests { } private void mockInterventionAllowDownscaleFalse() throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); Bundle metaDataBundle = new Bundle(); metaDataBundle.putBoolean( GameManagerService.GamePackageConfiguration.METADATA_WM_ALLOW_DOWNSCALE, false); @@ -263,6 +275,27 @@ public class GameManagerServiceTests { .thenReturn(applicationInfo); } + private void mockInterventionAllowAngleTrue() throws Exception { + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_ANGLE_ALLOW_ANGLE, true); + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + + private void mockInterventionAllowAngleFalse() throws Exception { + final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser( + mPackageName, PackageManager.GET_META_DATA, USER_ID_1); + Bundle metaDataBundle = new Bundle(); + metaDataBundle.putBoolean( + GameManagerService.GamePackageConfiguration.METADATA_ANGLE_ALLOW_ANGLE, false); + applicationInfo.metaData = metaDataBundle; + when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(applicationInfo); + } + /** * By default game mode is not supported. */ @@ -340,11 +373,12 @@ public class GameManagerServiceTests { */ @Test public void testSetGameModePermissionDenied() { + mockModifyGameModeGranted(); + mockDeviceConfigAll(); GameManagerService gameManagerService = new GameManagerService(mMockContext); gameManagerService.onUserStarting(USER_ID_1); // Update the game mode so we can read back something valid. - mockModifyGameModeGranted(); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1); assertEquals(GameManager.GAME_MODE_STANDARD, gameManagerService.getGameMode(mPackageName, USER_ID_1)); @@ -427,6 +461,19 @@ public class GameManagerServiceTests { assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling); } + private void checkAngleEnabled(GameManagerService gameManagerService, int gameMode, + boolean angleEnabled) { + gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName); + + // Validate GamePackageConfiguration returns the correct value. + GameManagerService.GamePackageConfiguration config = + gameManagerService.getConfig(mPackageName); + assertEquals(config.getGameModeConfiguration(gameMode).getUseAngle(), angleEnabled); + + // Validate GameManagerService.getAngleEnabled() returns the correct value. + assertEquals(gameManagerService.getAngleEnabled(mPackageName, USER_ID_1), angleEnabled); + } + /** * Phenotype device config exists, but is only propagating the default value. */ @@ -592,6 +639,50 @@ public class GameManagerServiceTests { } /** + * PERFORMANCE game mode is configured through Phenotype. The app hasn't specified any metadata. + */ + @Test + public void testInterventionAllowAngleDefault() throws Exception { + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.onUserStarting(USER_ID_1); + mockDeviceConfigPerformance(); + mockModifyGameModeGranted(); + checkAngleEnabled(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, false); + } + + /** + * PERFORMANCE game mode is configured through Phenotype. The app has opted-out of ANGLE. + */ + @Test + public void testInterventionAllowAngleFalse() throws Exception { + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.onUserStarting(USER_ID_1); + mockDeviceConfigPerformanceEnableAngle(); + mockInterventionAllowAngleFalse(); + mockModifyGameModeGranted(); + checkAngleEnabled(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, false); + } + + /** + * PERFORMANCE game mode is configured through Phenotype. The app has redundantly specified + * the ANGLE metadata default value of "true". + */ + @Test + public void testInterventionAllowAngleTrue() throws Exception { + mockDeviceConfigPerformanceEnableAngle(); + mockInterventionAllowAngleTrue(); + + GameManagerService gameManagerService = new GameManagerService(mMockContext); + gameManagerService.onUserStarting(USER_ID_1); + mockModifyGameModeGranted(); + gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); + assertEquals(GameManager.GAME_MODE_PERFORMANCE, + gameManagerService.getGameMode(mPackageName, USER_ID_1)); + + checkAngleEnabled(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, true); + } + + /** * PERFORMANCE game mode is configured through Phenotype, but the app has also opted into the * same mode. No interventions for this game mode should be available in this case. */ diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java index f703e2e59181..d0b2edadc714 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java @@ -906,6 +906,21 @@ public class LocationProviderManagerTest { } @Test + public void testProviderRequest_DelayedRequest_Remove() { + mProvider.setProviderLocation(createLocation(NAME, mRandom)); + + ILocationListener listener1 = createMockLocationListener(); + LocationRequest request1 = new LocationRequest.Builder(60000) + .setWorkSource(WORK_SOURCE) + .build(); + mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1); + mManager.unregisterLocationRequest(listener1); + + mInjector.getAlarmHelper().incrementAlarmTime(60000); + assertThat(mProvider.getRequest().isActive()).isFalse(); + } + + @Test public void testProviderRequest_SpamRequesting() { mProvider.setProviderLocation(createLocation(NAME, mRandom)); diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/StationaryThrottlingLocationProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/StationaryThrottlingLocationProviderTest.java index 63996f0e021c..4d6f49e5d223 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/StationaryThrottlingLocationProviderTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/StationaryThrottlingLocationProviderTest.java @@ -90,7 +90,7 @@ public class StationaryThrottlingLocationProviderTest { } @Test - public void testThrottle() { + public void testThrottle_stationaryExit() { ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build(); mProvider.getController().setRequest(request); @@ -113,6 +113,29 @@ public class StationaryThrottlingLocationProviderTest { } @Test + public void testThrottle_idleExit() { + ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build(); + + mProvider.getController().setRequest(request); + verify(mDelegate).onSetRequest(request); + + mDelegateProvider.reportLocation(createLocationResult("test_provider", mRandom)); + verify(mListener, times(1)).onReportLocation(any(LocationResult.class)); + + mInjector.getDeviceIdleHelper().setIdle(true); + verify(mDelegate, never()).onSetRequest(ProviderRequest.EMPTY_REQUEST); + + mInjector.getDeviceStationaryHelper().setStationary(true); + verify(mDelegate).onSetRequest(ProviderRequest.EMPTY_REQUEST); + verify(mListener, timeout(75).times(2)).onReportLocation(any(LocationResult.class)); + verify(mListener, timeout(75).times(3)).onReportLocation(any(LocationResult.class)); + + mInjector.getDeviceIdleHelper().setIdle(false); + verify(mDelegate, times(2)).onSetRequest(request); + verify(mListener, after(75).times(3)).onReportLocation(any(LocationResult.class)); + } + + @Test public void testThrottle_NoInitialLocation() { ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build(); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt index 7a6110bdbda3..f17fa625d007 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackagesBroadcastTest.kt @@ -79,8 +79,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10003)) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), any(), nullable()) @@ -97,8 +97,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, allowList(10001, 10002, 10007)) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms, times(2)).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), any(), nullable()) @@ -118,8 +118,8 @@ class SuspendPackagesBroadcastTest { mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) mockAllowList(packageSetting2, null) - pms.sendPackagesSuspendedForUser( - packagesToSuspend, uidsToSuspend, TEST_USER_ID, /* suspended = */ true) + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENDED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) verify(pms, times(2)).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) @@ -133,6 +133,22 @@ class SuspendPackagesBroadcastTest { } } + @Test + @Throws(Exception::class) + fun sendPackagesSuspendModifiedForUser() { + pms.sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, + packagesToSuspend, uidsToSuspend, TEST_USER_ID) + verify(pms).sendPackageBroadcast( + eq(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED), nullable(), bundleCaptor.capture(), + anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) + + var modifiedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST) + var modifiedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST) + assertThat(modifiedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2) + assertThat(modifiedUids).asList().containsExactly( + packageSetting1.appId, packageSetting2.appId) + } + private fun allowList(vararg uids: Int) = SparseArray<IntArray>().apply { this.put(TEST_USER_ID, uids) } 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 000000000000..f94377fe51c2 --- /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/mockingservicestests/src/com/android/server/sensorprivacy/SensorPrivacyServiceMockingTest.java b/services/tests/mockingservicestests/src/com/android/server/sensorprivacy/SensorPrivacyServiceMockingTest.java index ba79a764b672..38f01b5acc0c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/sensorprivacy/SensorPrivacyServiceMockingTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/sensorprivacy/SensorPrivacyServiceMockingTest.java @@ -16,12 +16,18 @@ package com.android.server.sensorprivacy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; + import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.AppOpsManager; +import android.app.AppOpsManagerInternal; import android.content.Context; import android.content.pm.UserInfo; import android.os.Environment; @@ -33,8 +39,10 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.server.LocalServices; import com.android.server.SensorPrivacyService; +import com.android.server.SystemService; import com.android.server.pm.UserManagerInternal; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -44,6 +52,7 @@ import org.mockito.quality.Strictness; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.concurrent.CompletableFuture; @RunWith(AndroidTestingRunner.class) public class SensorPrivacyServiceMockingTest { @@ -63,10 +72,21 @@ public class SensorPrivacyServiceMockingTest { public static final String PERSISTENCE_FILE6 = String.format(PERSISTENCE_FILE_PATHS_TEMPLATE, 6); + public static final String PERSISTENCE_FILE_MIC_MUTE_CAM_MUTE = + "SensorPrivacyServiceMockingTest/persisted_file_micMute_camMute.xml"; + public static final String PERSISTENCE_FILE_MIC_MUTE_CAM_UNMUTE = + "SensorPrivacyServiceMockingTest/persisted_file_micMute_camUnmute.xml"; + public static final String PERSISTENCE_FILE_MIC_UNMUTE_CAM_MUTE = + "SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camMute.xml"; + public static final String PERSISTENCE_FILE_MIC_UNMUTE_CAM_UNMUTE = + "SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camUnmute.xml"; + private Context mContext; @Mock private AppOpsManager mMockedAppOpsManager; @Mock + private AppOpsManagerInternal mMockedAppOpsManagerInternal; + @Mock private UserManagerInternal mMockedUserManagerInternal; @Mock private ActivityManager mMockedActivityManager; @@ -134,13 +154,103 @@ public class SensorPrivacyServiceMockingTest { } } + @Test + public void testServiceInit_AppOpsRestricted_micMute_camMute() throws IOException { + testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_MUTE_CAM_MUTE, true, true); + } + + @Test + public void testServiceInit_AppOpsRestricted_micMute_camUnmute() throws IOException { + testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_MUTE_CAM_UNMUTE, true, false); + } + + @Test + public void testServiceInit_AppOpsRestricted_micUnmute_camMute() throws IOException { + testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_UNMUTE_CAM_MUTE, false, true); + } + + @Test + public void testServiceInit_AppOpsRestricted_micUnmute_camUnmute() throws IOException { + testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_UNMUTE_CAM_UNMUTE, false, false); + } + + private void testServiceInit_AppOpsRestricted(String persistenceFileMicMuteCamMute, + boolean expectedMicState, boolean expectedCamState) + throws IOException { + MockitoSession mockitoSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .strictness(Strictness.WARN) + .spyStatic(LocalServices.class) + .spyStatic(Environment.class) + .startMocking(); + + try { + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + spyOn(mContext); + + doReturn(mMockedAppOpsManager).when(mContext).getSystemService(AppOpsManager.class); + doReturn(mMockedAppOpsManagerInternal) + .when(() -> LocalServices.getService(AppOpsManagerInternal.class)); + doReturn(mMockedUserManagerInternal) + .when(() -> LocalServices.getService(UserManagerInternal.class)); + doReturn(mMockedActivityManager).when(mContext).getSystemService(ActivityManager.class); + doReturn(mMockedActivityTaskManager) + .when(mContext).getSystemService(ActivityTaskManager.class); + doReturn(mMockedTelephonyManager).when(mContext).getSystemService( + TelephonyManager.class); + + String dataDir = mContext.getApplicationInfo().dataDir; + doReturn(new File(dataDir)).when(() -> Environment.getDataSystemDirectory()); + + File onDeviceFile = new File(dataDir, "sensor_privacy.xml"); + onDeviceFile.delete(); + + doReturn(new int[]{0}).when(mMockedUserManagerInternal).getUserIds(); + doReturn(ExtendedMockito.mock(UserInfo.class)).when(mMockedUserManagerInternal) + .getUserInfo(0); + + CompletableFuture<Boolean> micState = new CompletableFuture<>(); + CompletableFuture<Boolean> camState = new CompletableFuture<>(); + doAnswer(invocation -> { + int code = invocation.getArgument(0); + boolean restricted = invocation.getArgument(1); + if (code == AppOpsManager.OP_RECORD_AUDIO) { + micState.complete(restricted); + } else if (code == AppOpsManager.OP_CAMERA) { + camState.complete(restricted); + } + return null; + }).when(mMockedAppOpsManagerInternal).setGlobalRestriction(anyInt(), anyBoolean(), + any()); + + initServiceWithPersistenceFile(onDeviceFile, persistenceFileMicMuteCamMute, 0); + + Assert.assertTrue(micState.join() == expectedMicState); + Assert.assertTrue(camState.join() == expectedCamState); + + } finally { + mockitoSession.finishMocking(); + } + } + private void initServiceWithPersistenceFile(File onDeviceFile, String persistenceFilePath) throws IOException { + initServiceWithPersistenceFile(onDeviceFile, persistenceFilePath, -1); + } + + private void initServiceWithPersistenceFile(File onDeviceFile, + String persistenceFilePath, int startingUserId) throws IOException { if (persistenceFilePath != null) { Files.copy(mContext.getAssets().open(persistenceFilePath), onDeviceFile.toPath()); } - new SensorPrivacyService(mContext); + SensorPrivacyService service = new SensorPrivacyService(mContext); + if (startingUserId != -1) { + SystemService.TargetUser mockedTargetUser = + ExtendedMockito.mock(SystemService.TargetUser.class); + doReturn(startingUserId).when(mockedTargetUser).getUserIdentifier(); + service.onUserStarting(mockedTargetUser); + } onDeviceFile.delete(); } } diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java index 53483f6d70bc..a49afc75c739 100644 --- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java @@ -18,13 +18,18 @@ package com.android.server.wallpaper; import static android.app.WallpaperManager.COMMAND_REAPPLY; import static android.app.WallpaperManager.FLAG_SYSTEM; +import static android.os.FileObserver.CLOSE_WRITE; +import static android.os.UserHandle.USER_SYSTEM; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER; +import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_CROP; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; @@ -34,6 +39,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeThat; 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.reset; @@ -41,6 +47,7 @@ import static org.mockito.Mockito.verify; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.WallpaperColors; import android.app.WallpaperManager; import android.content.ComponentName; import android.content.Context; @@ -49,8 +56,10 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; +import android.graphics.Color; import android.hardware.display.DisplayManager; -import android.os.UserHandle; +import android.os.RemoteException; +import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; @@ -143,7 +152,6 @@ public class WallpaperManagerServiceTests { sContext.getTestablePermissions().setPermission( android.Manifest.permission.SET_WALLPAPER, PackageManager.PERMISSION_GRANTED); - doNothing().when(sContext).sendBroadcastAsUser(any(), any()); //Wallpaper components sWallpaperService = mock(IWallpaperConnection.Stub.class); @@ -180,6 +188,7 @@ public class WallpaperManagerServiceTests { MockitoAnnotations.initMocks(this); sContext.addMockSystemService(DisplayManager.class, mDisplayManager); + doNothing().when(sContext).sendBroadcastAsUser(any(), any()); final Display mockDisplay = mock(Display.class); doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension(); @@ -242,13 +251,13 @@ public class WallpaperManagerServiceTests { */ @Test public void testDataCorrectAfterBoot() { - mService.switchUser(UserHandle.USER_SYSTEM, null); + mService.switchUser(USER_SYSTEM, null); final WallpaperData fallbackData = mService.mFallbackWallpaper; assertEquals("Fallback wallpaper component should be ImageWallpaper.", sImageWallpaperComponentName, fallbackData.wallpaperComponent); - verifyLastWallpaperData(UserHandle.USER_SYSTEM, sDefaultWallpaperComponent); + verifyLastWallpaperData(USER_SYSTEM, sDefaultWallpaperComponent); verifyDisplayData(); } @@ -261,7 +270,7 @@ public class WallpaperManagerServiceTests { assumeThat(sDefaultWallpaperComponent, not(CoreMatchers.equalTo(sImageWallpaperComponentName))); - final int testUserId = UserHandle.USER_SYSTEM; + final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); @@ -281,7 +290,7 @@ public class WallpaperManagerServiceTests { */ @Test public void testSetCurrentComponent() throws Exception { - final int testUserId = UserHandle.USER_SYSTEM; + final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); @@ -387,6 +396,42 @@ public class WallpaperManagerServiceTests { assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors); } + @Test + public void testWallpaperManagerCallbackInRightOrder() throws RemoteException { + WallpaperData wallpaper = new WallpaperData( + USER_SYSTEM, mService.getWallpaperDir(USER_SYSTEM), WALLPAPER, WALLPAPER_CROP); + wallpaper.primaryColors = new WallpaperColors(Color.valueOf(Color.RED), + Color.valueOf(Color.BLUE), null); + + spyOn(wallpaper); + doReturn(wallpaper).when(mService).getWallpaperSafeLocked(wallpaper.userId, FLAG_SYSTEM); + doNothing().when(mService).switchWallpaper(any(), any()); + doReturn(true).when(mService) + .bindWallpaperComponentLocked(any(), anyBoolean(), anyBoolean(), any(), any()); + doNothing().when(mService).saveSettingsLocked(wallpaper.userId); + doNothing().when(mService).generateCrop(wallpaper); + + // timestamps of {ACTION_WALLPAPER_CHANGED, onWallpaperColorsChanged} + final long[] timestamps = new long[2]; + doAnswer(invocation -> timestamps[0] = SystemClock.elapsedRealtime()) + .when(sContext).sendBroadcastAsUser(any(), any()); + doAnswer(invocation -> timestamps[1] = SystemClock.elapsedRealtime()) + .when(mService).notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM); + + assertNull(wallpaper.wallpaperObserver); + mService.switchUser(wallpaper.userId, null); + assertNotNull(wallpaper.wallpaperObserver); + // We will call onEvent directly, so stop watching the file. + wallpaper.wallpaperObserver.stopWatching(); + + spyOn(wallpaper.wallpaperObserver); + doReturn(wallpaper).when(wallpaper.wallpaperObserver).dataForEvent(true, false); + wallpaper.wallpaperObserver.onEvent(CLOSE_WRITE, WALLPAPER); + + // ACTION_WALLPAPER_CHANGED should be invoked before onWallpaperColorsChanged. + assertTrue(timestamps[1] > timestamps[0]); + } + // Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for // non-current user must not bind to wallpaper service. private void verifyNoConnectionBeforeLastUser(int lastUserId) { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java index 2892bf58a7d2..b3f7587df612 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java @@ -74,6 +74,7 @@ import java.util.function.Consumer; public class AuthSessionTest { private static final String TEST_PACKAGE = "test_package"; + private static final long TEST_REQUEST_ID = 22; @Mock private Context mContext; @Mock private ITrustManager mTrustManager; @@ -112,6 +113,7 @@ public class AuthSessionTest { final AuthSession session = createAuthSession(mSensors, false /* checkDevicePolicyManager */, Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, 0 /* operationId */, 0 /* userId */); @@ -133,6 +135,7 @@ public class AuthSessionTest { final AuthSession session = createAuthSession(mSensors, false /* checkDevicePolicyManager */, Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, operationId, userId); assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); @@ -153,6 +156,7 @@ public class AuthSessionTest { eq(userId), eq(mSensorReceiver), eq(TEST_PACKAGE), + eq(TEST_REQUEST_ID), eq(sensor.getCookie()), anyBoolean() /* allowBackgroundAuthentication */); } @@ -185,6 +189,33 @@ public class AuthSessionTest { } @Test + public void testCancelReducesAppetiteForCookies() throws Exception { + setupFace(0 /* id */, false /* confirmationAlwaysRequired */, + mock(IBiometricAuthenticator.class)); + setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); + + final AuthSession session = createAuthSession(mSensors, + false /* checkDevicePolicyManager */, + Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, + 44 /* operationId */, + 2 /* userId */); + + session.goToInitialState(); + + for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { + assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); + } + + session.onCancelAuthSession(false /* force */); + + for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { + session.onCookieReceived(sensor.getCookie()); + assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState()); + } + } + + @Test public void testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes() throws Exception { setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); @@ -212,6 +243,7 @@ public class AuthSessionTest { final AuthSession session = createAuthSession(mSensors, false /* checkDevicePolicyManager */, Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, operationId, userId); assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); @@ -238,7 +270,7 @@ public class AuthSessionTest { // fingerprint sensor does not start even if all cookies are received assertEquals(STATE_AUTH_STARTED, session.getState()); verify(mStatusBarService).showAuthenticationDialog(any(), any(), any(), - anyBoolean(), anyBoolean(), anyInt(), any(), anyLong(), anyInt()); + anyBoolean(), anyBoolean(), anyInt(), anyLong(), any(), anyLong(), anyInt()); // Notify AuthSession that the UI is shown. Then, fingerprint sensor should be started. session.onDialogAnimatedIn(); @@ -277,6 +309,7 @@ public class AuthSessionTest { final AuthSession session = createAuthSession(mSensors, false /* checkDevicePolicyManager */, Authenticators.BIOMETRIC_STRONG, + TEST_REQUEST_ID, 0 /* operationId */, 0 /* userId */); @@ -285,7 +318,8 @@ public class AuthSessionTest { sessionConsumer.accept(session); - verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE)); + verify(faceAuthenticator).cancelAuthenticationFromService( + eq(mToken), eq(TEST_PACKAGE), eq(TEST_REQUEST_ID)); } private PreAuthInfo createPreAuthInfo(List<BiometricSensor> sensors, int userId, @@ -302,14 +336,14 @@ public class AuthSessionTest { private AuthSession createAuthSession(List<BiometricSensor> sensors, boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, - long operationId, int userId) throws RemoteException { + long requestId, long operationId, int userId) throws RemoteException { final PromptInfo promptInfo = createPromptInfo(authenticators); final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo, checkDevicePolicyManager); return new AuthSession(mContext, mStatusBarService, mSysuiReceiver, mKeyStore, - mRandom, mClientDeathReceiver, preAuthInfo, mToken, operationId, userId, + mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId, operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo, false /* debugEnabled */, mFingerprintSensorProps); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index 7c7afb7dde36..69d8e89ac3b3 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -85,6 +85,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; @Presubmit @SmallTest @@ -93,6 +94,7 @@ public class BiometricServiceTest { private static final String TAG = "BiometricServiceTest"; private static final String TEST_PACKAGE_NAME = "test_package"; + private static final long TEST_REQUEST_ID = 44; private static final String ERROR_HW_UNAVAILABLE = "hw_unavailable"; private static final String ERROR_NOT_RECOGNIZED = "not_recognized"; @@ -151,6 +153,7 @@ public class BiometricServiceTest { .thenReturn(mock(BiometricStrengthController.class)); when(mInjector.getTrustManager()).thenReturn(mTrustManager); when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager); + when(mInjector.getRequestGenerator()).thenReturn(new AtomicLong(TEST_REQUEST_ID - 1)); when(mResources.getString(R.string.biometric_error_hw_unavailable)) .thenReturn(ERROR_HW_UNAVAILABLE); @@ -215,8 +218,7 @@ public class BiometricServiceTest { mBiometricService.mCurrentAuthSession.getState()); verify(mBiometricService.mCurrentAuthSession.mPreAuthInfo.eligibleSensors.get(0).impl) - .cancelAuthenticationFromService(any(), - any()); + .cancelAuthenticationFromService(any(), any(), anyLong()); // Simulate ERROR_CANCELED received from HAL mBiometricService.mBiometricSensorReceiver.onError( @@ -272,8 +274,9 @@ public class BiometricServiceTest { eq(true) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -357,8 +360,9 @@ public class BiometricServiceTest { eq(false) /* credentialAllowed */, eq(false) /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -467,6 +471,7 @@ public class BiometricServiceTest { anyInt() /* userId */, any(IBiometricSensorReceiver.class), anyString() /* opPackageName */, + eq(TEST_REQUEST_ID), cookieCaptor.capture() /* cookie */, anyBoolean() /* allowBackgroundAuthentication */); @@ -488,8 +493,9 @@ public class BiometricServiceTest { eq(false) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); // Hardware authenticated @@ -543,8 +549,9 @@ public class BiometricServiceTest { eq(true) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -705,8 +712,9 @@ public class BiometricServiceTest { anyBoolean() /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, anyString(), - anyLong() /* sessionId */, + anyLong() /* requestId */, eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -805,8 +813,9 @@ public class BiometricServiceTest { eq(true) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -885,8 +894,9 @@ public class BiometricServiceTest { eq(true) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(TEST_REQUEST_ID), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -1030,8 +1040,7 @@ public class BiometricServiceTest { eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), eq(0 /* vendorCode */)); verify(mBiometricService.mSensors.get(0).impl).cancelAuthenticationFromService( - any(), - any()); + any(), any(), anyLong()); assertNull(mBiometricService.mCurrentAuthSession); } @@ -1051,7 +1060,7 @@ public class BiometricServiceTest { waitForIdle(); verify(mBiometricService.mSensors.get(0).impl) - .cancelAuthenticationFromService(any(), any()); + .cancelAuthenticationFromService(any(), any(), anyLong()); } @Test @@ -1071,7 +1080,7 @@ public class BiometricServiceTest { waitForIdle(); verify(mBiometricService.mSensors.get(0).impl) - .cancelAuthenticationFromService(any(), any()); + .cancelAuthenticationFromService(any(), any(), anyLong()); } @Test @@ -1088,7 +1097,7 @@ public class BiometricServiceTest { waitForIdle(); verify(mBiometricService.mSensors.get(0).impl) - .cancelAuthenticationFromService(any(), any()); + .cancelAuthenticationFromService(any(), any(), anyLong()); verify(mReceiver1).onError( eq(BiometricAuthenticator.TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), @@ -1126,7 +1135,7 @@ public class BiometricServiceTest { false /* requireConfirmation */, null /* authenticators */); mBiometricService.mImpl.cancelAuthentication(mBiometricService.mCurrentAuthSession.mToken, - TEST_PACKAGE_NAME); + TEST_PACKAGE_NAME, TEST_REQUEST_ID); waitForIdle(); // Pretend that the HAL has responded to cancel with ERROR_CANCELED @@ -1353,8 +1362,8 @@ public class BiometricServiceTest { int authenticators = Authenticators.BIOMETRIC_STRONG; assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, invokeCanAuthenticate(mBiometricService, authenticators)); - invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, - authenticators); + long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + false /* requireConfirmation */, authenticators); waitForIdle(); verify(mReceiver1).onError( eq(BiometricAuthenticator.TYPE_FINGERPRINT), @@ -1366,7 +1375,7 @@ public class BiometricServiceTest { authenticators = Authenticators.BIOMETRIC_WEAK; assertEquals(BiometricManager.BIOMETRIC_SUCCESS, invokeCanAuthenticate(mBiometricService, authenticators)); - invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, + requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, authenticators); waitForIdle(); @@ -1377,8 +1386,9 @@ public class BiometricServiceTest { eq(false) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(requestId), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); // Requesting strong and credential, when credential is setup @@ -1387,7 +1397,7 @@ public class BiometricServiceTest { when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true); assertEquals(BiometricManager.BIOMETRIC_SUCCESS, invokeCanAuthenticate(mBiometricService, authenticators)); - invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, authenticators); waitForIdle(); @@ -1399,8 +1409,9 @@ public class BiometricServiceTest { eq(true) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(requestId), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); // Un-downgrading the authenticator allows successful strong auth @@ -1414,7 +1425,7 @@ public class BiometricServiceTest { authenticators = Authenticators.BIOMETRIC_STRONG; assertEquals(BiometricManager.BIOMETRIC_SUCCESS, invokeCanAuthenticate(mBiometricService, authenticators)); - invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, + requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, authenticators); waitForIdle(); verify(mBiometricService.mStatusBarService).showAuthenticationDialog( @@ -1424,8 +1435,9 @@ public class BiometricServiceTest { eq(false) /* credentialAllowed */, anyBoolean() /* requireConfirmation */, anyInt() /* userId */, + anyLong() /* operationId */, eq(TEST_PACKAGE_NAME), - anyLong() /* sessionId */, + eq(requestId), eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); } @@ -1617,11 +1629,12 @@ public class BiometricServiceTest { mBiometricService.mStatusBarService = mock(IStatusBarService.class); } - private void invokeAuthenticateAndStart(IBiometricService.Stub service, + private long invokeAuthenticateAndStart(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators) throws Exception { // Request auth, creates a pending session - invokeAuthenticate(service, receiver, requireConfirmation, authenticators); + final long requestId = invokeAuthenticate( + service, receiver, requireConfirmation, authenticators); waitForIdle(); startPendingAuthSession(mBiometricService); @@ -1629,6 +1642,8 @@ public class BiometricServiceTest { assertNotNull(mBiometricService.mCurrentAuthSession); assertEquals(STATE_AUTH_STARTED, mBiometricService.mCurrentAuthSession.getState()); + + return requestId; } private static void startPendingAuthSession(BiometricService service) throws Exception { @@ -1644,10 +1659,10 @@ public class BiometricServiceTest { service.mImpl.onReadyForAuthentication(cookie); } - private static void invokeAuthenticate(IBiometricService.Stub service, + private static long invokeAuthenticate(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators) throws Exception { - service.authenticate( + return service.authenticate( new Binder() /* token */, 0 /* operationId */, 0 /* userId */, @@ -1657,9 +1672,9 @@ public class BiometricServiceTest { false /* checkDevicePolicy */)); } - private static void invokeAuthenticateForWorkApp(IBiometricService.Stub service, + private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service, IBiometricServiceReceiver receiver, Integer authenticators) throws Exception { - service.authenticate( + return service.authenticate( new Binder() /* token */, 0 /* operationId */, 0 /* userId */, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index a41f79e8f682..e3e3900c47e0 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -40,6 +40,7 @@ import android.platform.test.annotations.Presubmit; import android.testing.TestableContext; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -193,7 +194,7 @@ public class BiometricSchedulerTest { // Request it to be canceled. The operation can be canceled immediately, and the scheduler // should go back to idle, since in this case the framework has not even requested the HAL // to authenticate yet. - mScheduler.cancelAuthenticationOrDetection(mToken); + mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */); assertNull(mScheduler.mCurrentOperation); } @@ -303,7 +304,7 @@ public class BiometricSchedulerTest { mScheduler.mPendingOperations.getFirst().mState); // Request cancel before the authentication client has started - mScheduler.cancelAuthenticationOrDetection(mToken); + mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */); waitForIdle(); assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING, mScheduler.mPendingOperations.getFirst().mState); @@ -318,6 +319,107 @@ public class BiometricSchedulerTest { } @Test + public void testCancels_whenAuthRequestIdNotSet() { + testCancelsWhenRequestId(null /* requestId */, 2, true /* started */); + } + + @Test + public void testCancels_whenAuthRequestIdNotSet_notStarted() { + testCancelsWhenRequestId(null /* requestId */, 2, false /* started */); + } + + @Test + public void testCancels_whenAuthRequestIdMatches() { + testCancelsWhenRequestId(200L, 200, true /* started */); + } + + @Test + public void testCancels_whenAuthRequestIdMatches_noStarted() { + testCancelsWhenRequestId(200L, 200, false /* started */); + } + + @Test + public void testDoesNotCancel_whenAuthRequestIdMismatched() { + testCancelsWhenRequestId(10L, 20, true /* started */); + } + + @Test + public void testDoesNotCancel_whenAuthRequestIdMismatched_notStarted() { + testCancelsWhenRequestId(10L, 20, false /* started */); + } + + private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId, + boolean started) { + final boolean matches = requestId == null || requestId == cancelRequestId; + final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class); + final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); + final TestAuthenticationClient client = new TestAuthenticationClient( + mContext, lazyDaemon, mToken, callback); + if (requestId != null) { + client.setRequestId(requestId); + } + + mScheduler.scheduleClientMonitor(client); + if (started) { + mScheduler.startPreparedClient(client.getCookie()); + } + waitForIdle(); + mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId); + waitForIdle(); + + assertEquals(matches && started ? 1 : 0, client.mNumCancels); + + if (matches) { + if (started) { + assertEquals(Operation.STATE_STARTED_CANCELING, + mScheduler.mCurrentOperation.mState); + } + } else { + if (started) { + assertEquals(Operation.STATE_STARTED, + mScheduler.mCurrentOperation.mState); + } else { + assertEquals(Operation.STATE_WAITING_FOR_COOKIE, + mScheduler.mCurrentOperation.mState); + } + } + } + + @Test + public void testCancelsPending_whenAuthRequestIdsSet() { + final long requestId1 = 10; + final long requestId2 = 20; + final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class); + final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); + final TestAuthenticationClient client1 = new TestAuthenticationClient( + mContext, lazyDaemon, mToken, callback); + client1.setRequestId(requestId1); + final TestAuthenticationClient client2 = new TestAuthenticationClient( + mContext, lazyDaemon, mToken, callback); + client2.setRequestId(requestId2); + + mScheduler.scheduleClientMonitor(client1); + mScheduler.scheduleClientMonitor(client2); + mScheduler.startPreparedClient(client1.getCookie()); + waitForIdle(); + mScheduler.cancelAuthenticationOrDetection(mToken, 9999); + waitForIdle(); + + assertEquals(Operation.STATE_STARTED, + mScheduler.mCurrentOperation.mState); + assertEquals(Operation.STATE_WAITING_IN_QUEUE, + mScheduler.mPendingOperations.getFirst().mState); + + mScheduler.cancelAuthenticationOrDetection(mToken, requestId2); + waitForIdle(); + + assertEquals(Operation.STATE_STARTED, + mScheduler.mCurrentOperation.mState); + assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING, + mScheduler.mPendingOperations.getFirst().mState); + } + + @Test public void testInterruptPrecedingClients_whenExpected() { final BaseClientMonitor interruptableMonitor = mock(BaseClientMonitor.class, withSettings().extraInterfaces(Interruptable.class)); @@ -377,12 +479,10 @@ public class BiometricSchedulerTest { @Override protected void stopHalOperation() { - } @Override protected void startHalOperation() { - } @Override @@ -397,6 +497,7 @@ public class BiometricSchedulerTest { } private static class TestAuthenticationClient extends AuthenticationClient<Object> { + int mNumCancels = 0; public TestAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token, @@ -428,6 +529,11 @@ public class BiometricSchedulerTest { public boolean wasUserDetected() { return false; } + + public void cancel() { + mNumCancels++; + super.cancel(); + } } private static class TestClientMonitor2 extends TestClientMonitor { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java new file mode 100644 index 000000000000..09b5c5cac466 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java @@ -0,0 +1,52 @@ +/* + * 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.biometrics.sensors; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +@Presubmit +@SmallTest +public class CompositeCallbackTest { + + @Test + public void testNullCallback() { + BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class); + BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class); + BaseClientMonitor.Callback callback3 = null; + + BaseClientMonitor.CompositeCallback callback = new BaseClientMonitor.CompositeCallback( + callback1, callback2, callback3); + + BaseClientMonitor clientMonitor = mock(BaseClientMonitor.class); + + callback.onClientStarted(clientMonitor); + verify(callback1).onClientStarted(eq(clientMonitor)); + verify(callback2).onClientStarted(eq(clientMonitor)); + + callback.onClientFinished(clientMonitor, true /* success */); + verify(callback1).onClientFinished(eq(clientMonitor), eq(true)); + verify(callback2).onClientFinished(eq(clientMonitor), eq(true)); + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java new file mode 100644 index 000000000000..38e8dfa45262 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java @@ -0,0 +1,104 @@ +/* + * 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.biometrics.sensors.fingerprint; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.hardware.fingerprint.FingerprintStateListener; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import com.android.server.biometrics.sensors.AuthenticationClient; +import com.android.server.biometrics.sensors.EnrollClient; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@Presubmit +@SmallTest +public class FingerprintStateCallbackTest { + + private FingerprintStateCallback mCallback; + + @Mock + FingerprintStateListener mFingerprintStateListener; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + mCallback = new FingerprintStateCallback(); + mCallback.registerFingerprintStateListener(mFingerprintStateListener); + } + + @Test + public void testNoEnrollmentsToEnrollments_callbackNotified() { + testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */, + true /* expectCallback */, true /* expectedCallbackValue */); + } + + @Test + public void testEnrollmentsToNoEnrollments_callbackNotified() { + testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */, + true /* expectCallback */, false /* expectedCallbackValue */); + } + + @Test + public void testEnrollmentsToEnrollments_callbackNotNotified() { + testEnrollmentCallback(false /* changed */, true /* isNowEnrolled */, + false /* expectCallback */, false /* expectedCallbackValue */); + } + + private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled, + boolean expectCallback, boolean expectedCallbackValue) { + EnrollClient<?> client = mock(EnrollClient.class); + + final int userId = 10; + final int sensorId = 100; + + when(client.hasEnrollmentStateChanged()).thenReturn(changed); + when(client.hasEnrollments()).thenReturn(isNowEnrolled); + when(client.getTargetUserId()).thenReturn(userId); + when(client.getSensorId()).thenReturn(sensorId); + + mCallback.onClientFinished(client, true /* success */); + if (expectCallback) { + verify(mFingerprintStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId), + eq(expectedCallbackValue)); + } else { + verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), + anyBoolean()); + } + } + + @Test + public void testAuthentication_enrollmentCallbackNeverNotified() { + AuthenticationClient<?> client = mock(AuthenticationClient.class); + mCallback.onClientFinished(client, true /* success */); + verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), + anyBoolean()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java index 35c37efa16b4..b51918e24b13 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java @@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutResetDispatcher; +import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import org.junit.Before; @@ -58,6 +59,8 @@ public class FingerprintProviderTest { private UserManager mUserManager; @Mock private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; + @Mock + private FingerprintStateCallback mFingerprintStateCallback; private SensorProps[] mSensorProps; private LockoutResetDispatcher mLockoutResetDispatcher; @@ -87,8 +90,8 @@ public class FingerprintProviderTest { mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); - mFingerprintProvider = new TestableFingerprintProvider(mContext, mSensorProps, TAG, - mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + mFingerprintProvider = new TestableFingerprintProvider(mContext, mFingerprintStateCallback, + mSensorProps, TAG, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } @SuppressWarnings("rawtypes") @@ -133,11 +136,12 @@ public class FingerprintProviderTest { private static class TestableFingerprintProvider extends FingerprintProvider { public TestableFingerprintProvider(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { - super(context, props, halInstanceName, lockoutResetDispatcher, + super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher, gestureAvailabilityDispatcher); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java index 0a0dcc97272b..f6b92097a9fb 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java @@ -41,6 +41,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.LockoutResetDispatcher; +import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import org.junit.Before; import org.junit.Test; @@ -67,6 +68,8 @@ public class Fingerprint21Test { Fingerprint21.HalResultController mHalResultController; @Mock private BiometricScheduler mScheduler; + @Mock + private FingerprintStateCallback mFingerprintStateCallback; private LockoutResetDispatcher mLockoutResetDispatcher; private Fingerprint21 mFingerprint21; @@ -96,8 +99,9 @@ public class Fingerprint21Test { componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN, resetLockoutRequiresHardwareAuthToken); - mFingerprint21 = new TestableFingerprint21(mContext, sensorProps, mScheduler, - new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController); + mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps, + mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, + mHalResultController); } @Test @@ -118,11 +122,13 @@ public class Fingerprint21Test { private static class TestableFingerprint21 extends Fingerprint21 { TestableFingerprint21(@NonNull Context context, + @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller) { - super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); + super(context, fingerprintStateCallback, sensorProps, scheduler, handler, + lockoutResetDispatcher, controller); } @Override diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 7b20bf0f6bc7..3ac30d0258a5 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -2960,9 +2960,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(intent.getAction()).isEqualTo(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1)) .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID)); - assertThat( - (ComponentName) intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN)) - .isEqualTo(admin1); assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION)) .isEqualTo(UserManager.DISALLOW_ADJUST_VOLUME); @@ -2999,7 +2996,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION)) .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA); assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1)) - .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID)); + .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_UID)); // ScreenCapture should not be disabled by device owner intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE); assertThat(intent).isNull(); @@ -7753,6 +7750,12 @@ public class DevicePolicyManagerTest extends DpmTestBase { DpmMockContext.CALLER_SYSTEM_USER_UID, admin1.getPackageName(), MODE_DEFAULT); } + @Test + public void testGetOrganizationNameForUser_calledByNonPrivilegedApp_throwsException() { + assertExpectException(SecurityException.class, "Calling identity is not authorized", + () -> dpm.getOrganizationNameForUser(UserHandle.USER_SYSTEM)); + } + private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index 0dd5c61121db..c1569ce51270 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -26,6 +26,7 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_R import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE; import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE; +import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID; import static com.google.common.truth.Truth.assertThat; @@ -74,6 +75,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.util.Preconditions; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; @@ -110,6 +112,7 @@ public class DisplayModeDirectorTest { private static final boolean DEBUG = false; private static final float FLOAT_TOLERANCE = 0.01f; private static final int DISPLAY_ID = 0; + private static final float TRANSITION_POINT = 0.763f; private Context mContext; private FakesInjector mInjector; @@ -751,19 +754,27 @@ public class DisplayModeDirectorTest { director.start(sensorManager); - ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor<DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), + any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED + | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); + DisplayListener displayListener = displayListenerCaptor.getValue(); + + ArgumentCaptor<SensorEventListener> sensorListenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) .registerListener( - listenerCaptor.capture(), + sensorListenerCaptor.capture(), eq(lightSensor), anyInt(), any(Handler.class)); - SensorEventListener listener = listenerCaptor.getValue(); + SensorEventListener sensorListener = sensorListenerCaptor.getValue(); - setBrightness(10); + setBrightness(10, 10, displayListener); // Sensor reads 20 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/)); Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertVoteForRefreshRate(vote, 90 /*fps*/); @@ -771,9 +782,11 @@ public class DisplayModeDirectorTest { assertThat(vote).isNotNull(); assertThat(vote.disableRefreshRateSwitching).isTrue(); - setBrightness(125); + // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this + // parameter to the necessary threshold + setBrightness(10, 125, displayListener); // Sensor reads 1000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/)); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertThat(vote).isNull(); @@ -799,6 +812,14 @@ public class DisplayModeDirectorTest { director.start(sensorManager); + ArgumentCaptor<DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), + any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED + | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); + DisplayListener displayListener = displayListenerCaptor.getValue(); + ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) @@ -807,20 +828,22 @@ public class DisplayModeDirectorTest { eq(lightSensor), anyInt(), any(Handler.class)); - SensorEventListener listener = listenerCaptor.getValue(); + SensorEventListener sensorListener = listenerCaptor.getValue(); - setBrightness(100); + setBrightness(100, 100, displayListener); // Sensor reads 2000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertThat(vote).isNull(); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); assertThat(vote).isNull(); - setBrightness(255); + // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this + // parameter to the necessary threshold + setBrightness(100, 255, displayListener); // Sensor reads 9000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertVoteForRefreshRate(vote, 60 /*fps*/); @@ -1435,16 +1458,58 @@ public class DisplayModeDirectorTest { Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); - // Turn on HBM + // Turn on HBM, with brightness in the HBM range when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR)); + new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, hbmRefreshRate); + // Turn on HBM, with brightness below the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM, with brightness in the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertVoteForRefreshRate(vote, hbmRefreshRate); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM, with brightness below the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1514,7 +1579,8 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, initialRefreshRate); @@ -1531,14 +1597,16 @@ public class DisplayModeDirectorTest { // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); // Turn HBM on again and ensure the updated vote value stuck when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, updatedRefreshRate); @@ -1553,7 +1621,8 @@ public class DisplayModeDirectorTest { // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1584,14 +1653,16 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1600,7 +1671,7 @@ public class DisplayModeDirectorTest { private void setHbmAndAssertRefreshRate( DisplayModeDirector director, DisplayListener listener, int mode, float rr) { when(mInjector.getBrightnessInfo(DISPLAY_ID)) - .thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode)); + .thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); @@ -1655,6 +1726,72 @@ public class DisplayModeDirectorTest { } @Test + public void testHbmVoting_HbmUnsupported() { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + + ArgumentCaptor<DisplayListener> captor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS + | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); + DisplayListener listener = captor.getValue(); + + // Specify Limitation + when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( + List.of(new RefreshRateLimitation( + DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, + 60.0f, 60.0f))); + + // Verify that there is no HBM vote initially + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM when HBM is supported; expect a valid transition point and a vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertVoteForRefreshRate(vote, 60.0f); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on Sunlight HBM when HBM is unsupported; expect an invalid transition point and + // no vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + HBM_TRANSITION_POINT_INVALID)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HDR HBM when HBM is unsupported; expect an invalid transition point and + // no vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, + HBM_TRANSITION_POINT_INVALID)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + } + + @Test public void testHbmVoting_RemovedDisplay() { DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); @@ -1679,7 +1816,8 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, 60.f); @@ -1834,11 +1972,14 @@ public class DisplayModeDirectorTest { } } - private void setBrightness(int brightness) { - Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, - brightness); - mInjector.notifyBrightnessChanged(); - waitForIdleSync(); + private void setBrightness(int brightness, int adjustedBrightness, DisplayListener listener) { + float floatBri = BrightnessSynchronizer.brightnessIntToFloat(brightness); + float floatAdjBri = BrightnessSynchronizer.brightnessIntToFloat(adjustedBrightness); + + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); } private void setPeakRefreshRate(float fps) { @@ -1902,27 +2043,6 @@ public class DisplayModeDirectorTest { } @Override - public void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - if (mBrightnessObserver != null) { - throw new IllegalStateException("Tried to register a second brightness observer"); - } - mBrightnessObserver = observer; - } - - @Override - public void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - mBrightnessObserver = null; - } - - void notifyBrightnessChanged() { - if (mBrightnessObserver != null) { - mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI); - } - } - - @Override public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { mPeakRefreshRateObserver = observer; diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java index cc3591c89560..aca863299b33 100644 --- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java @@ -20,6 +20,8 @@ import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT; +import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.spy; @@ -124,6 +126,7 @@ public class HighBrightnessModeControllerTest { mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); + assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f); } @Test @@ -135,6 +138,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); + assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f); } @Test diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java index acd3fcab5e52..3261dfaa95c9 100644 --- a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java @@ -125,7 +125,7 @@ public class LegacyPermissionManagerServiceTest { public void checkDeviceIdentifierAccess_hasPrivilegedPermission_returnsGranted() { // Apps with the READ_PRIVILEGED_PHONE_STATE permission should have access to device // identifiers. - setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID); + setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID); when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, APP_PID, APP_UID)).thenReturn(PackageManager.PERMISSION_GRANTED); @@ -140,7 +140,7 @@ public class LegacyPermissionManagerServiceTest { public void checkDeviceIdentifierAccess_hasAppOp_returnsGranted() { // Apps that have been granted the READ_DEVICE_IDENTIFIERS appop should have access to // device identifiers. - setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID); + setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID); when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS), eq(APP_UID), eq(mPackageName), any(), any())).thenReturn( AppOpsManager.MODE_ALLOWED); @@ -156,7 +156,7 @@ public class LegacyPermissionManagerServiceTest { public void checkDeviceIdentifierAccess_hasDpmAccess_returnsGranted() { // Apps that pass a DevicePolicyManager device / profile owner check should have access to // device identifiers. - setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID); + setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID); when(mDevicePolicyManager.hasDeviceIdentifierAccess(mPackageName, APP_PID, APP_UID)).thenReturn(true); @@ -236,7 +236,7 @@ public class LegacyPermissionManagerServiceTest { // both the permission and the appop must be granted. If the permission is granted but the // appop is not then AppOpsManager#MODE_IGNORED should be returned to indicate that this // should be a silent failure. - setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID); + setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID); setPackageTargetSdk(Build.VERSION_CODES.Q); grantPermissionAndAppop(android.Manifest.permission.READ_PHONE_STATE, null); @@ -256,7 +256,7 @@ public class LegacyPermissionManagerServiceTest { // Apps targeting R+ with just the READ_PHONE_STATE permission granted should not have // access to the phone number; PERMISSION_DENIED should be returned both with and without // the appop granted since this check should be skipped for target SDK R+. - setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID); + setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID); grantPermissionAndAppop(android.Manifest.permission.READ_PHONE_STATE, null); int resultWithoutAppop = mLegacyPermissionManagerService.checkPhoneNumberAccess( @@ -319,12 +319,79 @@ public class LegacyPermissionManagerServiceTest { assertEquals(PackageManager.PERMISSION_GRANTED, resultWithAppop); } + @Test + public void checkPhoneNumberAccess_providedUidDoesNotMatchPackageUid_throwsException() + throws Exception { + // An app can directly interact with one of the services that accepts a package name and + // returns a protected resource via a direct binder transact. This app could then provide + // the name of another app that targets pre-R, then determine if the app is installed based + // on whether the service throws an exception or not. While the app can provide the package + // name of another app, it cannot specify the package uid which is passed to the + // LegacyPermissionManager using Binder#getCallingUid. Ultimately this uid should then be + // compared against the actual uid of the package to ensure information about packages + // installed on the device is not leaked. + setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID, APP_UID + 1); + + assertThrows(SecurityException.class, + () -> mLegacyPermissionManagerService.checkPhoneNumberAccess(mPackageName, + CHECK_PHONE_NUMBER_MESSAGE, null, APP_PID, APP_UID)); + } + + @Test + public void checkPhoneNumberAccess_nullPackageNameSystemUid_returnsGranted() throws Exception { + // The platform can pass a null package name when checking if the platform itself has + // access to the device phone number(s) / identifier(s). This test ensures if a null package + // is provided, then the package uid check is skipped and the test is based on whether the + // the provided uid / pid has been granted the privileged permission. + setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID, -1); + when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + SYSTEM_PID, SYSTEM_UID)).thenReturn(PackageManager.PERMISSION_GRANTED); + + int result = mLegacyPermissionManagerService.checkPhoneNumberAccess(null, + CHECK_PHONE_NUMBER_MESSAGE, null, SYSTEM_PID, SYSTEM_UID); + + assertEquals(PackageManager.PERMISSION_GRANTED, result); + } + + @Test + public void checkPhoneNumberAccess_systemUidMismatchPackageUid_returnsGranted() + throws Exception { + // When the platform is checking device phone number / identifier access checks for other + // components on the platform, a uid less than the first application UID is provided; this + // test verifies the package uid check is skipped and access is still granted with the + // privileged permission. + int telephonyUid = SYSTEM_UID + 1; + int telephonyPid = SYSTEM_PID + 1; + setupCheckPhoneNumberAccessTest(SYSTEM_PID, SYSTEM_UID, -1); + when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + telephonyPid, telephonyUid)).thenReturn(PackageManager.PERMISSION_GRANTED); + + int result = mLegacyPermissionManagerService.checkPhoneNumberAccess(mPackageName, + CHECK_PHONE_NUMBER_MESSAGE, null, telephonyPid, telephonyUid); + + assertEquals(PackageManager.PERMISSION_GRANTED, result); + } + /** * Configures device identifier access tests to fail; tests verifying access should individually * set an access check to succeed to verify access when that condition is met. */ private void setupCheckDeviceIdentifierAccessTest(int callingPid, int callingUid) { - setupAccessTest(callingPid, callingUid); + setupCheckDeviceIdentifierAccessTest(callingPid, callingUid, callingUid); + } + + /** + * Configures device identifier access tests to fail; tests verifying access should individually + * set an access check to succeed to verify access when that condition is met. + * + * <p>To prevent leaking package information, access checks for package UIDs >= {@link + * android.os.Process#FIRST_APPLICATION_UID} must ensure the provided uid matches the uid of + * the package being checked; to ensure this check is successful, this method accepts the + * {@code packageUid} to be used for the package being checked. + */ + public void setupCheckDeviceIdentifierAccessTest(int callingPid, int callingUid, + int packageUid) { + setupAccessTest(callingPid, callingUid, packageUid); when(mDevicePolicyManager.hasDeviceIdentifierAccess(anyString(), anyInt(), anyInt())).thenReturn(false); @@ -333,11 +400,26 @@ public class LegacyPermissionManagerServiceTest { } /** + * Configures phone number access tests to fail; tests verifying access should individually + * set an access check to succeed to verify access when that condition is set. + * + */ + private void setupCheckPhoneNumberAccessTest(int callingPid, int callingUid) throws Exception { + setupCheckPhoneNumberAccessTest(callingPid, callingUid, callingUid); + } + + /** * Configures phone number access tests to fail; tests verifying access should individually set * an access check to succeed to verify access when that condition is met. + * + * <p>To prevent leaking package information, access checks for package UIDs >= {@link + * android.os.Process#FIRST_APPLICATION_UID} must ensure the provided uid matches the uid of + * the package being checked; to ensure this check is successful, this method accepts the + * {@code packageUid} to be used for the package being checked. */ - private void setupCheckPhoneNumberAccessTest(int callingPid, int callingUid) throws Exception { - setupAccessTest(callingPid, callingUid); + private void setupCheckPhoneNumberAccessTest(int callingPid, int callingUid, int packageUid) + throws Exception { + setupAccessTest(callingPid, callingUid, packageUid); setPackageTargetSdk(Build.VERSION_CODES.R); } @@ -345,9 +427,10 @@ public class LegacyPermissionManagerServiceTest { * Configures the common mocks for any access tests using the provided {@code callingPid} * and {@code callingUid}. */ - private void setupAccessTest(int callingPid, int callingUid) { + private void setupAccessTest(int callingPid, int callingUid, int packageUid) { when(mInjector.getCallingPid()).thenReturn(callingPid); when(mInjector.getCallingUid()).thenReturn(callingUid); + when(mInjector.getPackageUidForUser(anyString(), anyInt())).thenReturn(packageUid); when(mInjector.checkPermission(anyString(), anyInt(), anyInt())).thenReturn( PackageManager.PERMISSION_DENIED); 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 5012ca9ab420..6e3f754e4882 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 @@ public class NotifierTest { @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 @@ public class NotifierTest { 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 5eabc1bea148..3d64d4b5abb9 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 @@ public class PowerManagerServiceTest { @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/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java b/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java index 11554c7a7dc5..6334e9d3cdc5 100644 --- a/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java @@ -82,6 +82,8 @@ public class UwbServiceImplTest { MockitoAnnotations.initMocks(this); when(mUwbInjector.getVendorService()).thenReturn(mVendorService); when(mUwbInjector.checkUwbRangingPermissionForDataDelivery(any(), any())).thenReturn(true); + when(mUwbInjector.isPersistedUwbStateEnabled()).thenReturn(true); + when(mUwbInjector.isAirplaneModeOn()).thenReturn(false); when(mVendorService.asBinder()).thenReturn(mVendorServiceBinder); mUwbServiceImpl = new UwbServiceImpl(mContext, mUwbInjector); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 71c05b5c46f7..ea46eab6e8f9 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -32,6 +32,7 @@ import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; @@ -72,6 +73,7 @@ import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.test.suitebuilder.annotation.SmallTest; +import android.util.Slog; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManager; @@ -1182,6 +1184,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); mService.buzzBeepBlinkLocked(r); + verifyDelayedVibrate(mService.getVibratorHelper().createFallbackVibration(false)); // quiet update should stop making noise mService.buzzBeepBlinkLocked(s); @@ -1564,6 +1567,32 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { } @Test + public void testRingtoneInsistentBeep_canUpdate() throws Exception { + NotificationChannel ringtoneChannel = + new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); + ringtoneChannel.setSound(Uri.fromParts("a", "b", "c"), + new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build()); + ringtoneChannel.enableVibration(true); + NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true); + mService.addNotification(ringtoneNotification); + assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); + mService.buzzBeepBlinkLocked(ringtoneNotification); + verifyBeepLooped(); + verifyDelayedVibrateLooped(); + Mockito.reset(mVibrator); + Mockito.reset(mRingtonePlayer); + + assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification)); + mService.buzzBeepBlinkLocked(ringtoneNotification); + + // beep wasn't reset + verifyNeverBeep(); + verifyNeverVibrate(); + verify(mRingtonePlayer, never()).stopAsync(); + verify(mVibrator, never()).cancel(); + } + + @Test public void testCannotInterruptRingtoneInsistentBuzz() { NotificationChannel ringtoneChannel = new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index f9663f200b56..987236c7c98c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -65,6 +65,7 @@ import com.google.android.collect.Lists; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -1320,16 +1321,15 @@ public class ManagedServicesTest extends UiServiceTestCase { APPROVAL_BY_COMPONENT); ComponentName cn = ComponentName.unflattenFromString("a/a"); - service.registerSystemService(cn, 0); - when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { - Object[] args = invocation.getArguments(); - ServiceConnection sc = (ServiceConnection) args[1]; - sc.onNullBinding(cn); - return true; - }); + ArgumentCaptor<ServiceConnection> captor = ArgumentCaptor.forClass(ServiceConnection.class); + when(context.bindServiceAsUser(any(), captor.capture(), anyInt(), any())) + .thenAnswer(invocation -> { + captor.getValue().onNullBinding(cn); + return true; + }); service.registerSystemService(cn, 0); - assertFalse(service.isBound(cn, 0)); + verify(context).unbindService(captor.getValue()); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index f57c416e4a97..1ae219db7726 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -516,7 +516,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); - mWorkerHandler = mService.new WorkerHandler(mTestableLooper.getLooper()); + mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper())); mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm, @@ -2703,6 +2703,42 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCrossUserSnooze() { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); + mService.addNotification(r); + NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); + mService.addNotification(r2); + + mListener = mock(ManagedServices.ManagedServiceInfo.class); + mListener.component = new ComponentName(PKG, PKG); + when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + + mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener); + + verify(mWorkerHandler, never()).post( + any(NotificationManagerService.SnoozeNotificationRunnable.class)); + } + + @Test + public void testSameUserSnooze() { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10); + mService.addNotification(r); + NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0); + mService.addNotification(r2); + + mListener = mock(ManagedServices.ManagedServiceInfo.class); + mListener.component = new ComponentName(PKG, PKG); + when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + + mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener); + + verify(mWorkerHandler).post( + any(NotificationManagerService.SnoozeNotificationRunnable.class)); + } + + @Test public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception { final NotificationRecord notification = generateNotificationRecord( mTestNotificationChannel, 1, null, true); @@ -3975,6 +4011,80 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testApplyAdjustmentsLogged() throws Exception { + NotificationManagerService.WorkerHandler handler = mock( + NotificationManagerService.WorkerHandler.class); + mService.setHandler(handler); + when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); + + // Set up notifications that will be adjusted + final NotificationRecord r1 = generateNotificationRecord( + mTestNotificationChannel, 1, null, true); + r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); + mService.addNotification(r1); + final NotificationRecord r2 = generateNotificationRecord( + mTestNotificationChannel, 2, null, true); + r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); + mService.addNotification(r2); + + // Third notification that's NOT adjusted, just to make sure that doesn't get spuriously + // logged. + final NotificationRecord r3 = generateNotificationRecord( + mTestNotificationChannel, 3, null, true); + r3.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); + mService.addNotification(r3); + + List<Adjustment> adjustments = new ArrayList<>(); + + // Test an adjustment that's associated with a ranking change and one that's not + Bundle signals1 = new Bundle(); + signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_HIGH); + Adjustment adjustment1 = new Adjustment( + r1.getSbn().getPackageName(), r1.getKey(), signals1, "", + r1.getUser().getIdentifier()); + adjustments.add(adjustment1); + + // This one wouldn't trigger a ranking change, but should still trigger a log. + Bundle signals2 = new Bundle(); + signals2.putFloat(Adjustment.KEY_RANKING_SCORE, -0.5f); + Adjustment adjustment2 = new Adjustment( + r2.getSbn().getPackageName(), r2.getKey(), signals2, "", + r2.getUser().getIdentifier()); + adjustments.add(adjustment2); + + mBinderService.applyAdjustmentsFromAssistant(null, adjustments); + verify(mRankingHandler, times(1)).requestSort(); + + // Actually apply the adjustments & recalculate importance when run + doAnswer(invocationOnMock -> { + ((NotificationRecord) invocationOnMock.getArguments()[0]) + .applyAdjustments(); + ((NotificationRecord) invocationOnMock.getArguments()[0]) + .calculateImportance(); + return null; + }).when(mRankingHelper).extractSignals(any(NotificationRecord.class)); + + // Now make sure that when the sort happens, we actually log the changes. + mService.handleRankingSort(); + + // Even though the ranking score change is not meant to trigger a ranking update, + // during this process the package visibility & canShowBadge values are changing + // in all notifications, so all 3 seem to trigger a ranking change. Here we check instead + // that scheduleSendRankingUpdate is sent and that the relevant fields have been changed + // accordingly to confirm the adjustments happened to the 2 relevant notifications. + verify(handler, times(3)).scheduleSendRankingUpdate(); + assertEquals(IMPORTANCE_HIGH, r1.getImportance()); + assertTrue(r2.rankingScoreMatches(-0.5f)); + assertEquals(2, mNotificationRecordLogger.numCalls()); + assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED, + mNotificationRecordLogger.event(0)); + assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED, + mNotificationRecordLogger.event(1)); + assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); + assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId()); + } + + @Test public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addEnqueuedNotification(r); @@ -4793,6 +4903,52 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testSetNotificationsShownFromListener_protectsCrossUserInformation() + throws RemoteException { + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), + null, 0); + final NotificationRecord r = + new NotificationRecord(mContext, sbn, mTestNotificationChannel); + r.setTextChanged(true); + mService.addNotification(r); + + // no security exception! + mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()}); + + verify(mAppUsageStats, never()).reportInterruptiveNotification( + anyString(), anyString(), anyInt()); + } + + @Test + public void testCancelNotificationsFromListener_protectsCrossUserInformation() + throws RemoteException { + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "tag" + System.currentTimeMillis(), UserHandle.PER_USER_RANGE, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE), + null, 0); + final NotificationRecord r = + new NotificationRecord(mContext, sbn, mTestNotificationChannel); + r.setTextChanged(true); + mService.addNotification(r); + + // no security exception! + mBinderService.cancelNotificationsFromListener(null, new String[] {r.getKey()}); + + waitForIdle(); + assertEquals(1, mService.getNotificationRecordCount()); + } + + @Test public void testMaybeRecordInterruptionLocked_doesNotRecordTwice() throws RemoteException { final NotificationRecord r = generateNotificationRecord( diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java index 64fd19e69009..8a11798bbf19 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java @@ -45,6 +45,15 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger { groupInstanceId = groupId; } + CallRecord(NotificationRecord r, int position, int buzzBeepBlink, InstanceId groupId) { + super(r, null); + this.position = position; + this.buzzBeepBlink = buzzBeepBlink; + wasLogged = true; + event = NotificationReportedEvent.NOTIFICATION_ADJUSTED; + groupInstanceId = groupId; + } + CallRecord(NotificationRecord r, UiEventLogger.UiEventEnum event) { super(r, null); wasLogged = true; @@ -75,6 +84,12 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger { } @Override + public void logNotificationAdjusted(NotificationRecord r, int position, int buzzBeepBlink, + InstanceId groupId) { + mCalls.add(new CallRecord(r, position, buzzBeepBlink, groupId)); + } + + @Override public void log(UiEventLogger.UiEventEnum event, NotificationRecord r) { mCalls.add(new CallRecord(r, event)); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index bf0ed713e4c3..66d157708332 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -91,6 +91,7 @@ import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.service.notification.ConversationChannelWrapper; @@ -376,27 +377,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(mPm.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); } - private static NotificationChannel createNotificationChannel(String id, String name, - int importance) { - NotificationChannel channel = new NotificationChannel(id, name, importance); - channel.setSound(SOUND_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT); - return channel; - } - @Test public void testWriteXml_onlyBackupsTargetUser() throws Exception { // Setup package notifications. String package0 = "test.package.user0"; int uid0 = 1001; setUpPackageWithUid(package0, uid0); - NotificationChannel channel0 = createNotificationChannel("id0", "name0", IMPORTANCE_HIGH); + NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); String package10 = "test.package.user10"; int uid10 = 1001001; setUpPackageWithUid(package10, uid10); - NotificationChannel channel10 = createNotificationChannel("id10", "name10", - IMPORTANCE_HIGH); + NotificationChannel channel10 = new NotificationChannel("id10", "name10", IMPORTANCE_HIGH); assertTrue(mHelper.createNotificationChannel(package10, uid10, channel10, true, false)); ByteArrayOutputStream baos = writeXmlAndPurge(package10, uid10, true, 10); @@ -421,7 +414,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { String package0 = "test.package.user0"; int uid0 = 1001; setUpPackageWithUid(package0, uid0); - NotificationChannel channel0 = createNotificationChannel("id0", "name0", IMPORTANCE_HIGH); + NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); ByteArrayOutputStream baos = writeXmlAndPurge(package0, uid0, true, 0); @@ -514,8 +507,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); NotificationChannel channel1 = - createNotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); - NotificationChannel channel2 = createNotificationChannel("id2", "name2", IMPORTANCE_LOW); + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + NotificationChannel channel2 = + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel2.setDescription("descriptions for all"); channel2.setSound(SOUND_URI, mAudioAttributes); channel2.enableLights(true); @@ -524,7 +518,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.enableVibration(false); channel2.setGroup(ncg.getId()); channel2.setLightColor(Color.BLUE); - NotificationChannel channel3 = createNotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); + NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); channel3.enableVibration(true); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); @@ -631,8 +625,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { } @Test - public void testRestoreXml_withNonExistentCanonicalizedSoundUri_ignoreChannel() - throws Exception { + public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception { Thread.sleep(3000); doReturn(null) .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI)); @@ -650,7 +643,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel actualChannel = mHelper.getNotificationChannel( PKG_N_MR1, UID_N_MR1, channel.getId(), false); - assertNull(actualChannel); + assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); } @@ -659,8 +652,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { * handle its restore properly. */ @Test - public void testRestoreXml_withUncanonicalizedNonLocalSoundUri_ignoreChannel() - throws Exception { + public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception { // Not a local uncanonicalized uri, simulating that it fails to exist locally doReturn(null) .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI)); @@ -679,7 +671,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { backupWithUncanonicalizedSoundUri.getBytes(), true, UserHandle.USER_SYSTEM); NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, id, false); - assertNull(actualChannel); + assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); } @Test @@ -703,11 +695,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); NotificationChannel channel1 = - createNotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel2 = - createNotificationChannel("id2", "name2", IMPORTANCE_HIGH); + new NotificationChannel("id2", "name2", IMPORTANCE_HIGH); NotificationChannel channel3 = - createNotificationChannel("id3", "name3", IMPORTANCE_LOW); + new NotificationChannel("id3", "name3", IMPORTANCE_LOW); channel3.setGroup(ncg.getId()); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); @@ -3062,7 +3054,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testChannelXml_backupDefaultApp() throws Exception { NotificationChannel channel1 = - createNotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_O, UID_O, channel1, true, false); @@ -3343,7 +3335,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mAppOpsManager, mStatsEventBuilderFactory); mHelper.createNotificationChannel( - PKG_P, UID_P, createNotificationChannel("id", "id", 2), true, false); + PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); assertTrue(mHelper.deleteNotificationChannel(PKG_P, UID_P, "id")); assertFalse(mHelper.deleteNotificationChannel(PKG_P, UID_P, "id")); } @@ -3354,7 +3346,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mAppOpsManager, mStatsEventBuilderFactory); mHelper.createNotificationChannel( - PKG_P, UID_P, createNotificationChannel("id", "id", 2), true, false); + PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); mHelper.deleteNotificationChannel(PKG_P, UID_P, "id"); NotificationChannel nc1 = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true); assertTrue(DateUtils.isToday(nc1.getDeletedTimeMs())); 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 222c692a9778..6b36fe808a2e 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 @@ public class SingleKeyGestureTests { @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 @@ public class SingleKeyGestureTests { } 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() { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 0d177c14427b..19f9b758811f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -30,6 +30,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; @@ -40,8 +41,10 @@ import static org.mockito.Mockito.timeout; import android.app.WaitResult; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.ConditionVariable; +import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.view.Display; @@ -187,6 +190,24 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { verify(taskChangeNotifier, never()).notifyActivityDismissingDockedRootTask(); } + /** Ensures that the calling package name passed to client complies with package visibility. */ + @Test + public void testFilteredReferred() { + final ActivityRecord activity = new ActivityBuilder(mAtm) + .setLaunchedFromPackage("other.package").setCreateTask(true).build(); + assertNotNull(activity.launchedFromPackage); + try { + mSupervisor.realStartActivityLocked(activity, activity.app, false /* andResume */, + false /* checkConfig */); + } catch (RemoteException ignored) { + } + verify(activity).getFilteredReferrer(eq(activity.launchedFromPackage)); + + activity.deliverNewIntentLocked(ActivityBuilder.DEFAULT_FAKE_UID, + new Intent(), null /* intentGrants */, "other.package2"); + verify(activity).getFilteredReferrer(eq("other.package2")); + } + /** * Ensures that notify focus task changes. */ diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 5a6581f94154..51e289f4d833 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1565,6 +1565,12 @@ public class DisplayContentTests extends WindowTestsBase { mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(); assertTrue(displayRotation.updateRotationUnchecked(false)); + // Rotation can be updated if the policy is not ok to animate (e.g. going to sleep). + mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity); + displayRotation.setRotation((displayRotation.getRotation() + 1) % 4); + ((TestWindowManagerPolicy) mWm.mPolicy).mOkToAnimate = false; + assertTrue(displayRotation.updateRotationUnchecked(false)); + // Rotation can be updated if the recents animation is animating but it is not on top, e.g. // switching activities in different orientations by quickstep gesture. mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity); diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java index f2418c68358d..a8ede13e5de6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java @@ -82,7 +82,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase { mWm.mWindowContextListenerController.registerWindowContainerListener(clientToken, dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG, null /* options */); - return true; + return dc.getImeContainer().getConfiguration(); }).when(wms).attachWindowContextToDisplayArea(any(), eq(TYPE_INPUT_METHOD_DIALOG), anyInt(), any()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 588089996d6c..611b3f5e62a5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -801,6 +801,7 @@ class WindowTestsBase extends SystemServiceTestsBase { private int mConfigChanges; private int mLaunchedFromPid; private int mLaunchedFromUid; + private String mLaunchedFromPackage; private WindowProcessController mWpc; private Bundle mIntentExtras; private boolean mOnTop = false; @@ -911,6 +912,11 @@ class WindowTestsBase extends SystemServiceTestsBase { return this; } + ActivityBuilder setLaunchedFromPackage(String packageName) { + mLaunchedFromPackage = packageName; + return this; + } + ActivityBuilder setUseProcess(WindowProcessController wpc) { mWpc = wpc; return this; @@ -1000,6 +1006,7 @@ class WindowTestsBase extends SystemServiceTestsBase { final ActivityRecord activity = new ActivityRecord.Builder(mService) .setLaunchedFromPid(mLaunchedFromPid) .setLaunchedFromUid(mLaunchedFromUid) + .setLaunchedFromPackage(mLaunchedFromPackage) .setIntent(intent) .setActivityInfo(aInfo) .setActivityOptions(options) diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java index 7b6ccd31adcc..0c65cc40bd82 100644 --- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java +++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java @@ -45,6 +45,7 @@ import android.service.usb.UsbUidPermissionProto; import android.service.usb.UsbUserPermissionsManagerProto; import android.util.ArrayMap; import android.util.AtomicFile; +import android.util.EventLog; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.TypedXmlPullParser; @@ -74,6 +75,8 @@ class UsbUserPermissionManager { private static final String TAG = UsbUserPermissionManager.class.getSimpleName(); private static final boolean DEBUG = false; + private static final int SNET_EVENT_LOG_ID = 0x534e4554; + @GuardedBy("mLock") /** Mapping of USB device name to list of UIDs with permissions for the device * Each entry lasts until device is disconnected*/ @@ -689,8 +692,11 @@ class UsbUserPermissionManager { try { ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0); if (aInfo.uid != uid) { - throw new IllegalArgumentException("package " + packageName + Slog.w(TAG, "package " + packageName + " does not match caller's uid " + uid); + EventLog.writeEvent(SNET_EVENT_LOG_ID, "180104273", -1, ""); + throw new IllegalArgumentException("package " + packageName + + " not found"); } } catch (PackageManager.NameNotFoundException e) { throw new IllegalArgumentException("package " + packageName + " not found"); diff --git a/services/uwb/java/com/android/server/uwb/UwbInjector.java b/services/uwb/java/com/android/server/uwb/UwbInjector.java index 64f1da1c8e16..a7a0500483c2 100644 --- a/services/uwb/java/com/android/server/uwb/UwbInjector.java +++ b/services/uwb/java/com/android/server/uwb/UwbInjector.java @@ -21,10 +21,13 @@ import static android.content.PermissionChecker.PERMISSION_GRANTED; import android.annotation.NonNull; import android.content.AttributionSource; +import android.content.ContentResolver; import android.content.Context; import android.content.PermissionChecker; import android.os.IBinder; import android.os.ServiceManager; +import android.provider.Settings; +import android.uwb.AdapterState; import android.uwb.IUwbAdapter; @@ -80,4 +83,23 @@ public class UwbInjector { mContext, UWB_RANGING, -1, attributionSource, message); return permissionCheckResult == PERMISSION_GRANTED; } + + /** Returns true if UWB state saved in Settings is enabled. */ + public boolean isPersistedUwbStateEnabled() { + final ContentResolver cr = mContext.getContentResolver(); + try { + return Settings.Global.getInt(cr, Settings.Global.UWB_ENABLED) + == AdapterState.STATE_ENABLED_ACTIVE; + } catch (Settings.SettingNotFoundException e) { + Settings.Global.putInt(cr, Settings.Global.UWB_ENABLED, + AdapterState.STATE_ENABLED_ACTIVE); + return true; + } + } + + /** Returns true if airplane mode is turned on. */ + public boolean isAirplaneModeOn() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; + } } diff --git a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java b/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java index 4dd26a66cf0e..889e182af46b 100644 --- a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java +++ b/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java @@ -18,13 +18,19 @@ package com.android.server.uwb; import android.annotation.NonNull; import android.content.AttributionSource; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; import android.os.PersistableBundle; import android.os.RemoteException; +import android.provider.Settings; import android.util.ArrayMap; import android.util.Log; +import android.uwb.AdapterState; import android.uwb.IUwbAdapter; import android.uwb.IUwbAdapterStateCallbacks; import android.uwb.IUwbRangingCallbacks; @@ -225,13 +231,20 @@ public class UwbServiceImpl extends IUwbAdapter.Stub implements IBinder.DeathRec mVendorUwbAdapter = null; } - private synchronized IUwbAdapter getVendorUwbAdapter() throws IllegalStateException { + private synchronized IUwbAdapter getVendorUwbAdapter() + throws IllegalStateException, RemoteException { if (mVendorUwbAdapter != null) return mVendorUwbAdapter; mVendorUwbAdapter = mUwbInjector.getVendorService(); if (mVendorUwbAdapter == null) { throw new IllegalStateException("No vendor service found!"); } Log.i(TAG, "Retrieved vendor service"); + long token = Binder.clearCallingIdentity(); + try { + mVendorUwbAdapter.setEnabled(isEnabled()); + } finally { + Binder.restoreCallingIdentity(token); + } linkToVendorServiceDeath(); return mVendorUwbAdapter; } @@ -239,6 +252,7 @@ public class UwbServiceImpl extends IUwbAdapter.Stub implements IBinder.DeathRec UwbServiceImpl(@NonNull Context context, @NonNull UwbInjector uwbInjector) { mContext = context; mUwbInjector = uwbInjector; + registerAirplaneModeReceiver(); } private void enforceUwbPrivilegedPermission() { @@ -320,6 +334,34 @@ public class UwbServiceImpl extends IUwbAdapter.Stub implements IBinder.DeathRec @Override public synchronized void setEnabled(boolean enabled) throws RemoteException { - getVendorUwbAdapter().setEnabled(enabled); + persistUwbState(enabled); + getVendorUwbAdapter().setEnabled(isEnabled()); + } + + private void persistUwbState(boolean enabled) { + final ContentResolver cr = mContext.getContentResolver(); + int state = enabled ? AdapterState.STATE_ENABLED_ACTIVE : AdapterState.STATE_DISABLED; + Settings.Global.putInt(cr, Settings.Global.UWB_ENABLED, state); + } + + private void registerAirplaneModeReceiver() { + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + handleAirplaneModeEvent(); + } + }, new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); + } + + private void handleAirplaneModeEvent() { + try { + getVendorUwbAdapter().setEnabled(isEnabled()); + } catch (RemoteException | IllegalStateException e) { + Log.e(TAG, "Unable to set UWB Adapter state.", e); + } + } + + private boolean isEnabled() { + return mUwbInjector.isPersistedUwbStateEnabled() && !mUwbInjector.isAirplaneModeOn(); } } diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp index 702ddb1b98fe..af0eca955242 100644 --- a/services/voiceinteraction/Android.bp +++ b/services/voiceinteraction/Android.bp @@ -18,5 +18,9 @@ java_library_static { name: "services.voiceinteraction", defaults: ["platform_service_defaults"], srcs: [":services.voiceinteraction-sources"], - libs: ["services.core"], + libs: [ + "services.core", + "android.hardware.power-V1-java", + "android.hardware.power-V1.0-java", + ], } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index a9aeb985d115..4dc83ae98d89 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -269,13 +269,11 @@ final class HotwordDetectionConnection { Slog.v(TAG, "cancelLocked"); clearDebugHotwordLoggingTimeoutLocked(); mDebugHotwordLogging = false; - if (mRemoteHotwordDetectionService.isBound()) { - mRemoteHotwordDetectionService.unbind(); - LocalServices.getService(PermissionManagerServiceInternal.class) - .setHotwordDetectionServiceProvider(null); - mIdentity = null; - updateServiceUidForAudioPolicy(Process.INVALID_UID); - } + mRemoteHotwordDetectionService.unbind(); + LocalServices.getService(PermissionManagerServiceInternal.class) + .setHotwordDetectionServiceProvider(null); + mIdentity = null; + updateServiceUidForAudioPolicy(Process.INVALID_UID); mCancellationTaskFuture.cancel(/* may interrupt */ true); if (mAudioFlinger != null) { mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index cc021a9acfe2..08e9703124ab 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -43,11 +43,13 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Bitmap; +import android.hardware.power.Boost; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.PowerManagerInternal; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -62,6 +64,7 @@ import android.view.IWindowManager; import com.android.internal.app.AssistUtils; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.am.AssistDataRequester; import com.android.server.am.AssistDataRequester.AssistDataRequesterCallbacks; @@ -70,13 +73,20 @@ import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.ActivityAssistInfo; import java.io.PrintWriter; +import java.time.Instant; import java.util.ArrayList; import java.util.List; final class VoiceInteractionSessionConnection implements ServiceConnection, AssistDataRequesterCallbacks { - final static String TAG = "VoiceInteractionServiceManager"; + static final String TAG = "VoiceInteractionServiceManager"; + static final int POWER_BOOST_TIMEOUT_MS = Integer.parseInt( + System.getProperty("vendor.powerhal.interaction.max", "200")); + static final int BOOST_TIMEOUT_MS = 300; + // TODO: To avoid ap doesn't call hide, only 10 secs for now, need a better way to manage it + // in the future. + static final int MAX_POWER_BOOST_TIMEOUT = 10_000; final IBinder mToken = new Binder(); final Object mLock; @@ -104,6 +114,45 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>(); private List<ActivityAssistInfo> mPendingHandleAssistWithoutData = new ArrayList<>(); AssistDataRequester mAssistDataRequester; + private final PowerManagerInternal mPowerManagerInternal; + private PowerBoostSetter mSetPowerBoostRunnable; + private final Handler mFgHandler; + + class PowerBoostSetter implements Runnable { + + private boolean mCanceled; + private final Instant mExpiryTime; + + PowerBoostSetter(Instant expiryTime) { + mExpiryTime = expiryTime; + } + + @Override + public void run() { + synchronized (mLock) { + if (mCanceled) { + return; + } + // To avoid voice interaction service does not call hide to cancel setting + // power boost. We will cancel set boost when reaching the max timeout. + if (Instant.now().isBefore(mExpiryTime)) { + mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, BOOST_TIMEOUT_MS); + if (mSetPowerBoostRunnable != null) { + mFgHandler.postDelayed(mSetPowerBoostRunnable, POWER_BOOST_TIMEOUT_MS); + } + } else { + Slog.w(TAG, "Reset power boost INTERACTION because reaching max timeout."); + mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, /* durationMs */ -1); + } + } + } + + void cancel() { + synchronized (mLock) { + mCanceled = true; + } + } + } IVoiceInteractionSessionShowCallback mShowCallback = new IVoiceInteractionSessionShowCallback.Stub() { @@ -152,7 +201,9 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class); mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mAppOps = context.getSystemService(AppOpsManager.class); + mFgHandler = FgThread.getHandler(); mAssistDataRequester = new AssistDataRequester(mContext, mIWindowManager, (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE), this, mLock, OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT); @@ -255,6 +306,13 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, mPendingHandleAssistWithoutData = topActivities; } } + // remove if already existing one. + if (mSetPowerBoostRunnable != null) { + mSetPowerBoostRunnable.cancel(); + } + mSetPowerBoostRunnable = new PowerBoostSetter( + Instant.now().plusMillis(MAX_POWER_BOOST_TIMEOUT)); + mFgHandler.post(mSetPowerBoostRunnable); mCallback.onSessionShown(this); return true; } @@ -420,6 +478,12 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, } catch (RemoteException e) { } } + if (mSetPowerBoostRunnable != null) { + mSetPowerBoostRunnable.cancel(); + mSetPowerBoostRunnable = null; + } + // A negative value indicates canceling previous boost. + mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, /* durationMs */ -1); mCallback.onSessionHidden(this); } if (mFullyBound) { diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index a427ed612b31..bc0a14667307 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -23,6 +23,8 @@ import android.os.Build; import android.os.Bundle; import android.util.ArrayMap; +import com.android.internal.annotations.GuardedBy; + import java.util.Collections; import java.util.List; import java.util.Map; @@ -115,6 +117,7 @@ public final class Phone { public static final int SDK_VERSION_R = 30; // A Map allows us to track each Call by its Telecom-specified call ID + @GuardedBy("mLock") private final Map<String, Call> mCallByTelecomCallId = new ArrayMap<>(); // A List allows us to keep the Calls in a stable iteration order so that casually developed @@ -139,6 +142,8 @@ public final class Phone { */ private final int mTargetSdkVersion; + private final Object mLock = new Object(); + Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) { mInCallAdapter = adapter; mCallingPackage = callingPackage; @@ -152,12 +157,16 @@ public final class Phone { return; } - Call call = mCallByTelecomCallId.get(parcelableCall.getId()); + Call call = getCallById(parcelableCall.getId()); if (call == null) { call = new Call(this, parcelableCall.getId(), mInCallAdapter, parcelableCall.getState(), mCallingPackage, mTargetSdkVersion); - mCallByTelecomCallId.put(parcelableCall.getId(), call); - mCalls.add(call); + + synchronized (mLock) { + mCallByTelecomCallId.put(parcelableCall.getId(), call); + mCalls.add(call); + } + checkCallTree(parcelableCall); call.internalUpdate(parcelableCall, mCallByTelecomCallId); fireCallAdded(call); @@ -169,8 +178,10 @@ public final class Phone { } final void internalRemoveCall(Call call) { - mCallByTelecomCallId.remove(call.internalGetCallId()); - mCalls.remove(call); + synchronized (mLock) { + mCallByTelecomCallId.remove(call.internalGetCallId()); + mCalls.remove(call); + } InCallService.VideoCall videoCall = call.getVideoCall(); if (videoCall != null) { @@ -183,14 +194,14 @@ public final class Phone { if (mTargetSdkVersion < SDK_VERSION_R && parcelableCall.getState() == Call.STATE_AUDIO_PROCESSING) { Log.i(this, "removing audio processing call during update for sdk compatibility"); - Call call = mCallByTelecomCallId.get(parcelableCall.getId()); + Call call = getCallById(parcelableCall.getId()); if (call != null) { internalRemoveCall(call); } return; } - Call call = mCallByTelecomCallId.get(parcelableCall.getId()); + Call call = getCallById(parcelableCall.getId()); if (call != null) { checkCallTree(parcelableCall); call.internalUpdate(parcelableCall, mCallByTelecomCallId); @@ -207,8 +218,14 @@ public final class Phone { } } + Call getCallById(String callId) { + synchronized (mLock) { + return mCallByTelecomCallId.get(callId); + } + } + final void internalSetPostDialWait(String telecomId, String remaining) { - Call call = mCallByTelecomCallId.get(telecomId); + Call call = getCallById(telecomId); if (call != null) { call.internalSetPostDialWait(remaining); } @@ -222,7 +239,7 @@ public final class Phone { } final Call internalGetCallByTelecomId(String telecomId) { - return mCallByTelecomCallId.get(telecomId); + return getCallById(telecomId); } final void internalBringToForeground(boolean showDialpad) { @@ -241,35 +258,35 @@ public final class Phone { } final void internalOnConnectionEvent(String telecomId, String event, Bundle extras) { - Call call = mCallByTelecomCallId.get(telecomId); + Call call = getCallById(telecomId); if (call != null) { call.internalOnConnectionEvent(event, extras); } } final void internalOnRttUpgradeRequest(String callId, int requestId) { - Call call = mCallByTelecomCallId.get(callId); + Call call = getCallById(callId); if (call != null) { call.internalOnRttUpgradeRequest(requestId); } } final void internalOnRttInitiationFailure(String callId, int reason) { - Call call = mCallByTelecomCallId.get(callId); + Call call = getCallById(callId); if (call != null) { call.internalOnRttInitiationFailure(reason); } } final void internalOnHandoverFailed(String callId, int error) { - Call call = mCallByTelecomCallId.get(callId); + Call call = getCallById(callId); if (call != null) { call.internalOnHandoverFailed(error); } } final void internalOnHandoverComplete(String callId) { - Call call = mCallByTelecomCallId.get(callId); + Call call = getCallById(callId); if (call != null) { call.internalOnHandoverComplete(); } diff --git a/telephony/OWNERS b/telephony/OWNERS index 4df8a4bc6413..f248fd52db83 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -8,10 +8,10 @@ rgreenwalt@google.com tgunn@google.com jminjie@google.com shuoq@google.com -nazaninb@google.com sarahchin@google.com xiaotonj@google.com huiwang@google.com jayachandranc@google.com chinmayd@google.com amruthr@google.com +sasindran@google.com diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java index a1c5bbefbbe1..ae597e02f33c 100644 --- a/telephony/java/android/telephony/AvailableNetworkInfo.java +++ b/telephony/java/android/telephony/AvailableNetworkInfo.java @@ -19,6 +19,7 @@ package android.telephony; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.RadioAccessSpecifier; import java.util.ArrayList; import java.util.Arrays; @@ -76,13 +77,28 @@ public final class AvailableNetworkInfo implements Parcelable { * Opportunistic network service will use these bands to scan. * * When no specific bands are specified (empty array or null) CBRS band - * {@link AccessNetworkConstants.EutranBand.BAND_48} will be used for network scan. + * {@link AccessNetworkConstants.EutranBand.BAND_48 + * } will be used for network scan. * * See {@link AccessNetworkConstants} for details. + * + * @deprecated use {@link #mRadioAccessSpecifiers} instead */ + @Deprecated private ArrayList<Integer> mBands; /** + * Returns a list of {@link RadioAccessSpecifier} associated with the available network. + * Opportunistic network service will use this to determine which bands to scan for. + * + * If this entry is left empty, {@link RadioAcccessSpecifier}s with {@link AccessNetworkType}s + * of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link + * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed + * by Opportunistic network service. + */ + private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers; + + /** * Return subscription Id of the available network. * This value must be one of the entry retrieved from * {@link SubscriptionManager#getOpportunisticSubscriptions} @@ -129,6 +145,22 @@ public final class AvailableNetworkInfo implements Parcelable { return (List<Integer>) mBands.clone(); } + /** + * Returns a list of {@link RadioAccessSpecifier} associated with the available network. + * Opportunistic network service will use this to determine which bands to scan for. + * + * the returned value is one of {@link AccessNetworkConstants.AccessNetworkType}. When no + * specific access network type is specified, {@link RadioAccessSpecifier}s with {@link + * AccessNetworkType}s of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link + * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed + * by Opportunistic network service. + * @return the access network type associated with the available network. + * @hide + */ + public List<RadioAccessSpecifier> getRadioAccessSpecifiers() { + return (List<RadioAccessSpecifier>) mRadioAccessSpecifiers.clone(); + } + @Override public int describeContents() { return 0; @@ -140,6 +172,7 @@ public final class AvailableNetworkInfo implements Parcelable { dest.writeInt(mPriority); dest.writeStringList(mMccMncs); dest.writeList(mBands); + dest.writeList(mRadioAccessSpecifiers); } private AvailableNetworkInfo(Parcel in) { @@ -149,14 +182,25 @@ public final class AvailableNetworkInfo implements Parcelable { in.readStringList(mMccMncs); mBands = new ArrayList<>(); in.readList(mBands, Integer.class.getClassLoader()); + mRadioAccessSpecifiers = new ArrayList<>(); + in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader()); } public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs, @NonNull List<Integer> bands) { + this(subId, priority, mccMncs, bands, + new ArrayList<RadioAccessSpecifier>()); + } + + /** @hide */ + private AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs, + @NonNull List<Integer> bands, @NonNull List<RadioAccessSpecifier> + radioAccessSpecifiers) { mSubId = subId; mPriority = priority; mMccMncs = new ArrayList<String>(mccMncs); mBands = new ArrayList<Integer>(bands); + mRadioAccessSpecifiers = new ArrayList<RadioAccessSpecifier>(radioAccessSpecifiers); } @Override @@ -177,12 +221,13 @@ public final class AvailableNetworkInfo implements Parcelable { && mPriority == ani.mPriority && (((mMccMncs != null) && mMccMncs.equals(ani.mMccMncs))) - && mBands.equals(ani.mBands)); + && mBands.equals(ani.mBands)) + && mRadioAccessSpecifiers.equals(ani.getRadioAccessSpecifiers()); } @Override public int hashCode() { - return Objects.hash(mSubId, mPriority, mMccMncs, mBands); + return Objects.hash(mSubId, mPriority, mMccMncs, mBands, mRadioAccessSpecifiers); } public static final @android.annotation.NonNull Parcelable.Creator<AvailableNetworkInfo> CREATOR = @@ -204,6 +249,72 @@ public final class AvailableNetworkInfo implements Parcelable { + " mSubId: " + mSubId + " mPriority: " + mPriority + " mMccMncs: " + Arrays.toString(mMccMncs.toArray()) - + " mBands: " + Arrays.toString(mBands.toArray())); + + " mBands: " + Arrays.toString(mBands.toArray()) + + " mRadioAccessSpecifiers: " + Arrays.toString(mRadioAccessSpecifiers.toArray())); + } + + /** + * Provides a convenient way to set the fields of a {@link AvailableNetworkInfo} when + * creating a new instance. + * + * <p>The example below shows how you might create a new {@code AvailableNetworkInfo}: + * + * <pre><code> + * + * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder() + * .setSubId(1) + * .setPriority(AvailableNetworkInfo.PRIORITY_MED) + * .build(); + * </code></pre> + * + * @hide + */ + public static final class Builder { + private int mSubId = Integer.MIN_VALUE; + private int mPriority = AvailableNetworkInfo.PRIORITY_LOW; + private ArrayList<String> mMccMncs = new ArrayList<>(); + private ArrayList<Integer> mBands = new ArrayList<>(); + private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers = new ArrayList<>(); + + public @NonNull Builder setSubId(int subId) { + mSubId = subId; + return this; + } + + public @NonNull Builder setPriority(int priority) { + if (priority > AvailableNetworkInfo.PRIORITY_LOW + || priority < AvailableNetworkInfo.PRIORITY_HIGH) { + throw new IllegalArgumentException("A valid priority must be set"); + } + mPriority = priority; + return this; + } + + public @NonNull Builder setMccMncs(@NonNull ArrayList<String> mccMncs) { + Objects.requireNonNull(mccMncs, "A non-null ArrayList of mccmncs must be set. An empty " + + "list is still accepted. Please read documentation in " + + "AvailableNetworkService to see consequences of an empty Arraylist."); + mMccMncs = mccMncs; + return this; + } + + public @NonNull Builder setRadioAccessSpecifiers( + @NonNull ArrayList<RadioAccessSpecifier> radioAccessSpecifiers) { + Objects.requireNonNull(radioAccessSpecifiers, "A non-null ArrayList of " + + "RadioAccessSpecifiers must be set. An empty list is still accepted. Please " + + "read documentation in AvailableNetworkService to see consequences of an " + + "empty Arraylist."); + mRadioAccessSpecifiers = radioAccessSpecifiers; + return this; + } + + public @NonNull AvailableNetworkInfo build() { + if (mSubId == Integer.MIN_VALUE) { + throw new IllegalArgumentException("A valid subId must be set"); + } + + return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, mBands, + mRadioAccessSpecifiers); + } } } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 0dfbc22df71f..548efb82bee7 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1003,6 +1003,21 @@ public class CarrierConfigManager { = "carrier_use_ims_first_for_emergency_bool"; /** + * When {@code true}, the determination of whether to place a call as an emergency call will be + * based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which + * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * it will not be treated as an emergency call in this case. + * When {@code false}, the determination is based on the emergency numbers from all device SIMs, + * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * the call will be dialed as an emergency number, but with an unspecified routing. + * @hide + */ + public static final String KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL = + "use_only_dialed_sim_ecc_list_bool"; + + /** * When IMS instant lettering is available for a carrier (see * {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters * which may not be contained in messages. Should be specified as a regular expression suitable @@ -3814,6 +3829,109 @@ public class CarrierConfigManager { "opportunistic_network_max_backoff_time_long"; /** + * Controls SS-RSRP threshold in dBm at which 5G opportunistic network will be considered good + * enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT = + "opportunistic_network_entry_threshold_ss_rsrp_int"; + + /** + * Controls SS-RSRQ threshold in dB at which 5G opportunistic network will be considered good + * enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE = + "opportunistic_network_entry_threshold_ss_rsrq_double"; + + /** + * Controls SS-RSRP threshold in dBm below which 5G opportunistic network available will not + * be considered good enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT = + "opportunistic_network_exit_threshold_ss_rsrp_int"; + + /** + * Controls SS-RSRQ threshold in dB below which 5G opportunistic network available will not + * be considered good enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE = + "opportunistic_network_exit_threshold_ss_rsrq_double"; + + /** + * Controls back off time in milliseconds for switching back to + * 5G opportunistic subscription. This time will be added to + * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} to + * determine hysteresis time if there is ping pong situation + * (determined by system app or 1st party app) between primary and 5G opportunistic + * subscription. Ping ping situation is defined in + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG. + * If ping pong situation continuous #KEY_OPPORTUNISTIC_5G_NETWORK_BACKOFF_TIME_LONG + * will be added to previously determined hysteresis time. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG = + "opportunistic_network_5g_backoff_time_long"; + + /** + * Controls the max back off time in milliseconds for switching back to + * 5G opportunistic subscription. + * This time will be the max hysteresis that can be determined irrespective of there is + * continuous ping pong situation or not as described in + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG and + * #KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG = + "opportunistic_network_5g_max_backoff_time_long"; + + /** + * Controls the ping pong determination of 5G opportunistic network. + * If opportunistic network is determined as out of service or below + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT or + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_INT within + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG of switching to opportunistic network, + * it will be determined as ping pong situation by system app or 1st party app. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG = + "opportunistic_network_5g_ping_pong_time_long"; + + /** + * Controls hysteresis time in milliseconds for which will be waited before switching + * data to a 5G opportunistic network. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG = + "opportunistic_network_5g_data_switch_hysteresis_time_long"; + + /** + * Controls hysteresis time in milliseconds for which will be waited before switching from + * 5G opportunistic network to primary network. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG = + "opportunistic_network_5g_data_switch_exit_hysteresis_time_long"; + /** + * Controls whether 4G opportunistic networks should be scanned for possible data switch. + * + * @hide + */ + public static final String KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL = + "enabled_4g_opportunistic_network_scan_bool"; + + /** * Indicates zero or more emergency number prefix(es), because some carrier requires * if users dial an emergency number address with a specific prefix, the combination of the * prefix and the address is also a valid emergency number to dial. For example, an emergency @@ -5121,6 +5239,16 @@ public class CarrierConfigManager { "display_no_data_notification_on_permanent_failure_bool"; /** + * Boolean indicating if the VoNR setting is visible in the Call Settings menu. + * If true, the VoNR setting menu will be visible. If false, the menu will be gone. + * + * Disabled by default. + * + * @hide + */ + public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool"; + + /** * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes * * @hide @@ -5222,6 +5350,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true); + sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, ""); @@ -5690,7 +5819,25 @@ public class CarrierConfigManager { sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000); /* Default value is 60 seconds. */ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000); - sDefaults.putAll(ImsServiceEntitlement.getDefaults()); + /* Default value is -111 dBm. */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT, -111); + /* Default value is -18.5 dB. */ + sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5); + /* Default value is -120 dBm. */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT, -120); + /* Default value is -18.5 dB. */ + sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5); + /* Default value is 10 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG, 10000); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG, 60000); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG, 60000); + /* Default value is 2 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000); + /* Default value is 2 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000); + sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true); sDefaults.putAll(Gps.getDefaults()); sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY, new int[] { @@ -5762,7 +5909,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, ""); sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false); sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false); - sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_MULTIANCHOR_CONFERENCE, false); + sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false); sDefaults.putStringArray(KEY_MULTI_APN_ARRAY_FOR_SAME_GID, new String[] { "52FF:mms,supl,hipri,default,fota:SA:nrphone", "52FF:mms,supl,hipri,default,fota:NSA:nxtgenphone", diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java index fe7e5976b132..41e24ddb3fa6 100644 --- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java +++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java @@ -26,8 +26,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -101,9 +103,11 @@ public final class SignalStrengthUpdateRequest implements Parcelable { } mSignalThresholdInfos = new ArrayList<>(signalThresholdInfos); - // Sort the collection with RAN ascending order, make the ordering not matter for equals + // Sort the collection with RAN and then SignalMeasurementType ascending order, make the + // ordering not matter for equals mSignalThresholdInfos.sort( - Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType)); + Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType) + .thenComparing(SignalThresholdInfo::getSignalMeasurementType)); return this; } @@ -144,7 +148,7 @@ public final class SignalStrengthUpdateRequest implements Parcelable { * @return the SignalStrengthUpdateRequest object * * @throws IllegalArgumentException if the SignalThresholdInfo collection is empty size, the - * radio access network type in the collection is not unique + * signal measurement type for the same RAN in the collection is not unique */ public @NonNull SignalStrengthUpdateRequest build() { return new SignalStrengthUpdateRequest(mSignalThresholdInfos, @@ -258,14 +262,23 @@ public final class SignalStrengthUpdateRequest implements Parcelable { } /** - * Throw IAE when the RAN in the collection is not unique. + * Throw IAE if SignalThresholdInfo collection is null or empty, + * or the SignalMeasurementType for the same RAN in the collection is not unique. */ private static void validate(Collection<SignalThresholdInfo> infos) { - Set<Integer> uniqueRan = new HashSet<>(infos.size()); + if (infos == null || infos.isEmpty()) { + throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty"); + } + + // Map from RAN to set of SignalMeasurementTypes + Map<Integer, Set<Integer>> ranToTypes = new HashMap<>(infos.size()); for (SignalThresholdInfo info : infos) { final int ran = info.getRadioAccessNetworkType(); - if (!uniqueRan.add(ran)) { - throw new IllegalArgumentException("RAN: " + ran + " is not unique"); + final int type = info.getSignalMeasurementType(); + ranToTypes.putIfAbsent(ran, new HashSet<>()); + if (!ranToTypes.get(ran).add(type)) { + throw new IllegalArgumentException( + "SignalMeasurementType " + type + " for RAN " + ran + " is not unique"); } } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 799930c53669..ba0d6afe25a4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3515,7 +3515,8 @@ public class TelephonyManager { */ private int getLogicalSlotIndex(int physicalSlotIndex) { UiccSlotInfo[] slotInfos = getUiccSlotsInfo(); - if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length) { + if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length + && slotInfos[physicalSlotIndex] != null) { return slotInfos[physicalSlotIndex].getLogicalSlotIdx(); } @@ -8888,7 +8889,8 @@ public class TelephonyManager { } /** - * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. + * Set the preferred network type to global mode which includes NR, LTE, CDMA, EvDo + * and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * @@ -8899,7 +8901,8 @@ public class TelephonyManager { } /** - * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. + * Set the preferred network type to global mode which includes NR, LTE, CDMA, EvDo + * and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * @@ -8907,7 +8910,7 @@ public class TelephonyManager { * @hide */ public boolean setPreferredNetworkTypeToGlobal(int subId) { - return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); + return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); } /** @@ -12178,6 +12181,100 @@ public class TelephonyManager { } /** + * No error. Operation succeeded. + * @hide + */ + public static final int ENABLE_VONR_SUCCESS = 0; + + /** + * Radio is not available. + * @hide + */ + public static final int ENABLE_VONR_RADIO_NOT_AVAILABLE = 2; + + /** + * Internal Radio error. + * @hide + */ + public static final int ENABLE_VONR_RADIO_ERROR = 3; + + /** + * Voice over NR enable/disable request is received when system is in invalid state. + * @hide + */ + public static final int ENABLE_VONR_RADIO_INVALID_STATE = 4; + + /** + * Voice over NR enable/disable request is not supported. + * @hide + */ + public static final int ENABLE_VONR_REQUEST_NOT_SUPPORTED = 5; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"EnableVoNrResult"}, value = { + ENABLE_VONR_SUCCESS, + ENABLE_VONR_RADIO_NOT_AVAILABLE, + ENABLE_VONR_RADIO_ERROR, + ENABLE_VONR_RADIO_INVALID_STATE, + ENABLE_VONR_REQUEST_NOT_SUPPORTED}) + public @interface EnableVoNrResult {} + + /** + * Enable or disable Voice over NR (VoNR) + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the + * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()} + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * + * @param enabled enable or disable VoNR. + * @throws IllegalStateException if the Telephony process is not currently available. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public @EnableVoNrResult int setVoNrEnabled(boolean enabled) { + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.setVoNrEnabled( + getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#setVoNrEnabled", e); + } + + return ENABLE_VONR_RADIO_INVALID_STATE; + } + + /** + * Is Voice over NR (VoNR) enabled. + * @return true if Voice over NR (VoNR) is enabled else false. Enabled state does not mean + * voice call over NR is active or voice ove NR is available. It means the device is allowed to + * register IMS over NR. + * @throws IllegalStateException if the Telephony process is not currently available. + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isVoNrEnabled() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.isVoNrEnabled(getSubId()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + Rlog.e(TAG, "isVoNrEnabled RemoteException", ex); + ex.rethrowFromSystemServer(); + } + return false; + } + + /** * Carrier action to start or stop reporting default network available events. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the @@ -14242,7 +14339,8 @@ public class TelephonyManager { if (callForwardingInfo.getNumber() == null) { throw new IllegalArgumentException("callForwarding number is null"); } - if (callForwardingInfo.getTimeoutSeconds() <= 0) { + if (callForwardingReason == CallForwardingInfo.REASON_NO_REPLY + && callForwardingInfo.getTimeoutSeconds() <= 0) { throw new IllegalArgumentException("callForwarding timeout isn't positive"); } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 018dabfdb552..89e39256bf09 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2228,6 +2228,20 @@ interface ITelephony { List<String> getEquivalentHomePlmns(int subId, String callingPackage, String callingFeatureId); /** + * Enable or disable Voice over NR (VoNR) + * @param subId the subscription ID that this action applies to. + * @param enabled enable or disable VoNR. + * @return operation result. + */ + int setVoNrEnabled(int subId, boolean enabled); + + /** + * Is voice over NR enabled + * @return true if VoNR is enabled else false + */ + boolean isVoNrEnabled(int subId); + + /** * Enable/Disable E-UTRA-NR Dual Connectivity * @return operation result. See TelephonyManager.EnableNrDualConnectivityResult for * details diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 2c258d97c1a9..e65624cb0ffd 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -528,6 +528,8 @@ public interface RILConstants { int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222; int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223; int RIL_REQUEST_GET_SLICING_CONFIG = 224; + int RIL_REQUEST_ENABLE_VONR = 225; + int RIL_REQUEST_IS_VONR_ENABLED = 225; /* RIL Request to get newly supported radio capabilities include 5G SA*/ diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 0f84f6ebe522..c9a8947ab5ef 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -322,6 +322,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID); verify(mSafeModeTimeoutAlarm).cancel(); assertFalse(mGatewayConnection.isInSafeMode()); + verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */); } @Test @@ -391,6 +392,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID); + verifySafeModeStateAndCallbackFired(2 /* invocationCount */, false /* isInSafeMode */); assertFalse(mGatewayConnection.isInSafeMode()); } @@ -400,7 +402,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mTestLooper.dispatchAll(); triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID); - assertFalse(mGatewayConnection.isInSafeMode()); + verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */); // Trigger a failed validation, and the subsequent safemode timeout. triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID); @@ -416,7 +418,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection runnableCaptor.getValue().run(); mTestLooper.dispatchAll(); - assertTrue(mGatewayConnection.isInSafeMode()); + verifySafeModeStateAndCallbackFired(2 /* invocationCount */, true /* isInSafeMode */); } private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() { diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index a696b3ae28f7..64d0bca15ce9 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -23,7 +23,6 @@ import static com.android.server.vcn.VcnTestUtils.setupIpSecManager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.CALLS_REAL_METHODS; @@ -301,6 +300,11 @@ public class VcnGatewayConnectionTestBase { expectCanceled); } + protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) { + verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged(); + assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode()); + } + protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent( @NonNull State expectedState) { // Set a VcnNetworkAgent, and expect it to be unregistered and cleared @@ -314,9 +318,8 @@ public class VcnGatewayConnectionTestBase { delayedEvent.run(); mTestLooper.dispatchAll(); - verify(mGatewayStatusCallback).onSafeModeStatusChanged(); assertEquals(expectedState, mGatewayConnection.getCurrentState()); - assertTrue(mGatewayConnection.isInSafeMode()); + verifySafeModeStateAndCallbackFired(1, true); verify(mockNetworkAgent).unregister(); assertNull(mGatewayConnection.getNetworkAgent()); |