Merge "pm: Modify getPackage() to only return non-null packages" into pi-dev
diff --git a/Android.bp b/Android.bp
index 1b9210c..1caa497 100644
--- a/Android.bp
+++ b/Android.bp
@@ -813,6 +813,7 @@
],
srcs: [
+ "core/proto/android/os/backtrace.proto",
"core/proto/android/os/batterytype.proto",
"core/proto/android/os/cpufreq.proto",
"core/proto/android/os/cpuinfo.proto",
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
new file mode 100644
index 0000000..55b97e7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2018 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 android.widget;
+
+import static android.view.View.MeasureSpec.AT_MOST;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.UNSPECIFIED;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Typeface;
+import android.graphics.Canvas;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.PrecomputedText;
+import android.text.Layout;
+import android.text.BoringLayout;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.style.TextAppearanceSpan;
+import android.view.LayoutInflater;
+import android.text.TextPerfUtils;
+import android.view.View.MeasureSpec;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+
+import com.android.perftests.core.R;
+
+import java.util.Random;
+import java.util.Locale;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertTrue;
+
+import static android.widget.TextView.UNKNOWN_BORING;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TextViewPrecomputedTextPerfTest {
+ private static final int WORD_LENGTH = 9; // Random word has 9 characters.
+ private static final int WORDS_IN_LINE = 8; // Roughly, 8 words in a line.
+ private static final boolean NO_STYLE_TEXT = false;
+ private static final boolean STYLE_TEXT = true;
+
+ private static TextPaint PAINT = new TextPaint();
+ private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize();
+
+ public TextViewPrecomputedTextPerfTest() {}
+
+ private static class TestableTextView extends TextView {
+ public TestableTextView(Context ctx) {
+ super(ctx);
+ }
+
+ public void onMeasure(int w, int h) {
+ super.onMeasure(w, h);
+ }
+
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ }
+ }
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ private TextPerfUtils mTextUtil = new TextPerfUtils();
+
+ @Before
+ public void setUp() {
+ mTextUtil.resetRandom(0 /* seed */);
+ }
+
+ private static Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+
+ @Test
+ public void testNewLayout_RandomText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+ TEXT_WIDTH, false);
+ }
+ }
+
+ @Test
+ public void testNewLayout_PrecomputedText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TextView textView = new TextView(getContext());
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+ TEXT_WIDTH, false);
+ }
+ }
+
+ @Test
+ public void testNewLayout_PrecomputedText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+ TEXT_WIDTH, false);
+ }
+ }
+
+ @Test
+ public void testSetText_RandomText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.setText(text);
+ }
+ }
+
+ @Test
+ public void testSetText_PrecomputedText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TextView textView = new TextView(getContext());
+ textView.setTextMetricsParams(params);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.setText(text);
+ }
+ }
+
+ @Test
+ public void testSetText_PrecomputedText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setTextMetricsParams(params);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.setText(text);
+ }
+ }
+
+ @Test
+ public void testOnMeasure_RandomText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onMeasure(width, height);
+ }
+ }
+
+ @Test
+ public void testOnMeasure_PrecomputedText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onMeasure(width, height);
+ }
+ }
+
+ @Test
+ public void testOnMeasure_PrecomputedText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onMeasure(width, height);
+ }
+ }
+
+ @Test
+ public void testOnDraw_RandomText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.nullLayouts();
+ textView.onMeasure(width, height);
+ final DisplayListCanvas c = node.start(
+ textView.getMeasuredWidth(), textView.getMeasuredHeight());
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onDraw(c);
+ }
+ }
+
+ @Test
+ public void testOnDraw_PrecomputedText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ textView.nullLayouts();
+ textView.onMeasure(width, height);
+ final DisplayListCanvas c = node.start(
+ textView.getMeasuredWidth(), textView.getMeasuredHeight());
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onDraw(c);
+ }
+ }
+
+ @Test
+ public void testOnDraw_PrecomputedText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
+ int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED).build();
+ final CharSequence text = PrecomputedText.create(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), params);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setTextMetricsParams(params);
+ textView.setText(text);
+ textView.nullLayouts();
+ textView.onMeasure(width, height);
+ final DisplayListCanvas c = node.start(
+ textView.getMeasuredWidth(), textView.getMeasuredHeight());
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onDraw(c);
+ }
+ }
+}
diff --git a/api/system-current.txt b/api/system-current.txt
index 0555263..6eef3a2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2115,8 +2115,15 @@
field public static final java.lang.String METADATA_KEY_ART = "android.hardware.radio.metadata.ART";
field public static final java.lang.String METADATA_KEY_ARTIST = "android.hardware.radio.metadata.ARTIST";
field public static final java.lang.String METADATA_KEY_CLOCK = "android.hardware.radio.metadata.CLOCK";
+ field public static final java.lang.String METADATA_KEY_DAB_COMPONENT_NAME = "android.hardware.radio.metadata.DAB_COMPONENT_NAME";
+ field public static final java.lang.String METADATA_KEY_DAB_COMPONENT_NAME_SHORT = "android.hardware.radio.metadata.DAB_COMPONENT_NAME_SHORT";
+ field public static final java.lang.String METADATA_KEY_DAB_ENSEMBLE_NAME = "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME";
+ field public static final java.lang.String METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT = "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME_SHORT";
+ field public static final java.lang.String METADATA_KEY_DAB_SERVICE_NAME = "android.hardware.radio.metadata.DAB_SERVICE_NAME";
+ field public static final java.lang.String METADATA_KEY_DAB_SERVICE_NAME_SHORT = "android.hardware.radio.metadata.DAB_SERVICE_NAME_SHORT";
field public static final java.lang.String METADATA_KEY_GENRE = "android.hardware.radio.metadata.GENRE";
field public static final java.lang.String METADATA_KEY_ICON = "android.hardware.radio.metadata.ICON";
+ field public static final java.lang.String METADATA_KEY_PROGRAM_NAME = "android.hardware.radio.metadata.PROGRAM_NAME";
field public static final java.lang.String METADATA_KEY_RBDS_PTY = "android.hardware.radio.metadata.RBDS_PTY";
field public static final java.lang.String METADATA_KEY_RDS_PI = "android.hardware.radio.metadata.RDS_PI";
field public static final java.lang.String METADATA_KEY_RDS_PS = "android.hardware.radio.metadata.RDS_PS";
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 3a47fe1..008a1bf 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -15,8 +15,10 @@
LOCAL_PATH:= $(call my-dir)
# proto files used in incidentd to generate cppstream proto headers.
-PROTO_FILES:= frameworks/base/core/proto/android/util/log.proto \
- frameworks/base/core/proto/android/os/data.proto
+PROTO_FILES:= \
+ frameworks/base/core/proto/android/os/backtrace.proto \
+ frameworks/base/core/proto/android/os/data.proto \
+ frameworks/base/core/proto/android/util/log.proto
# ========= #
# incidentd #
@@ -46,6 +48,8 @@
libbase \
libbinder \
libcutils \
+ libdebuggerd_client \
+ libdumputils \
libincident \
liblog \
libprotobuf-cpp-lite \
@@ -119,6 +123,8 @@
libbase \
libbinder \
libcutils \
+ libdebuggerd_client \
+ libdumputils \
libincident \
liblog \
libprotobuf-cpp-lite \
diff --git a/cmds/incidentd/incidentd.rc b/cmds/incidentd/incidentd.rc
index 6dd8114..9c16a1c 100644
--- a/cmds/incidentd/incidentd.rc
+++ b/cmds/incidentd/incidentd.rc
@@ -16,6 +16,7 @@
class main
user incidentd
group incidentd log readproc
+ capabilities KILL SYS_PTRACE
on post-fs-data
# Create directory for incidentd
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 64da677..3570144 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -87,6 +87,35 @@
return NO_ERROR;
}
+status_t FdBuffer::readFully(int fd) {
+ mStartTime = uptimeMillis();
+
+ while (true) {
+ if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
+ // Don't let it get too big.
+ mTruncated = true;
+ VLOG("Truncating data");
+ break;
+ }
+ if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
+
+ ssize_t amt =
+ TEMP_FAILURE_RETRY(::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
+ if (amt < 0) {
+ VLOG("Fail to read %d: %s", fd, strerror(errno));
+ return -errno;
+ } else if (amt == 0) {
+ VLOG("Done reading %zu bytes", mBuffer.size());
+ // We're done.
+ break;
+ }
+ mBuffer.wp()->move(amt);
+ }
+
+ mFinishTime = uptimeMillis();
+ return NO_ERROR;
+}
+
status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
const bool isSysfs) {
struct pollfd pfds[] = {
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index 66a3de1..34ebcf5 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -41,6 +41,12 @@
status_t read(int fd, int64_t timeoutMs);
/**
+ * Read the data until we hit eof.
+ * Returns NO_ERROR if there were no errors.
+ */
+ status_t readFully(int fd);
+
+ /**
* Read processed results by streaming data to a parsing process, e.g. incident helper.
* The parsing process provides IO fds which are 'toFd' and 'fromFd'. The function
* reads original data in 'fd' and writes to parsing process through 'toFd', then it reads
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 46243c05..6dd76a8 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -18,13 +18,19 @@
#include "Section.h"
+#include <dirent.h>
+#include <errno.h>
#include <wait.h>
#include <mutex>
+#include <set>
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android/util/protobuf.h>
#include <binder/IServiceManager.h>
+#include <debuggerd/client.h>
+#include <dumputils/dump_utils.h>
#include <log/log_event_list.h>
#include <log/log_read.h>
#include <log/logprint.h>
@@ -33,6 +39,7 @@
#include "FdBuffer.h"
#include "Privacy.h"
#include "PrivacyBuffer.h"
+#include "frameworks/base/core/proto/android/os/backtrace.proto.h"
#include "frameworks/base/core/proto/android/os/data.proto.h"
#include "frameworks/base/core/proto/android/util/log.proto.h"
#include "incidentd_util.h"
@@ -95,6 +102,7 @@
return WriteFully(fd, buf, p - buf) ? NO_ERROR : -errno;
}
+// Reads data from FdBuffer and writes it to the requests file descriptor.
static status_t write_report_requests(const int id, const FdBuffer& buffer,
ReportRequestSet* requests) {
status_t err = -EBADF;
@@ -387,6 +395,7 @@
return NO_ERROR;
}
+
// ================================================================================
struct WorkerThreadData : public virtual RefBase {
const WorkerThreadSection* section;
@@ -413,7 +422,8 @@
WorkerThreadData::~WorkerThreadData() {}
// ================================================================================
-WorkerThreadSection::WorkerThreadSection(int id) : Section(id) {}
+WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs)
+ : Section(id, timeoutMs) {}
WorkerThreadSection::~WorkerThreadSection() {}
@@ -594,7 +604,7 @@
return readStatus;
}
- // TODO: wait for command here has one trade-off: the failed status of command won't be detected
+ // Waiting for command here has one trade-off: the failed status of command won't be detected
// until buffer timeout, but it has advatage on starting the data stream earlier.
status_t cmdStatus = wait_child(cmdPid);
status_t ihStatus = wait_child(ihPid);
@@ -694,7 +704,6 @@
}
status_t LogSection::BlockingCall(int pipeWriteFd) const {
- status_t err = NO_ERROR;
// Open log buffer and getting logs since last retrieved time if any.
unique_ptr<logger_list, void (*)(logger_list*)> loggers(
gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end()
@@ -705,15 +714,16 @@
if (android_logger_open(loggers.get(), mLogID) == NULL) {
ALOGW("LogSection %s: Can't get logger.", this->name.string());
- return err;
+ return NO_ERROR;
}
log_msg msg;
log_time lastTimestamp(0);
+ status_t err = NO_ERROR;
ProtoOutputStream proto;
while (true) { // keeps reading until logd buffer is fully read.
- status_t err = android_logger_list_read(loggers.get(), &msg);
+ err = android_logger_list_read(loggers.get(), &msg);
// err = 0 - no content, unexpected connection drop or EOF.
// err = +ive number - size of retrieved data from logger
// err = -ive number, OS supplied error _except_ for -EAGAIN
@@ -814,3 +824,133 @@
proto.flush(pipeWriteFd);
return err;
}
+
+// ================================================================================
+
+TombstoneSection::TombstoneSection(int id, const char* type, const int64_t timeoutMs)
+ : WorkerThreadSection(id, timeoutMs), mType(type) {
+ name += "tombstone ";
+ name += type;
+}
+
+TombstoneSection::~TombstoneSection() {}
+
+status_t TombstoneSection::BlockingCall(int pipeWriteFd) const {
+ std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+ if (proc.get() == nullptr) {
+ ALOGE("opendir /proc failed: %s\n", strerror(errno));
+ return -errno;
+ }
+
+ const std::set<int> hal_pids = get_interesting_hal_pids();
+
+ ProtoOutputStream proto;
+ struct dirent* d;
+ status_t err = NO_ERROR;
+ while ((d = readdir(proc.get()))) {
+ int pid = atoi(d->d_name);
+ if (pid <= 0) {
+ continue;
+ }
+
+ const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+ std::string exe;
+ if (!android::base::Readlink(link_name, &exe)) {
+ ALOGE("Can't read '%s': %s\n", link_name.c_str(), strerror(errno));
+ continue;
+ }
+
+ bool is_java_process;
+ if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+ if (mType != "java") continue;
+ // Don't bother dumping backtraces for the zygote.
+ if (IsZygote(pid)) {
+ VLOG("Skipping Zygote");
+ continue;
+ }
+
+ is_java_process = true;
+ } else if (should_dump_native_traces(exe.c_str())) {
+ if (mType != "native") continue;
+ is_java_process = false;
+ } else if (hal_pids.find(pid) != hal_pids.end()) {
+ if (mType != "hal") continue;
+ is_java_process = false;
+ } else {
+ // Probably a native process we don't care about, continue.
+ VLOG("Skipping %d", pid);
+ continue;
+ }
+
+ Fpipe dumpPipe;
+ if (!dumpPipe.init()) {
+ ALOGW("TombstoneSection '%s' failed to setup dump pipe", this->name.string());
+ err = -errno;
+ break;
+ }
+
+ const uint64_t start = Nanotime();
+ pid_t child = fork();
+ if (child < 0) {
+ ALOGE("Failed to fork child process");
+ break;
+ } else if (child == 0) {
+ // This is the child process.
+ close(dumpPipe.readFd());
+ const int ret = dump_backtrace_to_file_timeout(
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+ is_java_process ? 5 : 20, dumpPipe.writeFd());
+ if (ret == -1) {
+ if (errno == 0) {
+ ALOGW("Dumping failed for pid '%d', likely due to a timeout\n", pid);
+ } else {
+ ALOGE("Dumping failed for pid '%d': %s\n", pid, strerror(errno));
+ }
+ }
+ if (close(dumpPipe.writeFd()) != 0) {
+ ALOGW("TombstoneSection '%s' failed to close dump pipe writeFd: %d",
+ this->name.string(), errno);
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+ close(dumpPipe.writeFd());
+ // Parent process.
+ // Read from the pipe concurrently to avoid blocking the child.
+ FdBuffer buffer;
+ err = buffer.readFully(dumpPipe.readFd());
+ if (err != NO_ERROR) {
+ ALOGW("TombstoneSection '%s' failed to read stack dump: %d", this->name.string(), err);
+ if (close(dumpPipe.readFd()) != 0) {
+ ALOGW("TombstoneSection '%s' failed to close dump pipe readFd: %s",
+ this->name.string(), strerror(errno));
+ }
+ break;
+ }
+
+ auto dump = std::make_unique<char[]>(buffer.size());
+ auto iterator = buffer.data();
+ int i = 0;
+ while (iterator.hasNext()) {
+ dump[i] = iterator.next();
+ i++;
+ }
+ long long token = proto.start(android::os::BackTraceProto::TRACES);
+ proto.write(android::os::BackTraceProto::Stack::PID, pid);
+ proto.write(android::os::BackTraceProto::Stack::DUMP, dump.get(), i);
+ proto.write(android::os::BackTraceProto::Stack::DUMP_DURATION_NS,
+ static_cast<long long>(Nanotime() - start));
+ proto.end(token);
+
+ if (close(dumpPipe.readFd()) != 0) {
+ ALOGW("TombstoneSection '%s' failed to close dump pipe readFd: %d", this->name.string(),
+ errno);
+ err = -errno;
+ break;
+ }
+ }
+
+ proto.flush(pipeWriteFd);
+ return err;
+}
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 8294be1..19ef7ee 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -103,7 +103,7 @@
*/
class WorkerThreadSection : public Section {
public:
- WorkerThreadSection(int id);
+ WorkerThreadSection(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
virtual ~WorkerThreadSection();
virtual status_t Execute(ReportRequestSet* requests) const;
@@ -161,4 +161,18 @@
bool mBinary;
};
+/**
+ * Section that gets data from tombstoned.
+ */
+class TombstoneSection : public WorkerThreadSection {
+public:
+ TombstoneSection(int id, const char* type, const int64_t timeoutMs = 30000 /* 30 seconds */);
+ virtual ~TombstoneSection();
+
+ virtual status_t BlockingCall(int pipeWriteFd) const;
+
+private:
+ std::string mType;
+};
+
#endif // SECTIONS_H
diff --git a/cmds/incidentd/src/incidentd_util.cpp b/cmds/incidentd/src/incidentd_util.cpp
index c095f2b..c869c7a 100644
--- a/cmds/incidentd/src/incidentd_util.cpp
+++ b/cmds/incidentd/src/incidentd_util.cpp
@@ -80,6 +80,7 @@
close(output->writeFd());
return pid;
}
+
// ================================================================================
const char** varargs(const char* first, va_list rest) {
va_list copied_rest;
@@ -101,3 +102,11 @@
ret[numOfArgs] = NULL;
return ret;
}
+
+// ================================================================================
+const uint64_t NANOS_PER_SEC = 1000000000;
+uint64_t Nanotime() {
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return static_cast<uint64_t>(ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec);
+}
diff --git a/cmds/incidentd/src/incidentd_util.h b/cmds/incidentd/src/incidentd_util.h
index db7ec82..3f7df91 100644
--- a/cmds/incidentd/src/incidentd_util.h
+++ b/cmds/incidentd/src/incidentd_util.h
@@ -60,4 +60,9 @@
*/
const char** varargs(const char* first, va_list rest);
-#endif // INCIDENTD_UTIL_H
\ No newline at end of file
+/**
+ * Returns the current monotonic clock time in nanoseconds.
+ */
+uint64_t Nanotime();
+
+#endif // INCIDENTD_UTIL_H
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 8ecb538..7f0a26c 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -40,10 +40,6 @@
src/external/SubsystemSleepStatePuller.cpp \
src/external/ResourceHealthManagerPuller.cpp \
src/external/ResourceThermalManagerPuller.cpp \
- src/external/CpuTimePerUidPuller.cpp \
- src/external/CpuTimePerUidFreqPuller.cpp \
- src/external/KernelUidCpuActiveTimeReader.cpp \
- src/external/KernelUidCpuClusterTimeReader.cpp \
src/external/StatsPullerManagerImpl.cpp \
src/external/puller_util.cpp \
src/logd/LogEvent.cpp \
@@ -203,7 +199,9 @@
tests/e2e/MetricConditionLink_e2e_test.cpp \
tests/e2e/Attribution_e2e_test.cpp \
tests/e2e/GaugeMetric_e2e_test.cpp \
- tests/e2e/DimensionInCondition_e2e_test.cpp
+ tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \
+ tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \
+ tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
LOCAL_STATIC_LIBRARIES := \
$(statsd_common_static_libraries) \
@@ -251,11 +249,32 @@
LOCAL_MODULE := statsd_benchmark
LOCAL_SRC_FILES := $(statsd_common_src) \
+ src/atom_field_options.proto \
+ src/atoms.proto \
+ src/stats_log.proto \
benchmark/main.cpp \
benchmark/hello_world_benchmark.cpp \
benchmark/log_event_benchmark.cpp \
benchmark/stats_write_benchmark.cpp \
- benchmark/filter_value_benchmark.cpp
+ benchmark/filter_value_benchmark.cpp \
+ benchmark/get_dimensions_for_condition_benchmark.cpp \
+ benchmark/metric_util.cpp \
+ benchmark/duration_metric_benchmark.cpp
+
+LOCAL_STATIC_LIBRARIES := \
+ $(statsd_common_static_libraries)
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := full
+
+LOCAL_PROTOC_FLAGS := \
+ -Iexternal/protobuf/src
+
+LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
+ libprotobuf-cpp-full
+
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ platformprotoslite
LOCAL_C_INCLUDES := $(statsd_common_c_includes)
@@ -289,4 +308,4 @@
statsd_common_shared_libraries:=
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/cmds/statsd/benchmark/duration_metric_benchmark.cpp b/cmds/statsd/benchmark/duration_metric_benchmark.cpp
new file mode 100644
index 0000000..2631009
--- /dev/null
+++ b/cmds/statsd/benchmark/duration_metric_benchmark.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vector>
+#include "benchmark/benchmark.h"
+#include "FieldValue.h"
+#include "HashableDimensionKey.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+#include "metric_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::vector;
+
+static StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto screenIsOffPredicate = CreateScreenIsOffPredicate();
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+ {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = screenIsOffPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+ auto combinationPredicate = config.add_predicate();
+ combinationPredicate->set_id(StringToId("CombinationPredicate"));
+ combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
+ addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
+ auto dimensionWhat = metric->mutable_dimensions_in_what();
+ dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensionWhat->add_child()->set_field(2); // job name field.
+ *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+static StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *dimensions = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ auto screenIsOffPredicate = CreateScreenIsOffPredicate();
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = screenIsOffPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+ auto combinationPredicate = config.add_predicate();
+ combinationPredicate->set_id(StringToId("CombinationPredicate"));
+ combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
+ addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
+ *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+
+ auto links = metric->add_links();
+ links->set_condition(isSyncingPredicate.id());
+ *links->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *links->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+static void BM_DurationMetricNoLink(benchmark::State& state) {
+ ConfigKey cfgKey;
+ auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
+ DurationMetric::SUM, false);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 11));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 40));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 102));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 450));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 650));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 100));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + bucketSizeNs + 640));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 650));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 10));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 200));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 300));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 401));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ while (state.KeepRunning()) {
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+ }
+}
+
+BENCHMARK(BM_DurationMetricNoLink);
+
+
+static void BM_DurationMetricLink(benchmark::State& state) {
+ ConfigKey cfgKey;
+ auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition(
+ DurationMetric::SUM, false);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions3 = {
+ CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 55));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 120));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 121));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 450));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 501));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 100));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",
+ bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(
+ CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs - 2));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 110));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 300));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 550));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 800));
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ sortLogEventsByTimestamp(&events);
+
+ while (state.KeepRunning()) {
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+ }
+}
+
+BENCHMARK(BM_DurationMetricLink);
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/benchmark/filter_value_benchmark.cpp b/cmds/statsd/benchmark/filter_value_benchmark.cpp
index b9ddf36..66c4def 100644
--- a/cmds/statsd/benchmark/filter_value_benchmark.cpp
+++ b/cmds/statsd/benchmark/filter_value_benchmark.cpp
@@ -18,6 +18,7 @@
#include "FieldValue.h"
#include "HashableDimensionKey.h"
#include "logd/LogEvent.h"
+#include "stats_log_util.h"
namespace android {
namespace os {
@@ -25,17 +26,29 @@
using std::vector;
+static void createLogEventAndMatcher(LogEvent* event, FieldMatcher *field_matcher) {
+ AttributionNodeInternal node;
+ node.set_uid(100);
+ node.set_tag("LOCATION");
+
+ std::vector<AttributionNodeInternal> nodes = {node, node};
+ event->write(nodes);
+ event->write(3.2f);
+ event->write("LOCATION");
+ event->write((int64_t)990);
+ event->init();
+
+ field_matcher->set_field(1);
+ auto child = field_matcher->add_child();
+ child->set_field(1);
+ child->set_position(FIRST);
+ child->add_child()->set_field(1);
+}
+
static void BM_FilterValue(benchmark::State& state) {
LogEvent event(1, 100000);
- event.write(3.2f);
- event.write("LOCATION");
- event.write((int64_t)990);
- event.init();
-
FieldMatcher field_matcher;
- field_matcher.set_field(1);
- field_matcher.add_child()->set_field(2);
- field_matcher.add_child()->set_field(3);
+ createLogEventAndMatcher(&event, &field_matcher);
std::vector<Matcher> matchers;
translateFieldMatcher(field_matcher, &matchers);
@@ -48,6 +61,22 @@
BENCHMARK(BM_FilterValue);
+static void BM_FilterValue2(benchmark::State& state) {
+ LogEvent event(1, 100000);
+ FieldMatcher field_matcher;
+ createLogEventAndMatcher(&event, &field_matcher);
+
+ std::vector<Matcher> matchers;
+ translateFieldMatcher(field_matcher, &matchers);
+
+ while (state.KeepRunning()) {
+ HashableDimensionKey output;
+ filterValues(matchers, event.getValues(), &output);
+ }
+}
+
+BENCHMARK(BM_FilterValue2);
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp b/cmds/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp
new file mode 100644
index 0000000..2a4403e
--- /dev/null
+++ b/cmds/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vector>
+#include "benchmark/benchmark.h"
+#include "FieldValue.h"
+#include "HashableDimensionKey.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::vector;
+
+static void createLogEventAndLink(LogEvent* event, Metric2Condition *link) {
+ AttributionNodeInternal node;
+ node.set_uid(100);
+ node.set_tag("LOCATION");
+
+ std::vector<AttributionNodeInternal> nodes = {node, node};
+ event->write(nodes);
+ event->write(3.2f);
+ event->write("LOCATION");
+ event->write((int64_t)990);
+ event->init();
+
+ link->conditionId = 1;
+
+ FieldMatcher field_matcher;
+ field_matcher.set_field(event->GetTagId());
+ auto child = field_matcher.add_child();
+ child->set_field(1);
+ child->set_position(FIRST);
+ child->add_child()->set_field(1);
+
+ translateFieldMatcher(field_matcher, &link->metricFields);
+ field_matcher.set_field(event->GetTagId() + 1);
+ translateFieldMatcher(field_matcher, &link->conditionFields);
+}
+
+static void BM_GetDimensionInCondition(benchmark::State& state) {
+ Metric2Condition link;
+ LogEvent event(1, 100000);
+ createLogEventAndLink(&event, &link);
+
+ while (state.KeepRunning()) {
+ HashableDimensionKey output;
+ getDimensionForCondition(event.getValues(), link, &output);
+ }
+}
+
+BENCHMARK(BM_GetDimensionInCondition);
+
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/benchmark/metric_util.cpp b/cmds/statsd/benchmark/metric_util.cpp
new file mode 100644
index 0000000..b67764b
--- /dev/null
+++ b/cmds/statsd/benchmark/metric_util.cpp
@@ -0,0 +1,394 @@
+// 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.
+
+#include "metric_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(atomId);
+ return atom_matcher;
+}
+
+AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name,
+ ScheduledJobStateChanged::State state) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(3); // State field.
+ field_value_matcher->set_eq_int(state);
+ return atom_matcher;
+}
+
+AtomMatcher CreateStartScheduledJobAtomMatcher() {
+ return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobStart",
+ ScheduledJobStateChanged::STARTED);
+}
+
+AtomMatcher CreateFinishScheduledJobAtomMatcher() {
+ return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobFinish",
+ ScheduledJobStateChanged::FINISHED);
+}
+
+AtomMatcher CreateScreenBrightnessChangedAtomMatcher() {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId("ScreenBrightnessChanged"));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::SCREEN_BRIGHTNESS_CHANGED);
+ return atom_matcher;
+}
+
+AtomMatcher CreateUidProcessStateChangedAtomMatcher() {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId("UidProcessStateChanged"));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::UID_PROCESS_STATE_CHANGED);
+ return atom_matcher;
+}
+
+AtomMatcher CreateWakelockStateChangedAtomMatcher(const string& name,
+ WakelockStateChanged::State state) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::WAKELOCK_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(4); // State field.
+ field_value_matcher->set_eq_int(state);
+ return atom_matcher;
+}
+
+AtomMatcher CreateAcquireWakelockAtomMatcher() {
+ return CreateWakelockStateChangedAtomMatcher("AcquireWakelock", WakelockStateChanged::ACQUIRE);
+}
+
+AtomMatcher CreateReleaseWakelockAtomMatcher() {
+ return CreateWakelockStateChangedAtomMatcher("ReleaseWakelock", WakelockStateChanged::RELEASE);
+}
+
+AtomMatcher CreateScreenStateChangedAtomMatcher(
+ const string& name, android::view::DisplayStateEnum state) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::SCREEN_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(1); // State field.
+ field_value_matcher->set_eq_int(state);
+ return atom_matcher;
+}
+
+AtomMatcher CreateScreenTurnedOnAtomMatcher() {
+ return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn",
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+}
+
+AtomMatcher CreateScreenTurnedOffAtomMatcher() {
+ return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff",
+ ::android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
+}
+
+AtomMatcher CreateSyncStateChangedAtomMatcher(
+ const string& name, SyncStateChanged::State state) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::SYNC_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(3); // State field.
+ field_value_matcher->set_eq_int(state);
+ return atom_matcher;
+}
+
+AtomMatcher CreateSyncStartAtomMatcher() {
+ return CreateSyncStateChangedAtomMatcher("SyncStart", SyncStateChanged::ON);
+}
+
+AtomMatcher CreateSyncEndAtomMatcher() {
+ return CreateSyncStateChangedAtomMatcher("SyncEnd", SyncStateChanged::OFF);
+}
+
+AtomMatcher CreateActivityForegroundStateChangedAtomMatcher(
+ const string& name, ActivityForegroundStateChanged::Activity activity) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(4); // Activity field.
+ field_value_matcher->set_eq_int(activity);
+ return atom_matcher;
+}
+
+AtomMatcher CreateMoveToBackgroundAtomMatcher() {
+ return CreateActivityForegroundStateChangedAtomMatcher(
+ "MoveToBackground", ActivityForegroundStateChanged::MOVE_TO_BACKGROUND);
+}
+
+AtomMatcher CreateMoveToForegroundAtomMatcher() {
+ return CreateActivityForegroundStateChangedAtomMatcher(
+ "MoveToForeground", ActivityForegroundStateChanged::MOVE_TO_FOREGROUND);
+}
+
+Predicate CreateScheduledJobPredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("ScheduledJobRunningPredicate"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("ScheduledJobStart"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("ScheduledJobFinish"));
+ return predicate;
+}
+
+Predicate CreateBatterySaverModePredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("BatterySaverIsOn"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("BatterySaverModeStart"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("BatterySaverModeStop"));
+ return predicate;
+}
+
+Predicate CreateScreenIsOnPredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("ScreenIsOn"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOn"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOff"));
+ return predicate;
+}
+
+Predicate CreateScreenIsOffPredicate() {
+ Predicate predicate;
+ predicate.set_id(1111123);
+ predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOff"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOn"));
+ return predicate;
+}
+
+Predicate CreateHoldingWakelockPredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("HoldingWakelock"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("AcquireWakelock"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("ReleaseWakelock"));
+ return predicate;
+}
+
+Predicate CreateIsSyncingPredicate() {
+ Predicate predicate;
+ predicate.set_id(33333333333333);
+ predicate.mutable_simple_predicate()->set_start(StringToId("SyncStart"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("SyncEnd"));
+ return predicate;
+}
+
+Predicate CreateIsInBackgroundPredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("IsInBackground"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("MoveToBackground"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("MoveToForeground"));
+ return predicate;
+}
+
+void addPredicateToPredicateCombination(const Predicate& predicate,
+ Predicate* combinationPredicate) {
+ combinationPredicate->mutable_combination()->add_predicate(predicate.id());
+}
+
+FieldMatcher CreateAttributionUidDimensions(const int atomId,
+ const std::vector<Position>& positions) {
+ FieldMatcher dimensions;
+ dimensions.set_field(atomId);
+ for (const auto position : positions) {
+ auto child = dimensions.add_child();
+ child->set_field(1);
+ child->set_position(position);
+ child->add_child()->set_field(1);
+ }
+ return dimensions;
+}
+
+FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId,
+ const std::vector<Position>& positions) {
+ FieldMatcher dimensions;
+ dimensions.set_field(atomId);
+ for (const auto position : positions) {
+ auto child = dimensions.add_child();
+ child->set_field(1);
+ child->set_position(position);
+ child->add_child()->set_field(1);
+ child->add_child()->set_field(2);
+ }
+ return dimensions;
+}
+
+FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields) {
+ FieldMatcher dimensions;
+ dimensions.set_field(atomId);
+ for (const int field : fields) {
+ dimensions.add_child()->set_field(field);
+ }
+ return dimensions;
+}
+
+std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
+ const android::view::DisplayStateEnum state, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
+ event->write(state);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
+ int level, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
+ (event->write(level));
+ event->init();
+ return event;
+
+}
+
+std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
+ const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
+ event->write(attributions);
+ event->write(jobName);
+ event->write(state);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs) {
+ return CreateScheduledJobStateChangedEvent(
+ attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
+}
+
+// Create log event when scheduled job finishes.
+std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs) {
+ return CreateScheduledJobStateChangedEvent(
+ attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+ const WakelockStateChanged::State state, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
+ event->write(attributions);
+ event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
+ event->write(wakelockName);
+ event->write(state);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+ uint64_t timestampNs) {
+ return CreateWakelockStateChangedEvent(
+ attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+ uint64_t timestampNs) {
+ return CreateWakelockStateChangedEvent(
+ attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
+ const int uid, const ActivityForegroundStateChanged::Activity activity, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(
+ android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
+ event->write(uid);
+ event->write("pkg_name");
+ event->write("class_name");
+ event->write(activity);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
+ return CreateActivityForegroundStateChangedEvent(
+ uid, ActivityForegroundStateChanged::MOVE_TO_BACKGROUND, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
+ return CreateActivityForegroundStateChangedEvent(
+ uid, ActivityForegroundStateChanged::MOVE_TO_FOREGROUND, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& name,
+ const SyncStateChanged::State state, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
+ event->write(attributions);
+ event->write(name);
+ event->write(state);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateSyncStartEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& name,
+ uint64_t timestampNs) {
+ return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
+}
+
+std::unique_ptr<LogEvent> CreateSyncEndEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& name,
+ uint64_t timestampNs) {
+ return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
+}
+
+sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
+ const ConfigKey& key) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ sp<StatsLogProcessor> processor = new StatsLogProcessor(
+ uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){});
+ processor->OnConfigUpdated(key, config);
+ return processor;
+}
+
+AttributionNodeInternal CreateAttribution(const int& uid, const string& tag) {
+ AttributionNodeInternal attribution;
+ attribution.set_uid(uid);
+ attribution.set_tag(tag);
+ return attribution;
+}
+
+void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) {
+ std::sort(events->begin(), events->end(),
+ [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) {
+ return a->GetElapsedTimestampNs() < b->GetElapsedTimestampNs();
+ });
+}
+
+int64_t StringToId(const string& str) {
+ return static_cast<int64_t>(std::hash<std::string>()(str));
+}
+
+
+} // namespace statsd
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/benchmark/metric_util.h b/cmds/statsd/benchmark/metric_util.h
new file mode 100644
index 0000000..9b28d60
--- /dev/null
+++ b/cmds/statsd/benchmark/metric_util.h
@@ -0,0 +1,161 @@
+// 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.
+
+#pragma once
+
+#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/StatsLogProcessor.h"
+#include "src/logd/LogEvent.h"
+#include "statslog.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Create AtomMatcher proto to simply match a specific atom type.
+AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
+
+// Create AtomMatcher proto for scheduled job state changed.
+AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
+
+// Create AtomMatcher proto for starting a scheduled job.
+AtomMatcher CreateStartScheduledJobAtomMatcher();
+
+// Create AtomMatcher proto for a scheduled job is done.
+AtomMatcher CreateFinishScheduledJobAtomMatcher();
+
+// Create AtomMatcher proto for screen brightness state changed.
+AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
+
+// Create AtomMatcher proto for acquiring wakelock.
+AtomMatcher CreateAcquireWakelockAtomMatcher();
+
+// Create AtomMatcher proto for releasing wakelock.
+AtomMatcher CreateReleaseWakelockAtomMatcher() ;
+
+// Create AtomMatcher proto for screen turned on.
+AtomMatcher CreateScreenTurnedOnAtomMatcher();
+
+// Create AtomMatcher proto for screen turned off.
+AtomMatcher CreateScreenTurnedOffAtomMatcher();
+
+// Create AtomMatcher proto for app sync turned on.
+AtomMatcher CreateSyncStartAtomMatcher();
+
+// Create AtomMatcher proto for app sync turned off.
+AtomMatcher CreateSyncEndAtomMatcher();
+
+// Create AtomMatcher proto for app sync moves to background.
+AtomMatcher CreateMoveToBackgroundAtomMatcher();
+
+// Create AtomMatcher proto for app sync moves to foreground.
+AtomMatcher CreateMoveToForegroundAtomMatcher();
+
+// Create Predicate proto for screen is off.
+Predicate CreateScreenIsOffPredicate();
+
+// Create Predicate proto for a running scheduled job.
+Predicate CreateScheduledJobPredicate();
+
+// Create Predicate proto for holding wakelock.
+Predicate CreateHoldingWakelockPredicate();
+
+// Create a Predicate proto for app syncing.
+Predicate CreateIsSyncingPredicate();
+
+// Create a Predicate proto for app is in background.
+Predicate CreateIsInBackgroundPredicate();
+
+// Add a predicate to the predicate combination.
+void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
+
+// Create dimensions from primitive fields.
+FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields);
+
+// Create dimensions by attribution uid and tag.
+FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId,
+ const std::vector<Position>& positions);
+
+// Create dimensions by attribution uid only.
+FieldMatcher CreateAttributionUidDimensions(const int atomId,
+ const std::vector<Position>& positions);
+
+// Create log event for screen state changed.
+std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
+ const android::view::DisplayStateEnum state, uint64_t timestampNs);
+
+// Create log event for screen brightness state changed.
+std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
+ int level, uint64_t timestampNs);
+
+// Create log event when scheduled job starts.
+std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs);
+
+// Create log event when scheduled job finishes.
+std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs);
+
+// Create log event for app moving to background.
+std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs);
+
+// Create log event for app moving to foreground.
+std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs);
+
+// Create log event when the app sync starts.
+std::unique_ptr<LogEvent> CreateSyncStartEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& name,
+ uint64_t timestampNs);
+
+// Create log event when the app sync ends.
+std::unique_ptr<LogEvent> CreateSyncEndEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& name,
+ uint64_t timestampNs);
+
+// Create log event when the app sync ends.
+std::unique_ptr<LogEvent> CreateAppCrashEvent(
+ const int uid, uint64_t timestampNs);
+
+// Create log event for acquiring wakelock.
+std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+ uint64_t timestampNs);
+
+// Create log event for releasing wakelock.
+std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+ uint64_t timestampNs);
+
+// Create log event for releasing wakelock.
+std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
+ int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
+
+// Helper function to create an AttributionNodeInternal proto.
+AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
+
+// Create a statsd log event processor upon the start time in seconds, config and key.
+sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
+ const ConfigKey& key);
+
+// Util function to sort the log events by timestamp.
+void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
+
+int64_t StringToId(const string& str);
+
+} // namespace statsd
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index b541612..0c9b701 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -205,6 +205,29 @@
}
}
+bool equalDimensions(const std::vector<Matcher>& dimension_a,
+ const std::vector<Matcher>& dimension_b) {
+ bool eq = dimension_a.size() == dimension_b.size();
+ for (size_t i = 0; eq && i < dimension_a.size(); ++i) {
+ if (dimension_b[i] != dimension_a[i]) {
+ eq = false;
+ }
+ }
+ return eq;
+}
+
+bool HasPositionANY(const FieldMatcher& matcher) {
+ if (matcher.has_position() && matcher.position() == Position::ANY) {
+ return true;
+ }
+ for (const auto& child : matcher.child()) {
+ if (HasPositionANY(child)) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 621d0be9..0e3ae06 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -336,11 +336,16 @@
Value mValue;
};
+bool HasPositionANY(const FieldMatcher& matcher);
+
bool isAttributionUidField(const FieldValue& value);
void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
bool isAttributionUidField(const Field& field, const Value& value);
+
+bool equalDimensions(const std::vector<Matcher>& dimension_a,
+ const std::vector<Matcher>& dimension_b);
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index cc706313..d0c8311 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -59,6 +59,33 @@
return JenkinsHashWhiten(hash);
}
+bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values,
+ HashableDimensionKey* output) {
+ for (size_t i = 0; i < matcherFields.size(); ++i) {
+ const auto& matcher = matcherFields[i];
+ bool found = false;
+ for (const auto& value : values) {
+ // TODO: potential optimization here to break early because all fields are naturally
+ // sorted.
+ if (value.mField.matches(matcher)) {
+ output->addValue(value);
+ output->mutableValue(i)->mField.setTag(value.mField.getTag());
+ output->mutableValue(i)->mField.setField(value.mField.getField() & matcher.mMask);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(),
+ matcher.mMatcher.getField());
+ return false;
+ }
+ }
+
+ return true;
+}
+
// Filter fields using the matchers and output the results as a HashableDimensionKey.
// Note: HashableDimensionKey is just a wrapper for vector<FieldValue>
bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values,
@@ -168,22 +195,21 @@
void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
const Metric2Condition& links,
- vector<HashableDimensionKey>* conditionDimension) {
+ HashableDimensionKey* conditionDimension) {
// Get the dimension first by using dimension from what.
filterValues(links.metricFields, eventValues, conditionDimension);
- // Then replace the field with the dimension from condition.
- for (auto& dim : *conditionDimension) {
- size_t count = dim.getValues().size();
- if (count != links.conditionFields.size()) {
- // ALOGE("WTF condition link is bad");
- return;
- }
+ size_t count = conditionDimension->getValues().size();
+ if (count != links.conditionFields.size()) {
+ // ALOGE("WTF condition link is bad");
+ return;
+ }
- for (size_t i = 0; i < count; i++) {
- dim.mutableValue(i)->mField.setField(links.conditionFields[i].mMatcher.getField());
- dim.mutableValue(i)->mField.setTag(links.conditionFields[i].mMatcher.getTag());
- }
+ for (size_t i = 0; i < count; i++) {
+ conditionDimension->mutableValue(i)->mField.setField(
+ links.conditionFields[i].mMatcher.getField());
+ conditionDimension->mutableValue(i)->mField.setTag(
+ links.conditionFields[i].mMatcher.getTag());
}
}
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index 57bdf68..4cfed88 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -65,10 +65,6 @@
std::string toString() const;
- inline const char* c_str() const {
- return toString().c_str();
- }
-
bool operator==(const HashableDimensionKey& that) const;
bool operator<(const HashableDimensionKey& that) const;
@@ -104,6 +100,10 @@
return mDimensionKeyInCondition;
}
+ inline void setDimensionKeyInCondition(const HashableDimensionKey& key) {
+ mDimensionKeyInCondition = key;
+ }
+
bool hasDimensionKeyInCondition() const {
return mDimensionKeyInCondition.getValues().size() > 0;
}
@@ -112,9 +112,6 @@
bool operator<(const MetricDimensionKey& that) const;
- inline const char* c_str() const {
- return toString().c_str();
- }
private:
HashableDimensionKey mDimensionKeyInWhat;
HashableDimensionKey mDimensionKeyInCondition;
@@ -134,6 +131,9 @@
*/
bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
std::vector<HashableDimensionKey>* output);
+// This function is used when there is at most one output dimension key. (no ANY matcher)
+bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
+ HashableDimensionKey* output);
/**
* Filter the values from FieldValues using the matchers.
@@ -146,7 +146,7 @@
void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
const Metric2Condition& links,
- std::vector<HashableDimensionKey>* conditionDimension);
+ HashableDimensionKey* conditionDimension);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index a672ab4..8db8200 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -123,10 +123,21 @@
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
- FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricWithLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition);
+
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition);
+
+
+
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition);
+
};
} // namespace statsd
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index e0a1299..30896e6 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -177,11 +177,6 @@
/**
* Print the event log.
*/
- status_t cmd_print_stats_log(FILE* out, const Vector<String8>& args);
-
- /**
- * Print the event log.
- */
status_t cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args);
/**
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index fa96e11..9bfbd38 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1489,7 +1489,7 @@
* Note that isolated process uid time should be attributed to host uids.
*/
message CpuTimePerUid {
- optional uint64 uid = 1;
+ optional int32 uid = 1;
optional uint64 user_time_millis = 2;
optional uint64 sys_time_millis = 3;
}
@@ -1500,8 +1500,8 @@
* For each uid, we order the time by descending frequencies.
*/
message CpuTimePerUidFreq {
- optional uint64 uid = 1;
- optional uint64 freq_idx = 2;
+ optional int32 uid = 1;
+ optional uint32 freq_index = 2;
optional uint64 time_millis = 3;
}
@@ -1634,10 +1634,8 @@
* The file contains a monotonically increasing count of time for a single boot.
*/
message CpuActiveTime {
- optional uint64 uid = 1;
- optional uint32 cluster_number = 2;
- optional uint64 idx = 3;
- optional uint64 time_millis = 4;
+ optional int32 uid = 1;
+ optional uint64 time_millis = 2;
}
/**
@@ -1650,8 +1648,8 @@
* The file contains a monotonically increasing count of time for a single boot.
*/
message CpuClusterTime {
- optional uint64 uid = 1;
- optional uint64 idx = 2;
+ optional int32 uid = 1;
+ optional int32 cluster_index = 2;
optional uint64 time_millis = 3;
}
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 13a2b7b..3661d2b 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -91,6 +91,9 @@
if (allConditionTrackers[childIndex]->isSliced()) {
setSliced(true);
+ mSlicedChildren.push_back(childIndex);
+ } else {
+ mUnSlicedChildren.push_back(childIndex);
}
mChildren.push_back(childIndex);
mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(),
@@ -107,13 +110,19 @@
void CombinationConditionTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
- const std::vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
+ const std::vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
+ vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
// So far, this is fine as there is at most one child having sliced output.
for (const int childIndex : mChildren) {
if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
allConditions[childIndex]->isConditionMet(conditionParameters, allConditions,
- dimensionFields, conditionCache,
+ dimensionFields,
+ isSubOutputDimensionFields,
+ isPartialLink,
+ conditionCache,
dimensionsKeySet);
}
}
@@ -150,7 +159,11 @@
nonSlicedConditionCache[mIndex] = mNonSlicedConditionState;
conditionChangedCache[mIndex] = nonSlicedChanged;
+ mUnSlicedPart = newCondition;
} else {
+ mUnSlicedPart = evaluateCombinationCondition(
+ mUnSlicedChildren, mLogicalOperation, nonSlicedConditionCache);
+
for (const int childIndex : mChildren) {
// If any of the sliced condition in children condition changes, the combination
// condition may be changed too.
@@ -168,13 +181,14 @@
ConditionState CombinationConditionTracker::getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const std::vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
vector<ConditionState> conditionCache(allConditions.size(), ConditionState::kNotEvaluated);
// So far, this is fine as there is at most one child having sliced output.
for (const int childIndex : mChildren) {
conditionCache[childIndex] = conditionCache[childIndex] |
allConditions[childIndex]->getMetConditionDimension(
- allConditions, dimensionFields, dimensionsKeySet);
+ allConditions, dimensionFields, isSubOutputDimensionFields, dimensionsKeySet);
}
evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
if (conditionCache[mIndex] == ConditionState::kTrue && dimensionsKeySet.empty()) {
@@ -183,6 +197,18 @@
return conditionCache[mIndex];
}
+bool CombinationConditionTracker::equalOutputDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ const vector<Matcher>& dimensions) const {
+ if (mSlicedChildren.size() != 1 ||
+ mSlicedChildren.front() >= (int)allConditions.size() ||
+ mLogicalOperation != LogicalOperation::AND) {
+ return false;
+ }
+ const sp<ConditionTracker>& slicedChild = allConditions.at(mSlicedChildren.front());
+ return slicedChild->equalOutputDimensions(allConditions, dimensions);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index 7b8dc6b..481cb20 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -44,12 +44,15 @@
void isConditionMet(const ConditionKey& conditionParameters,
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
std::vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
ConditionState getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
// Only one child predicate can have dimension.
@@ -63,6 +66,7 @@
}
return nullptr;
}
+
// Only one child predicate can have dimension.
const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
const std::vector<sp<ConditionTracker>>& allConditions) const override {
@@ -75,6 +79,26 @@
return nullptr;
}
+ bool IsSimpleCondition() const override { return false; }
+
+ bool IsChangedDimensionTrackable() const override {
+ return mLogicalOperation == LogicalOperation::AND && mSlicedChildren.size() == 1;
+ }
+
+ bool equalOutputDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ const vector<Matcher>& dimensions) const override;
+
+ void getTrueSlicedDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ std::set<HashableDimensionKey>* dimensions) const override {
+ if (mSlicedChildren.size() == 1) {
+ return allConditions[mSlicedChildren.front()]->getTrueSlicedDimensions(
+ allConditions, dimensions);
+ }
+ }
+
+
private:
LogicalOperation mLogicalOperation;
@@ -83,6 +107,10 @@
// map the name to object. We don't want to store smart pointers to children, because it
// increases the risk of circular dependency and memory leak.
std::vector<int> mChildren;
+
+ std::vector<int> mSlicedChildren;
+ std::vector<int> mUnSlicedChildren;
+
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 856a3a0..1f4266b 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -84,18 +84,28 @@
// condition.
// [allConditions]: all condition trackers. This is needed because the condition evaluation is
// done recursively
+ // [dimensionFields]: the needed dimension fields which should be all or subset of the condition
+ // tracker output dimension.
+ // [isSubOutputDimensionFields]: true if the needed dimension fields which is strictly subset of
+ // the condition tracker output dimension.
+ // [isPartialLink]: true if the link specified by 'conditionParameters' contains all the fields
+ // in the condition tracker output dimension.
// [conditionCache]: the cache holding the condition evaluation values.
// [dimensionsKeySet]: the dimensions where the sliced condition is true. For combination
// condition, it assumes that only one child predicate is sliced.
virtual void isConditionMet(
const ConditionKey& conditionParameters,
const std::vector<sp<ConditionTracker>>& allConditions,
- const vector<Matcher>& dimensionFields, std::vector<ConditionState>& conditionCache,
+ const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
+ std::vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
virtual ConditionState getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
// return the list of LogMatchingTracker index that this ConditionTracker uses.
@@ -107,7 +117,7 @@
mSliced = mSliced | sliced;
}
- bool isSliced() const {
+ inline bool isSliced() const {
return mSliced;
}
@@ -116,6 +126,26 @@
virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
const std::vector<sp<ConditionTracker>>& allConditions) const = 0;
+ inline int64_t getConditionId() const {
+ return mConditionId;
+ }
+
+ virtual void getTrueSlicedDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ std::set<HashableDimensionKey>* dimensions) const = 0;
+
+ virtual bool IsChangedDimensionTrackable() const = 0;
+
+ virtual bool IsSimpleCondition() const = 0;
+
+ virtual bool equalOutputDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ const vector<Matcher>& dimensions) const = 0;
+
+ inline ConditionState getUnSlicedPartConditionState() const {
+ return mUnSlicedPart;
+ }
+
protected:
const int64_t mConditionId;
@@ -131,6 +161,7 @@
ConditionState mNonSlicedConditionState;
bool mSliced;
+ ConditionState mUnSlicedPart;
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/ConditionWizard.cpp b/cmds/statsd/src/condition/ConditionWizard.cpp
index 952b0cc..23a9d37 100644
--- a/cmds/statsd/src/condition/ConditionWizard.cpp
+++ b/cmds/statsd/src/condition/ConditionWizard.cpp
@@ -26,19 +26,24 @@
ConditionState ConditionWizard::query(const int index, const ConditionKey& parameters,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
vector<ConditionState> cache(mAllConditions.size(), ConditionState::kNotEvaluated);
mAllConditions[index]->isConditionMet(
- parameters, mAllConditions, dimensionFields, cache, *dimensionKeySet);
+ parameters, mAllConditions, dimensionFields, isSubOutputDimensionFields, isPartialLink,
+ cache, *dimensionKeySet);
return cache[index];
}
ConditionState ConditionWizard::getMetConditionDimension(
const int index, const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const {
return mAllConditions[index]->getMetConditionDimension(mAllConditions, dimensionFields,
- *dimensionsKeySet);
+ isSubOutputDimensionFields,
+ *dimensionsKeySet);
}
const set<HashableDimensionKey>* ConditionWizard::getChangedToTrueDimensions(
@@ -51,6 +56,30 @@
return mAllConditions[index]->getChangedToFalseDimensions(mAllConditions);
}
+bool ConditionWizard::IsChangedDimensionTrackable(const int index) {
+ if (index >= 0 && index < (int)mAllConditions.size()) {
+ return mAllConditions[index]->IsChangedDimensionTrackable();
+ } else {
+ return false;
+ }
+}
+
+bool ConditionWizard::IsSimpleCondition(const int index) {
+ if (index >= 0 && index < (int)mAllConditions.size()) {
+ return mAllConditions[index]->IsSimpleCondition();
+ } else {
+ return false;
+ }
+}
+
+bool ConditionWizard::equalOutputDimensions(const int index, const vector<Matcher>& dimensions) {
+ if (index >= 0 && index < (int)mAllConditions.size()) {
+ return mAllConditions[index]->equalOutputDimensions(mAllConditions, dimensions);
+ } else {
+ return false;
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h
index fcfdc2a..a6f88af 100644
--- a/cmds/statsd/src/condition/ConditionWizard.h
+++ b/cmds/statsd/src/condition/ConditionWizard.h
@@ -41,15 +41,30 @@
// the conditionParameters contains the parameters for it's children SimpleConditionTrackers.
virtual ConditionState query(const int conditionIndex, const ConditionKey& conditionParameters,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
std::unordered_set<HashableDimensionKey>* dimensionKeySet);
virtual ConditionState getMetConditionDimension(
const int index, const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const;
virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(const int index) const;
virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
const int index) const;
+ bool equalOutputDimensions(const int index, const vector<Matcher>& dimensions);
+
+ bool IsChangedDimensionTrackable(const int index);
+ bool IsSimpleCondition(const int index);
+
+ ConditionState getUnSlicedPartConditionState(const int index) {
+ return mAllConditions[index]->getUnSlicedPartConditionState();
+ }
+ void getTrueSlicedDimensions(const int index,
+ std::set<HashableDimensionKey>* trueDimensions) const {
+ return mAllConditions[index]->getTrueSlicedDimensions(mAllConditions, trueDimensions);
+ }
private:
std::vector<sp<ConditionTracker>> mAllConditions;
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 9e27a8b..4913aef 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -34,7 +34,7 @@
const ConfigKey& key, const int64_t& id, const int index,
const SimplePredicate& simplePredicate,
const unordered_map<int64_t, int>& trackerNameIndexMap)
- : ConditionTracker(id, index), mConfigKey(key) {
+ : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) {
VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
mCountNesting = simplePredicate.count_nesting();
@@ -80,6 +80,7 @@
mSliced = true;
mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
}
+ mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
}
if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) {
@@ -90,6 +91,10 @@
mNonSlicedConditionState = mInitialValue;
+ if (!mSliced) {
+ mUnSlicedPart = mInitialValue;
+ }
+
mInitialized = true;
}
@@ -109,7 +114,7 @@
void SimpleConditionTracker::dumpState() {
VLOG("%lld DUMP:", (long long)mConditionId);
for (const auto& pair : mSlicedConditionState) {
- VLOG("\t%s : %d", pair.first.c_str(), pair.second);
+ VLOG("\t%s : %d", pair.first.toString().c_str(), pair.second);
}
VLOG("Changed to true keys: \n");
@@ -140,6 +145,9 @@
mInitialValue = ConditionState::kFalse;
mSlicedConditionState.clear();
conditionCache[mIndex] = ConditionState::kFalse;
+ if (!mSliced) {
+ mUnSlicedPart = ConditionState::kFalse;
+ }
}
bool SimpleConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) {
@@ -154,7 +162,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("Predicate %lld dropping data for dimension key %s",
- (long long)mConditionId, newKey.c_str());
+ (long long)mConditionId, newKey.toString().c_str());
return true;
}
}
@@ -177,13 +185,13 @@
// We get a new output key.
newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse;
if (matchStart && mInitialValue != ConditionState::kTrue) {
- mSlicedConditionState.insert(std::make_pair(outputKey, 1));
+ mSlicedConditionState[outputKey] = 1;
changed = true;
mLastChangedToTrueDimensions.insert(outputKey);
} else if (mInitialValue != ConditionState::kFalse) {
// it's a stop and we don't have history about it.
// If the default condition is not false, it means this stop is valuable to us.
- mSlicedConditionState.insert(std::make_pair(outputKey, 0));
+ mSlicedConditionState[outputKey] = 0;
mLastChangedToFalseDimensions.insert(outputKey);
changed = true;
}
@@ -226,7 +234,7 @@
// if default condition is false, it means we don't need to keep the false values.
if (mInitialValue == ConditionState::kFalse && startedCount == 0) {
mSlicedConditionState.erase(outputIt);
- VLOG("erase key %s", outputKey.c_str());
+ VLOG("erase key %s", outputKey.toString().c_str());
}
}
}
@@ -238,6 +246,7 @@
(*conditionChangedCache) = changed;
(*conditionCache) = newCondition;
+
VLOG("SimplePredicate %lld nonSlicedChange? %d", (long long)mConditionId,
conditionChangedCache[mIndex] == true);
}
@@ -294,6 +303,7 @@
conditionCache[mIndex] =
itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
}
+ mUnSlicedPart = conditionCache[mIndex];
}
return;
@@ -305,6 +315,17 @@
if (mOutputDimensions.size() == 0) {
handleConditionEvent(DEFAULT_DIMENSION_KEY, matchedState == 1, &overallState,
&overallChanged);
+ } else if (!mContainANYPositionInInternalDimensions) {
+ HashableDimensionKey outputValue;
+ filterValues(mOutputDimensions, event.getValues(), &outputValue);
+
+ // If this event has multiple nodes in the attribution chain, this log event probably will
+ // generate multiple dimensions. If so, we will find if the condition changes for any
+ // dimension and ask the corresponding metric producer to verify whether the actual sliced
+ // condition has changed or not.
+ // A high level assumption is that a predicate is either sliced or unsliced. We will never
+ // have both sliced and unsliced version of a predicate.
+ handleConditionEvent(outputValue, matchedState == 1, &overallState, &overallChanged);
} else {
std::vector<HashableDimensionKey> outputValues;
filterValues(mOutputDimensions, event.getValues(), &outputValues);
@@ -328,11 +349,17 @@
}
conditionCache[mIndex] = overallState;
conditionChangedCache[mIndex] = overallChanged;
+ if (!mSliced) {
+ mUnSlicedPart = overallState;
+ }
}
void SimpleConditionTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
- const vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
+ const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
+ vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
@@ -347,7 +374,7 @@
ConditionState conditionState = ConditionState::kNotEvaluated;
if (dimensionFields.size() > 0 && dimensionFields[0].mMatcher.getTag() == mDimensionTag) {
conditionState = conditionState | getMetConditionDimension(
- allConditions, dimensionFields, dimensionsKeySet);
+ allConditions, dimensionFields, isSubOutputDimensionFields, dimensionsKeySet);
} else {
conditionState = conditionState | mInitialValue;
if (!mSliced) {
@@ -362,42 +389,48 @@
conditionCache[mIndex] = conditionState;
return;
}
- std::vector<HashableDimensionKey> defaultKeys = { DEFAULT_DIMENSION_KEY };
- const std::vector<HashableDimensionKey> &keys =
- (pair == conditionParameters.end()) ? defaultKeys : pair->second;
ConditionState conditionState = ConditionState::kNotEvaluated;
- for (size_t i = 0; i < keys.size(); ++i) {
- const HashableDimensionKey& key = keys[i];
+ const HashableDimensionKey& key = pair->second;
+ if (isPartialLink) {
+ // For unseen key, check whether the require dimensions are subset of sliced condition
+ // output.
+ conditionState = conditionState | mInitialValue;
+ for (const auto& slice : mSlicedConditionState) {
+ ConditionState sliceState =
+ slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
+ if (slice.first.contains(key)) {
+ conditionState = conditionState | sliceState;
+ if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
+ if (isSubOutputDimensionFields) {
+ HashableDimensionKey dimensionKey;
+ filterValues(dimensionFields, slice.first.getValues(), &dimensionKey);
+ dimensionsKeySet.insert(dimensionKey);
+ } else {
+ dimensionsKeySet.insert(slice.first);
+ }
+ }
+ }
+ }
+ } else {
auto startedCountIt = mSlicedConditionState.find(key);
+ conditionState = conditionState | mInitialValue;
if (startedCountIt != mSlicedConditionState.end()) {
ConditionState sliceState =
startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
conditionState = conditionState | sliceState;
if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
- vector<HashableDimensionKey> dimensionKeys;
- filterValues(dimensionFields, startedCountIt->first.getValues(), &dimensionKeys);
- dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
- }
- } else {
- // For unseen key, check whether the require dimensions are subset of sliced condition
- // output.
- conditionState = conditionState | mInitialValue;
- for (const auto& slice : mSlicedConditionState) {
- ConditionState sliceState =
- slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
- if (slice.first.contains(key)) {
- conditionState = conditionState | sliceState;
- if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
- vector<HashableDimensionKey> dimensionKeys;
- filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
-
- dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
- }
- }
+ if (isSubOutputDimensionFields) {
+ HashableDimensionKey dimensionKey;
+ filterValues(dimensionFields, startedCountIt->first.getValues(), &dimensionKey);
+ dimensionsKeySet.insert(dimensionKey);
+ } else {
+ dimensionsKeySet.insert(startedCountIt->first);
}
}
}
+
+ }
conditionCache[mIndex] = conditionState;
VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]);
}
@@ -405,6 +438,7 @@
ConditionState SimpleConditionTracker::getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
ConditionState conditionState = mInitialValue;
if (dimensionFields.size() == 0 || mOutputDimensions.size() == 0 ||
@@ -424,10 +458,13 @@
conditionState = conditionState | sliceState;
if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
- vector<HashableDimensionKey> dimensionKeys;
- filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
-
- dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
+ if (isSubOutputDimensionFields) {
+ HashableDimensionKey dimensionKey;
+ filterValues(dimensionFields, slice.first.getValues(), &dimensionKey);
+ dimensionsKeySet.insert(dimensionKey);
+ } else {
+ dimensionsKeySet.insert(slice.first);
+ }
}
}
return conditionState;
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index e4b72b8..47d1ece 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -49,12 +49,15 @@
void isConditionMet(const ConditionKey& conditionParameters,
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
std::vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
ConditionState getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(
@@ -65,6 +68,7 @@
return nullptr;
}
}
+
virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
const std::vector<sp<ConditionTracker>>& allConditions) const {
if (mSliced) {
@@ -74,6 +78,26 @@
}
}
+ void getTrueSlicedDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ std::set<HashableDimensionKey>* dimensions) const override {
+ for (const auto& itr : mSlicedConditionState) {
+ if (itr.second > 0) {
+ dimensions->insert(itr.first);
+ }
+ }
+ }
+
+ bool IsChangedDimensionTrackable() const override { return true; }
+
+ bool IsSimpleCondition() const override { return true; }
+
+ bool equalOutputDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ const vector<Matcher>& dimensions) const override {
+ return equalDimensions(mOutputDimensions, dimensions);
+ }
+
private:
const ConfigKey mConfigKey;
// The index of the LogEventMatcher which defines the start.
@@ -92,6 +116,8 @@
std::vector<Matcher> mOutputDimensions;
+ bool mContainANYPositionInInternalDimensions;
+
std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateTracker.cpp
index e479f93..c68875c 100644
--- a/cmds/statsd/src/condition/StateTracker.cpp
+++ b/cmds/statsd/src/condition/StateTracker.cpp
@@ -107,7 +107,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("Predicate %lld dropping data for dimension key %s",
- (long long)mConditionId, newKey.c_str());
+ (long long)mConditionId, newKey.toString().c_str());
return true;
}
}
@@ -181,7 +181,10 @@
void StateTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
- const vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
+ const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
+ vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
// it has been evaluated.
@@ -203,20 +206,19 @@
return;
}
- const auto& primaryKeys = pair->second;
+ const auto& primaryKey = pair->second;
conditionCache[mIndex] = mInitialValue;
- for (const auto& primaryKey : primaryKeys) {
- auto it = mSlicedState.find(primaryKey);
- if (it != mSlicedState.end()) {
- conditionCache[mIndex] = ConditionState::kTrue;
- dimensionsKeySet.insert(it->second);
- }
+ auto it = mSlicedState.find(primaryKey);
+ if (it != mSlicedState.end()) {
+ conditionCache[mIndex] = ConditionState::kTrue;
+ dimensionsKeySet.insert(it->second);
}
}
ConditionState StateTracker::getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
if (mSlicedState.size() > 0) {
for (const auto& state : mSlicedState) {
diff --git a/cmds/statsd/src/condition/StateTracker.h b/cmds/statsd/src/condition/StateTracker.h
index 3fe6e60..2bdf98c 100644
--- a/cmds/statsd/src/condition/StateTracker.h
+++ b/cmds/statsd/src/condition/StateTracker.h
@@ -56,6 +56,8 @@
void isConditionMet(const ConditionKey& conditionParameters,
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
+ const bool isPartialLink,
std::vector<ConditionState>& conditionCache,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
@@ -67,6 +69,7 @@
ConditionState getMetConditionDimension(
const std::vector<sp<ConditionTracker>>& allConditions,
const vector<Matcher>& dimensionFields,
+ const bool isSubOutputDimensionFields,
std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(
@@ -79,6 +82,24 @@
return &mLastChangedToFalseDimensions;
}
+ bool IsChangedDimensionTrackable() const override { return true; }
+
+ bool IsSimpleCondition() const override { return true; }
+
+ bool equalOutputDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ const vector<Matcher>& dimensions) const override {
+ return equalDimensions(mOutputDimensions, dimensions);
+ }
+
+ void getTrueSlicedDimensions(
+ const std::vector<sp<ConditionTracker>>& allConditions,
+ std::set<HashableDimensionKey>* dimensions) const override {
+ for (const auto& itr : mSlicedState) {
+ dimensions->insert(itr.second);
+ }
+ }
+
private:
const ConfigKey mConfigKey;
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
deleted file mode 100644
index d1d9d37..0000000
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ /dev/null
@@ -1,100 +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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <fstream>
-#include "external/CpuTimePerUidFreqPuller.h"
-
-#include "../guardrail/StatsdStats.h"
-#include "CpuTimePerUidFreqPuller.h"
-#include "guardrail/StatsdStats.h"
-#include "logd/LogEvent.h"
-#include "statslog.h"
-#include "stats_log_util.h"
-
-using std::make_shared;
-using std::shared_ptr;
-using std::ifstream;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-static const string sProcFile = "/proc/uid_time_in_state";
-static const int kLineBufferSize = 1024;
-
-/**
- * Reads /proc/uid_time_in_state which has the format:
- *
- * uid: [freq1] [freq2] [freq3] ...
- * [uid1]: [time in freq1] [time in freq2] [time in freq3] ...
- * [uid2]: [time in freq1] [time in freq2] [time in freq3] ...
- * ...
- *
- * This provides the times a UID's processes spent executing at each different cpu frequency.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-CpuTimePerUidFreqPuller::CpuTimePerUidFreqPuller()
- : StatsPuller(android::util::CPU_TIME_PER_UID_FREQ) {
-}
-
-bool CpuTimePerUidFreqPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
- data->clear();
-
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
-
- int64_t wallClockTimestampNs = getWallClockNs();
- int64_t elapsedTimestampNs = getElapsedRealtimeNs();
-
- char buf[kLineBufferSize];
- // first line prints the format and frequencies
- fin.getline(buf, kLineBufferSize);
- char* pch;
- while (!fin.eof()) {
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(NULL, " ");
- uint64_t timeMs;
- int idx = 0;
- do {
- timeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ,
- wallClockTimestampNs, elapsedTimestampNs);
- ptr->write(uid);
- ptr->write(idx);
- ptr->write(timeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
- idx++;
- pch = strtok(NULL, " ");
- } while (pch != NULL);
- }
- return true;
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h
deleted file mode 100644
index 6f6c669..0000000
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h
+++ /dev/null
@@ -1,42 +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.
- */
-
-#pragma once
-
-#include <utils/String16.h>
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Reads /proc/uid_cputime/show_uid_stat which has the line format:
- *
- * uid: user_time_micro_seconds system_time_micro_seconds
- *
- * This provides the time a UID's processes spent executing in user-space and kernel-space.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-class CpuTimePerUidFreqPuller : public StatsPuller {
- public:
- CpuTimePerUidFreqPuller();
- bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
deleted file mode 100644
index 568b8f0..0000000
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
+++ /dev/null
@@ -1,90 +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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <fstream>
-#include "external/CpuTimePerUidPuller.h"
-
-#include "CpuTimePerUidPuller.h"
-#include "guardrail/StatsdStats.h"
-#include "logd/LogEvent.h"
-#include "statslog.h"
-#include "stats_log_util.h"
-
-using std::make_shared;
-using std::shared_ptr;
-using std::ifstream;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-static const string sProcFile = "/proc/uid_cputime/show_uid_stat";
-static const int kLineBufferSize = 1024;
-
-/**
- * Reads /proc/uid_cputime/show_uid_stat which has the line format:
- *
- * uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds
- *
- * This provides the time a UID's processes spent executing in user-space and kernel-space.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-CpuTimePerUidPuller::CpuTimePerUidPuller() : StatsPuller(android::util::CPU_TIME_PER_UID) {
-}
-
-bool CpuTimePerUidPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
- data->clear();
-
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
-
- int64_t wallClockTimestampNs = getWallClockNs();
- int64_t elapsedTimestampNs = getElapsedRealtimeNs();
- char buf[kLineBufferSize];
- char* pch;
- while (!fin.eof()) {
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t userTimeMs = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t sysTimeMs = std::stoull(pch);
-
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID,
- wallClockTimestampNs, elapsedTimestampNs);
- ptr->write(uid);
- ptr->write(userTimeMs);
- ptr->write(sysTimeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs,
- (long long)sysTimeMs);
- }
- return true;
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.h b/cmds/statsd/src/external/CpuTimePerUidPuller.h
deleted file mode 100644
index d0d39d0..0000000
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.h
+++ /dev/null
@@ -1,42 +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.
- */
-
-#pragma once
-
-#include <utils/String16.h>
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Reads /proc/uid_cputime/show_uid_stat which has the line format:
- *
- * uid: user_time_micro_seconds system_time_micro_seconds
- *
- * This provides the time a UID's processes spent executing in user-space and kernel-space.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-class CpuTimePerUidPuller : public StatsPuller {
- public:
- CpuTimePerUidPuller();
- bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp
deleted file mode 100644
index 0b545cc..0000000
--- a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <fstream>
-
-#include "KernelUidCpuActiveTimeReader.h"
-#include "guardrail/StatsdStats.h"
-#include "logd/LogEvent.h"
-#include "statslog.h"
-#include "stats_log_util.h"
-
-using std::make_shared;
-using std::shared_ptr;
-using std::ifstream;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-static const string sProcFile = "/proc/uid_concurrent_active_time";
-static const int kLineBufferSize = 1024;
-
-/**
- * Reads /proc/uid_concurrent_active_time which has the format:
- * active: X (X is # cores)
- * [uid0]: [time-0] [time-1] [time-2] ... (# entries = # cores)
- * [uid1]: [time-0] [time-1] [time-2] ... ...
- * ...
- * Time-N means the CPU time a UID spent running concurrently with N other processes.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-KernelUidCpuActiveTimeReader::KernelUidCpuActiveTimeReader() : StatsPuller(android::util::CPU_ACTIVE_TIME) {
-}
-
-bool KernelUidCpuActiveTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* data) {
- data->clear();
-
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
-
- int64_t wallClockTimestampNs = getWallClockNs();
- int64_t elapsedTimestampNs = getElapsedRealtimeNs();
-
- char buf[kLineBufferSize];
- char* pch;
- while (!fin.eof()) {
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(NULL, " ");
- uint64_t timeMs;
- int idx = 0;
- do {
- timeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs);
- ptr->write(uid);
- ptr->write(idx);
- ptr->write(timeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, freq idx %d, active time %lld", (long long)uid, idx, (long long)timeMs);
- idx++;
- pch = strtok(NULL, " ");
- } while (pch != NULL);
- }
- return true;
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.h b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.h
deleted file mode 100644
index fcae35f..0000000
--- a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#pragma once
-
-#include <utils/String16.h>
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-class KernelUidCpuActiveTimeReader : public StatsPuller {
- public:
- KernelUidCpuActiveTimeReader();
- bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp
deleted file mode 100644
index cc80204..0000000
--- a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <fstream>
-#include "KernelUidCpuClusterTimeReader.h"
-#include "guardrail/StatsdStats.h"
-#include "logd/LogEvent.h"
-#include "statslog.h"
-#include "stats_log_util.h"
-
-using std::make_shared;
-using std::shared_ptr;
-using std::ifstream;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-static const string sProcFile = "/proc/uid_concurrent_policy_time";
-static const int kLineBufferSize = 1024;
-
-/**
- * Reads /proc/uid_concurrent_policy_time which has the format:
- * policy0: X policy4: Y (there are X cores on policy0, Y cores on policy4)
- * [uid0]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
- * [uid1]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
- * ...
- * Time-X-Y means the time a UID spent on clusterX running concurrently with Y other processes.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-KernelUidCpuClusterTimeReader::KernelUidCpuClusterTimeReader() : StatsPuller(android::util::CPU_CLUSTER_TIME) {
-}
-
-bool KernelUidCpuClusterTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* data) {
- data->clear();
-
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
-
- int64_t wallClockTimestampNs = getWallClockNs();
- int64_t elapsedTimestampNs = getElapsedRealtimeNs();
- char buf[kLineBufferSize];
- char* pch;
- while (!fin.eof()) {
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(NULL, " ");
- uint64_t timeMs;
- int idx = 0;
- do {
- timeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs);
- ptr->write(uid);
- ptr->write(idx);
- ptr->write(timeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, freq idx %d, cluster time %lld", (long long)uid, idx, (long long)timeMs);
- idx++;
- pch = strtok(NULL, " ");
- } while (pch != NULL);
- }
- return true;
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.h b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.h
deleted file mode 100644
index 90236ae..0000000
--- a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#pragma once
-
-#include <utils/String16.h>
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Reads /proc/uid_cputime/show_uid_stat which has the line format:
- *
- * uid: user_time_micro_seconds system_time_micro_seconds
- *
- * This provides the time a UID's processes spent executing in user-space and kernel-space.
- * The file contains a monotonically increasing count of time for a single boot.
- */
-class KernelUidCpuClusterTimeReader : public StatsPuller {
- public:
- KernelUidCpuClusterTimeReader();
- bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-} // namespace statsd
-} // namespace os
-} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 880dfd1..72a00cb 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -21,10 +21,6 @@
#include <cutils/log.h>
#include <algorithm>
#include <climits>
-#include "CpuTimePerUidFreqPuller.h"
-#include "CpuTimePerUidPuller.h"
-#include "KernelUidCpuActiveTimeReader.h"
-#include "KernelUidCpuClusterTimeReader.h"
#include "ResourceHealthManagerPuller.h"
#include "ResourceThermalManagerPuller.h"
#include "StatsCompanionServicePuller.h"
@@ -51,27 +47,19 @@
const std::map<int, PullAtomInfo> StatsPullerManagerImpl::kAllPullAtomInfo = {
// wifi_bytes_transfer
{android::util::WIFI_BYTES_TRANSFER,
- {{2, 3, 4, 5},
- {},
- 1,
+ {{2, 3, 4, 5}, {}, 1,
new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}},
// wifi_bytes_transfer_by_fg_bg
{android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
- {{3, 4, 5, 6},
- {2},
- 1,
+ {{3, 4, 5, 6}, {2}, 1,
new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
// mobile_bytes_transfer
{android::util::MOBILE_BYTES_TRANSFER,
- {{2, 3, 4, 5},
- {},
- 1,
+ {{2, 3, 4, 5}, {}, 1,
new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
// mobile_bytes_transfer_by_fg_bg
{android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
- {{3, 4, 5, 6},
- {2},
- 1,
+ {{3, 4, 5, 6}, {2}, 1,
new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
// bluetooth_bytes_transfer
{android::util::BLUETOOTH_BYTES_TRANSFER,
@@ -80,14 +68,26 @@
{android::util::KERNEL_WAKELOCK,
{{}, {}, 1, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
// subsystem_sleep_state
- {android::util::SUBSYSTEM_SLEEP_STATE, {{}, {}, 1, new SubsystemSleepStatePuller()}},
+ {android::util::SUBSYSTEM_SLEEP_STATE,
+ {{}, {}, 1, new SubsystemSleepStatePuller()}},
// cpu_time_per_freq
{android::util::CPU_TIME_PER_FREQ,
{{3}, {2}, 1, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
// cpu_time_per_uid
- {android::util::CPU_TIME_PER_UID, {{2, 3}, {}, 1, new CpuTimePerUidPuller()}},
+ {android::util::CPU_TIME_PER_UID,
+ {{2, 3}, {}, 1, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}},
// cpu_time_per_uid_freq
- {android::util::CPU_TIME_PER_UID_FREQ, {{3}, {2}, 1, new CpuTimePerUidFreqPuller()}},
+ // the throttling is 3sec, handled in frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
+ {android::util::CPU_TIME_PER_UID_FREQ,
+ {{4}, {2,3}, 0, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}},
+ // cpu_active_time
+ // the throttling is 3sec, handled in frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
+ {android::util::CPU_ACTIVE_TIME,
+ {{2}, {}, 0, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
+ // cpu_cluster_time
+ // the throttling is 3sec, handled in frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
+ {android::util::CPU_CLUSTER_TIME,
+ {{3}, {2}, 0, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
// wifi_activity_energy_info
{android::util::WIFI_ACTIVITY_ENERGY_INFO,
{{}, {}, 1, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_ENERGY_INFO)}},
@@ -103,10 +103,6 @@
// system_uptime
{android::util::SYSTEM_UPTIME,
{{}, {}, 1, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
- // cpu_active_time
- {android::util::CPU_ACTIVE_TIME, {{3}, {2}, 1, new KernelUidCpuActiveTimeReader()}},
- // cpu_cluster_time
- {android::util::CPU_CLUSTER_TIME, {{3}, {2}, 1, new KernelUidCpuClusterTimeReader()}},
// disk_space
{android::util::DISK_SPACE,
{{}, {}, 1, new StatsCompanionServicePuller(android::util::DISK_SPACE)}},
@@ -118,7 +114,10 @@
{{}, {}, 1, new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
// process_memory_state
{android::util::PROCESS_MEMORY_STATE,
- {{4,5,6,7,8}, {2,3}, 0, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
+ {{4,5,6,7,8},
+ {2,3},
+ 0,
+ new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
// temperature
{android::util::TEMPERATURE, {{}, {}, 1, new ResourceThermalManagerPuller()}}};
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index da5ef44..22b2a30 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -71,6 +71,7 @@
if (metric.has_dimensions_in_what()) {
translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+ mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
}
if (metric.has_dimensions_in_condition()) {
@@ -113,7 +114,7 @@
for (const auto& counter : mPastBuckets) {
const MetricDimensionKey& dimensionKey = counter.first;
- VLOG(" dimension key %s", dimensionKey.c_str());
+ VLOG(" dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -176,7 +177,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("CountMetric %lld dropping data for dimension key %s",
- (long long)mMetricId, newKey.c_str());
+ (long long)mMetricId, newKey.toString().c_str());
return true;
}
}
@@ -218,7 +219,7 @@
countWholeBucket);
}
- VLOG("metric %lld %s->%lld", (long long)mMetricId, eventKey.c_str(),
+ VLOG("metric %lld %s->%lld", (long long)mMetricId, eventKey.toString().c_str(),
(long long)(*mCurrentSlicedCounter)[eventKey]);
}
@@ -253,7 +254,8 @@
info.mCount = counter.second;
auto& bucketList = mPastBuckets[counter.first];
bucketList.push_back(info);
- VLOG("metric %lld, dump key value: %s -> %lld", (long long)mMetricId, counter.first.c_str(),
+ VLOG("metric %lld, dump key value: %s -> %lld", (long long)mMetricId,
+ counter.first.toString().c_str(),
(long long)counter.second);
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 29a892d..0dd3f70 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -67,7 +67,8 @@
mStartIndex(startIndex),
mStopIndex(stopIndex),
mStopAllIndex(stopAllIndex),
- mNested(nesting) {
+ mNested(nesting),
+ mContainANYPositionInInternalDimensions(false) {
// TODO: The following boiler plate code appears in all MetricProducers, but we can't abstract
// them in the base class, because the proto generated CountMetric, and DurationMetric are
// not related. Maybe we should add a template in the future??
@@ -80,10 +81,12 @@
if (metric.has_dimensions_in_what()) {
translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+ mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
}
if (internalDimensions.has_field()) {
translateFieldMatcher(internalDimensions, &mInternalDimensions);
+ mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions);
}
if (metric.has_dimensions_in_condition()) {
@@ -100,19 +103,18 @@
}
}
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
+ mUnSlicedPartCondition = ConditionState::kUnknown;
- if (mDimensionsInWhat.size() == mInternalDimensions.size()) {
- bool mUseWhatDimensionAsInternalDimension = true;
- for (size_t i = 0; mUseWhatDimensionAsInternalDimension &&
- i < mDimensionsInWhat.size(); ++i) {
- if (mDimensionsInWhat[i] != mInternalDimensions[i]) {
- mUseWhatDimensionAsInternalDimension = false;
- }
+ mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions);
+ if (mWizard != nullptr && mConditionTrackerIndex >= 0) {
+ mSameConditionDimensionsInTracker =
+ mWizard->equalOutputDimensions(mConditionTrackerIndex, mDimensionsInCondition);
+ if (mMetric2ConditionLinks.size() == 1) {
+ mHasLinksToAllConditionDimensionsInTracker =
+ mWizard->equalOutputDimensions(mConditionTrackerIndex,
+ mMetric2ConditionLinks.begin()->conditionFields);
}
- } else {
- mUseWhatDimensionAsInternalDimension = false;
}
-
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
(long long)mBucketSizeNs, (long long)mStartTimeNs);
}
@@ -139,12 +141,171 @@
return make_unique<OringDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
- mStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
+ mStartTimeNs, mBucketSizeNs, mConditionSliced,
+ mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
case DurationMetric_AggregationType_MAX_SPARSE:
return make_unique<MaxDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
- mStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
+ mStartTimeNs, mBucketSizeNs, mConditionSliced,
+ mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
+ }
+}
+
+// SlicedConditionChange optimization case 1:
+// 1. If combination condition, logical operation is AND, only one sliced child predicate.
+// 2. No condition in dimension
+// 3. The links covers all dimension fields in the sliced child condition predicate.
+void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime) {
+ if (mMetric2ConditionLinks.size() != 1 ||
+ !mHasLinksToAllConditionDimensionsInTracker ||
+ !mDimensionsInCondition.empty()) {
+ return;
+ }
+
+ bool currentUnSlicedPartCondition = true;
+ if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) {
+ ConditionState unslicedPartState =
+ mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex);
+ // When the unsliced part is still false, return directly.
+ if (mUnSlicedPartCondition == ConditionState::kFalse &&
+ unslicedPartState == ConditionState::kFalse) {
+ return;
+ }
+ mUnSlicedPartCondition = unslicedPartState;
+ currentUnSlicedPartCondition = mUnSlicedPartCondition > 0;
+ }
+
+ auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex);
+ auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex);
+
+ // The condition change is from the unsliced predicates.
+ // We need to find out the true dimensions from the sliced predicate and flip their condition
+ // state based on the new unsliced condition state.
+ if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr ||
+ (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) {
+ std::set<HashableDimensionKey> trueConditionDimensions;
+ mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, &trueConditionDimensions);
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ HashableDimensionKey linkedConditionDimensionKey;
+ getDimensionForCondition(whatIt.first.getValues(),
+ mMetric2ConditionLinks[0],
+ &linkedConditionDimensionKey);
+ if (trueConditionDimensions.find(linkedConditionDimensionKey) !=
+ trueConditionDimensions.end()) {
+ for (auto& condIt : whatIt.second) {
+ condIt.second->onConditionChanged(
+ currentUnSlicedPartCondition, eventTime);
+ }
+ }
+ }
+ } else {
+ // Handle the condition change from the sliced predicate.
+ if (currentUnSlicedPartCondition) {
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ HashableDimensionKey linkedConditionDimensionKey;
+ getDimensionForCondition(whatIt.first.getValues(),
+ mMetric2ConditionLinks[0],
+ &linkedConditionDimensionKey);
+ if (dimensionsChangedToTrue->find(linkedConditionDimensionKey) !=
+ dimensionsChangedToTrue->end()) {
+ for (auto& condIt : whatIt.second) {
+ condIt.second->onConditionChanged(true, eventTime);
+ }
+ }
+ if (dimensionsChangedToFalse->find(linkedConditionDimensionKey) !=
+ dimensionsChangedToFalse->end()) {
+ for (auto& condIt : whatIt.second) {
+ condIt.second->onConditionChanged(false, eventTime);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// SlicedConditionChange optimization case 2:
+// 1. If combination condition, logical operation is AND, only one sliced child predicate.
+// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate.
+void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime) {
+ if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) {
+ return;
+ }
+
+ auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex);
+ auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex);
+
+ bool currentUnSlicedPartCondition = true;
+ if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) {
+ ConditionState unslicedPartState =
+ mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex);
+ // When the unsliced part is still false, return directly.
+ if (mUnSlicedPartCondition == ConditionState::kFalse &&
+ unslicedPartState == ConditionState::kFalse) {
+ return;
+ }
+ mUnSlicedPartCondition = unslicedPartState;
+ currentUnSlicedPartCondition = mUnSlicedPartCondition > 0;
+ }
+
+ const std::set<HashableDimensionKey>* trueDimensionsToProcess = nullptr;
+ const std::set<HashableDimensionKey>* falseDimensionsToProcess = nullptr;
+
+ std::set<HashableDimensionKey> currentTrueConditionDimensions;
+ if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr ||
+ (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) {
+ mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, ¤tTrueConditionDimensions);
+ trueDimensionsToProcess = ¤tTrueConditionDimensions;
+ } else if (currentUnSlicedPartCondition) {
+ // Handles the condition change from the sliced predicate. If the unsliced condition state
+ // is not true, not need to do anything.
+ trueDimensionsToProcess = dimensionsChangedToTrue;
+ falseDimensionsToProcess = dimensionsChangedToFalse;
+ }
+
+ if (trueDimensionsToProcess == nullptr && falseDimensionsToProcess == nullptr) {
+ return;
+ }
+
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ if (falseDimensionsToProcess != nullptr) {
+ for (const auto& changedDim : *falseDimensionsToProcess) {
+ auto condIt = whatIt.second.find(changedDim);
+ if (condIt != whatIt.second.end()) {
+ condIt->second->onConditionChanged(false, eventTime);
+ }
+ }
+ }
+ if (trueDimensionsToProcess != nullptr) {
+ HashableDimensionKey linkedConditionDimensionKey;
+ if (!trueDimensionsToProcess->empty() && mMetric2ConditionLinks.size() == 1) {
+ getDimensionForCondition(whatIt.first.getValues(),
+ mMetric2ConditionLinks[0],
+ &linkedConditionDimensionKey);
+ }
+ for (auto& trueDim : *trueDimensionsToProcess) {
+ auto condIt = whatIt.second.find(trueDim);
+ if (condIt != whatIt.second.end()) {
+ condIt->second->onConditionChanged(
+ currentUnSlicedPartCondition, eventTime);
+ } else {
+ if (mMetric2ConditionLinks.size() == 0 ||
+ trueDim.contains(linkedConditionDimensionKey)) {
+ if (!whatIt.second.empty()) {
+ unique_ptr<DurationTracker> newTracker =
+ whatIt.second.begin()->second->clone(eventTime);
+ if (newTracker != nullptr) {
+ newTracker->setEventKey(
+ MetricDimensionKey(whatIt.first, trueDim));
+ newTracker->onConditionChanged(true, eventTime);
+ whatIt.second[trueDim] = std::move(newTracker);
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -152,6 +313,23 @@
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
flushIfNeededLocked(eventTime);
+ if (!mConditionSliced) {
+ return;
+ }
+
+ bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
+ if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker &&
+ mDimensionsInCondition.empty()) {
+ onSlicedConditionMayChangeLocked_opt1(eventTime);
+ return;
+ }
+
+ if (changeDimTrackable && mSameConditionDimensionsInTracker &&
+ mMetric2ConditionLinks.size() <= 1) {
+ onSlicedConditionMayChangeLocked_opt2(eventTime);
+ return;
+ }
+
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
@@ -166,6 +344,7 @@
if (mMetric2ConditionLinks.empty()) {
std::unordered_set<HashableDimensionKey> conditionDimensionsKeySet;
mWizard->getMetConditionDimension(mConditionTrackerIndex, mDimensionsInCondition,
+ !mSameConditionDimensionsInTracker,
&conditionDimensionsKeySet);
for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (const auto& pair : whatIt.second) {
@@ -177,9 +356,12 @@
if (!whatIt.second.empty()) {
unique_ptr<DurationTracker> newTracker =
whatIt.second.begin()->second->clone(eventTime);
- newTracker->setEventKey(MetricDimensionKey(whatIt.first, conditionDimension));
- newTracker->onSlicedConditionMayChange(eventTime);
- whatIt.second[conditionDimension] = std::move(newTracker);
+ if (newTracker != nullptr) {
+ newTracker->setEventKey(MetricDimensionKey(
+ whatIt.first, conditionDimension));
+ newTracker->onSlicedConditionMayChange(eventTime);
+ whatIt.second[conditionDimension] = std::move(newTracker);
+ }
}
}
}
@@ -192,15 +374,20 @@
}
std::unordered_set<HashableDimensionKey> conditionDimensionsKeys;
mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
&conditionDimensionsKeys);
for (const auto& conditionDimension : conditionDimensionsKeys) {
if (!whatIt.second.empty() &&
whatIt.second.find(conditionDimension) == whatIt.second.end()) {
auto newTracker = whatIt.second.begin()->second->clone(eventTime);
- newTracker->setEventKey(MetricDimensionKey(whatIt.first, conditionDimension));
- newTracker->onSlicedConditionMayChange(eventTime);
- whatIt.second[conditionDimension] = std::move(newTracker);
+ if (newTracker != nullptr) {
+ newTracker->setEventKey(
+ MetricDimensionKey(whatIt.first, conditionDimension));
+ newTracker->onSlicedConditionMayChange(eventTime);
+ whatIt.second[conditionDimension] = std::move(newTracker);
+ }
}
}
}
@@ -241,7 +428,7 @@
for (const auto& pair : mPastBuckets) {
const MetricDimensionKey& dimensionKey = pair.first;
- VLOG(" dimension key %s", dimensionKey.c_str());
+ VLOG(" dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -291,7 +478,8 @@
whatIt != mCurrentSlicedDurationTrackerMap.end();) {
for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
if (it->second->flushIfNeeded(eventTimeNs, &mPastBuckets)) {
- VLOG("erase bucket for key %s %s", whatIt->first.c_str(), it->first.c_str());
+ VLOG("erase bucket for key %s %s",
+ whatIt->first.toString().c_str(), it->first.toString().c_str());
it = whatIt->second.erase(it);
} else {
++it;
@@ -314,7 +502,8 @@
whatIt != mCurrentSlicedDurationTrackerMap.end();) {
for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
if (it->second->flushCurrentBucket(eventTimeNs, &mPastBuckets)) {
- VLOG("erase bucket for key %s %s", whatIt->first.c_str(), it->first.c_str());
+ VLOG("erase bucket for key %s %s", whatIt->first.toString().c_str(),
+ it->first.toString().c_str());
it = whatIt->second.erase(it);
} else {
++it;
@@ -338,7 +527,8 @@
if (verbose) {
for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (const auto& slice : whatIt.second) {
- fprintf(out, "\t%s\t%s\n", whatIt.first.c_str(), slice.first.c_str());
+ fprintf(out, "\t(what)%s\t(condition)%s\n", whatIt.first.toString().c_str(),
+ slice.first.toString().c_str());
slice.second->dumpStates(out, verbose);
}
}
@@ -353,7 +543,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("DurationMetric %lld dropping data for dimension key %s",
- (long long)mMetricId, newKey.c_str());
+ (long long)mMetricId, newKey.toString().c_str());
return true;
}
}
@@ -388,14 +578,21 @@
return;
}
- std::vector<HashableDimensionKey> values;
- filterValues(mInternalDimensions, event.getValues(), &values);
- if (values.empty()) {
+ if (mInternalDimensions.empty()) {
it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
event.GetElapsedTimestampNs(), conditionKeys);
} else {
- for (const auto& value : values) {
- it->second->noteStart(value, condition, event.GetElapsedTimestampNs(), conditionKeys);
+ if (mContainANYPositionInInternalDimensions) {
+ std::vector<HashableDimensionKey> dimensionKeys;
+ filterValues(mInternalDimensions, event.getValues(), &dimensionKeys);
+ for (const auto& key : dimensionKeys) {
+ it->second->noteStart(key, condition, event.GetElapsedTimestampNs(), conditionKeys);
+ }
+ } else {
+ HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
+ filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
+ it->second->noteStart(
+ dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
}
}
@@ -408,8 +605,113 @@
ALOGW("Not used in duration tracker.");
}
+void DurationMetricProducer::onMatchedLogEventLocked_simple(const size_t matcherIndex,
+ const LogEvent& event) {
+ uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ if (eventTimeNs < mStartTimeNs) {
+ return;
+ }
+
+ flushIfNeededLocked(event.GetElapsedTimestampNs());
+
+ // Handles Stopall events.
+ if (matcherIndex == mStopAllIndex) {
+ for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+ for (auto& pair : whatIt.second) {
+ pair.second->noteStopAll(event.GetElapsedTimestampNs());
+ }
+ }
+ return;
+ }
+
+ HashableDimensionKey dimensionInWhat;
+ if (!mDimensionsInWhat.empty()) {
+ filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
+ } else {
+ dimensionInWhat = DEFAULT_DIMENSION_KEY;
+ }
+
+ // Handles Stop events.
+ if (matcherIndex == mStopIndex) {
+ if (mUseWhatDimensionAsInternalDimension) {
+ auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
+ if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
+ for (const auto& condIt : whatIt->second) {
+ condIt.second->noteStop(dimensionInWhat, event.GetElapsedTimestampNs(), false);
+ }
+ }
+ return;
+ }
+
+ HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY;
+ if (!mInternalDimensions.empty()) {
+ filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey);
+ }
+
+ auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
+ if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
+ for (const auto& condIt : whatIt->second) {
+ condIt.second->noteStop(
+ internalDimensionKey, event.GetElapsedTimestampNs(), false);
+ }
+ }
+ return;
+ }
+
+ bool condition;
+ ConditionKey conditionKey;
+ std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
+ if (mConditionSliced) {
+ for (const auto& link : mMetric2ConditionLinks) {
+ getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]);
+ }
+
+ auto conditionState =
+ mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
+ &dimensionKeysInCondition);
+ condition = (conditionState == ConditionState::kTrue);
+ if (mDimensionsInCondition.empty() && condition) {
+ dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
+ }
+ } else {
+ condition = mCondition;
+ if (condition) {
+ dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
+ }
+ }
+
+ if (dimensionKeysInCondition.empty()) {
+ handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY),
+ conditionKey, condition, event);
+ } else {
+ auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
+ // If the what dimension is already there, we should update all the trackers even
+ // the condition is false.
+ if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
+ for (const auto& condIt : whatIt->second) {
+ const bool cond = dimensionKeysInCondition.find(condIt.first) !=
+ dimensionKeysInCondition.end();
+ handleStartEvent(MetricDimensionKey(dimensionInWhat, condIt.first),
+ conditionKey, cond, event);
+ dimensionKeysInCondition.erase(condIt.first);
+ }
+ }
+ for (const auto& conditionDimension : dimensionKeysInCondition) {
+ handleStartEvent(MetricDimensionKey(dimensionInWhat, conditionDimension), conditionKey,
+ condition, event);
+ }
+ }
+}
+
void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
const LogEvent& event) {
+ if (!mContainANYPositionInDimensionsInWhat) {
+ onMatchedLogEventLocked_simple(matcherIndex, event);
+ return;
+ }
+
uint64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mStartTimeNs) {
return;
@@ -448,19 +750,17 @@
return;
}
- std::vector<HashableDimensionKey> internalDimensionKeys;
- filterValues(mInternalDimensions, event.getValues(), &internalDimensionKeys);
- if (internalDimensionKeys.empty()) {
- internalDimensionKeys.push_back(DEFAULT_DIMENSION_KEY);
+ HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY;
+ if (!mInternalDimensions.empty()) {
+ filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey);
}
+
for (const HashableDimensionKey& whatDimension : dimensionInWhatValues) {
auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension);
if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
for (const auto& condIt : whatIt->second) {
- for (const auto& internalDimensionKey : internalDimensionKeys) {
- condIt.second->noteStop(
- internalDimensionKey, event.GetElapsedTimestampNs(), false);
- }
+ condIt.second->noteStop(
+ internalDimensionKey, event.GetElapsedTimestampNs(), false);
}
}
}
@@ -477,6 +777,8 @@
auto conditionState =
mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
&dimensionKeysInCondition);
condition = (conditionState == ConditionState::kTrue);
if (mDimensionsInCondition.empty() && condition) {
@@ -490,32 +792,30 @@
}
for (const auto& whatDimension : dimensionInWhatValues) {
- auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension);
- // If the what dimension is already there, we should update all the trackers even
- // the condition is false.
- if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
- for (const auto& condIt : whatIt->second) {
- const bool cond = dimensionKeysInCondition.find(condIt.first) !=
- dimensionKeysInCondition.end();
- handleStartEvent(MetricDimensionKey(whatDimension, condIt.first),
- conditionKey, cond, event);
- }
+ if (dimensionKeysInCondition.empty()) {
+ handleStartEvent(MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
+ conditionKey, condition, event);
} else {
- // If it is a new what dimension key, we need to handle the start events for all current
- // condition dimensions.
+ auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension);
+ // If the what dimension is already there, we should update all the trackers even
+ // the condition is false.
+ if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
+ for (const auto& condIt : whatIt->second) {
+ const bool cond = dimensionKeysInCondition.find(condIt.first) !=
+ dimensionKeysInCondition.end();
+ handleStartEvent(MetricDimensionKey(whatDimension, condIt.first),
+ conditionKey, cond, event);
+ dimensionKeysInCondition.erase(condIt.first);
+ }
+ }
for (const auto& conditionDimension : dimensionKeysInCondition) {
handleStartEvent(MetricDimensionKey(whatDimension, conditionDimension),
conditionKey, condition, event);
}
}
- if (dimensionKeysInCondition.empty()) {
- handleStartEvent(MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
- conditionKey, condition, event);
- }
}
}
-
size_t DurationMetricProducer::byteSizeLocked() const {
size_t totalSize = 0;
for (const auto& pair : mPastBuckets) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 23408a7..6746e11 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -51,6 +51,9 @@
protected:
void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
+
+ void onMatchedLogEventLocked_simple(const size_t matcherIndex, const LogEvent& event);
+
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
const ConditionKey& conditionKeys, bool condition,
@@ -69,6 +72,9 @@
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime);
+ void onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime);
+
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
@@ -98,9 +104,14 @@
// The dimension from the atom predicate. e.g., uid, wakelock name.
vector<Matcher> mInternalDimensions;
+ bool mContainANYPositionInInternalDimensions;
+
// This boolean is true iff When mInternalDimensions == mDimensionsInWhat
bool mUseWhatDimensionAsInternalDimension;
+ // Caches the current unsliced part condition.
+ ConditionState mUnSlicedPartCondition;
+
// Save the past buckets and we can clear when the StatsLogReport is dumped.
// TODO: Add a lock to mPastBuckets.
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>> mPastBuckets;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 288f563c..e479e5c 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -83,6 +83,7 @@
// TODO: use UidMap if uid->pkg_name is required
if (metric.has_dimensions_in_what()) {
translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+ mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
}
if (metric.has_dimensions_in_condition()) {
@@ -140,7 +141,7 @@
for (const auto& pair : mPastBuckets) {
const MetricDimensionKey& dimensionKey = pair.first;
- VLOG(" dimension key %s", dimensionKey.c_str());
+ VLOG(" dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -283,7 +284,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("GaugeMetric %lld dropping data for dimension key %s",
- (long long)mMetricId, newKey.c_str());
+ (long long)mMetricId, newKey.toString().c_str());
return true;
}
}
@@ -398,7 +399,8 @@
info.mGaugeAtoms = slice.second;
auto& bucketList = mPastBuckets[slice.first];
bucketList.push_back(info);
- VLOG("gauge metric %lld, dump key value: %s", (long long)mMetricId, slice.first.c_str());
+ VLOG("gauge metric %lld, dump key value: %s", (long long)mMetricId,
+ slice.first.toString().c_str());
}
// If we have anomaly trackers, we need to update the partial bucket values.
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 18694a1..6c90b03 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -39,9 +39,10 @@
for (const auto& link : mMetric2ConditionLinks) {
getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]);
}
-
auto conditionState =
mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
&dimensionKeysInCondition);
condition = (conditionState == ConditionState::kTrue);
} else {
@@ -52,25 +53,41 @@
dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
}
- vector<HashableDimensionKey> dimensionInWhatValues;
- if (!mDimensionsInWhat.empty()) {
- filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues);
- } else {
- dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY);
- }
+ if (mContainANYPositionInDimensionsInWhat) {
+ vector<HashableDimensionKey> dimensionInWhatValues;
+ if (!mDimensionsInWhat.empty()) {
+ filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues);
+ } else {
+ dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY);
+ }
- for (const auto& whatDimension : dimensionInWhatValues) {
+ for (const auto& whatDimension : dimensionInWhatValues) {
+ for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
+ onMatchedLogEventInternalLocked(
+ matcherIndex, MetricDimensionKey(whatDimension, conditionDimensionKey),
+ conditionKey, condition, event);
+ }
+ if (dimensionKeysInCondition.empty()) {
+ onMatchedLogEventInternalLocked(
+ matcherIndex, MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
+ conditionKey, condition, event);
+ }
+ }
+ } else {
+ HashableDimensionKey dimensionInWhat;
+ filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
+ MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY);
for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
+ metricKey.setDimensionKeyInCondition(conditionDimensionKey);
onMatchedLogEventInternalLocked(
- matcherIndex, MetricDimensionKey(whatDimension, conditionDimensionKey),
- conditionKey, condition, event);
+ matcherIndex, metricKey, conditionKey, condition, event);
}
if (dimensionKeysInCondition.empty()) {
onMatchedLogEventInternalLocked(
- matcherIndex, MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
- conditionKey, condition, event);
+ matcherIndex, metricKey, conditionKey, condition, event);
}
}
+
}
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 05b7f87..ea45f43 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -50,7 +50,11 @@
mCondition(conditionIndex >= 0 ? false : true),
mConditionSliced(false),
mWizard(wizard),
- mConditionTrackerIndex(conditionIndex){};
+ mConditionTrackerIndex(conditionIndex),
+ mContainANYPositionInDimensionsInWhat(false),
+ mSameConditionDimensionsInTracker(false),
+ mHasLinksToAllConditionDimensionsInTracker(false) {
+ }
virtual ~MetricProducer(){};
@@ -219,6 +223,16 @@
vector<Matcher> mDimensionsInWhat; // The dimensions_in_what defined in statsd_config
vector<Matcher> mDimensionsInCondition; // The dimensions_in_condition defined in statsd_config
+ bool mContainANYPositionInDimensionsInWhat;
+
+ // True iff the condition dimensions equal to the sliced dimensions in the simple condition
+ // tracker. This field is always false for combinational condition trackers.
+ bool mSameConditionDimensionsInTracker;
+
+ // True iff the metric to condition links cover all dimension fields in the condition tracker.
+ // This field is always false for combinational condition trackers.
+ bool mHasLinksToAllConditionDimensionsInTracker;
+
std::vector<Metric2Condition> mMetric2ConditionLinks;
std::vector<sp<AnomalyTracker>> mAnomalyTrackers;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index a32e037..dbab814 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -160,10 +160,18 @@
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
- FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricWithLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink);
- FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition);
+
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition);
+ FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition);
+
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index e88daf7..09913dc 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -80,6 +80,7 @@
mBucketSizeNs = bucketSizeMills * 1000000;
if (metric.has_dimensions_in_what()) {
translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+ mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
}
if (metric.has_dimensions_in_condition()) {
@@ -146,7 +147,7 @@
for (const auto& pair : mPastBuckets) {
const MetricDimensionKey& dimensionKey = pair.first;
- VLOG(" dimension key %s", dimensionKey.c_str());
+ VLOG(" dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -254,7 +255,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("ValueMetric %lld dropping data for dimension key %s",
- (long long)mMetricId, newKey.c_str());
+ (long long)mMetricId, newKey.toString().c_str());
return true;
}
}
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 8f236fa..7b3393f 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -64,7 +64,7 @@
sp<ConditionWizard> wizard, int conditionIndex,
const std::vector<Matcher>& dimensionInCondition, bool nesting,
uint64_t currentBucketStartNs, uint64_t currentBucketNum, uint64_t startTimeNs,
- uint64_t bucketSizeNs, bool conditionSliced,
+ uint64_t bucketSizeNs, bool conditionSliced, bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: mConfigKey(key),
mTrackerId(id),
@@ -80,6 +80,7 @@
mCurrentBucketNum(currentBucketNum),
mStartTimeNs(startTimeNs),
mConditionSliced(conditionSliced),
+ mHasLinksToAllConditionDimensionsInTracker(fullLink),
mAnomalyTrackers(anomalyTrackers){};
virtual ~DurationTracker(){};
@@ -198,6 +199,9 @@
const bool mConditionSliced;
+ bool mSameConditionDimensionsInTracker;
+ bool mHasLinksToAllConditionDimensionsInTracker;
+
std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index b225560..8e0bf26 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -30,20 +30,33 @@
const vector<Matcher>& dimensionInCondition, bool nesting,
uint64_t currentBucketStartNs, uint64_t currentBucketNum,
uint64_t startTimeNs, uint64_t bucketSizeNs,
- bool conditionSliced,
+ bool conditionSliced, bool fullLink,
const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
- conditionSliced, anomalyTrackers) {
+ conditionSliced, fullLink, anomalyTrackers) {
+ if (mWizard != nullptr) {
+ mSameConditionDimensionsInTracker =
+ mWizard->equalOutputDimensions(conditionIndex, mDimensionInCondition);
+ }
}
unique_ptr<DurationTracker> MaxDurationTracker::clone(const uint64_t eventTime) {
auto clonedTracker = make_unique<MaxDurationTracker>(*this);
- for (auto it = clonedTracker->mInfos.begin(); it != clonedTracker->mInfos.end(); ++it) {
- it->second.lastStartTime = eventTime;
- it->second.lastDuration = 0;
+ for (auto it = clonedTracker->mInfos.begin(); it != clonedTracker->mInfos.end();) {
+ if (it->second.state != kStopped) {
+ it->second.lastStartTime = eventTime;
+ it->second.lastDuration = 0;
+ it++;
+ } else {
+ it = clonedTracker->mInfos.erase(it);
+ }
}
- return clonedTracker;
+ if (clonedTracker->mInfos.empty()) {
+ return nullptr;
+ } else {
+ return clonedTracker;
+ }
}
bool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) {
@@ -59,7 +72,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("MaxDurTracker %lld dropping data for dimension key %s",
- (long long)mTrackerId, newKey.c_str());
+ (long long)mTrackerId, newKey.toString().c_str());
return true;
}
}
@@ -77,7 +90,7 @@
if (mConditionSliced) {
duration.conditionKeys = conditionKey;
}
- VLOG("MaxDuration: key %s start condition %d", key.c_str(), condition);
+ VLOG("MaxDuration: key %s start condition %d", key.toString().c_str(), condition);
switch (duration.state) {
case kStarted:
@@ -103,7 +116,7 @@
void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
bool forceStop) {
- VLOG("MaxDuration: key %s stop", key.c_str());
+ VLOG("MaxDuration: key %s stop", key.toString().c_str());
if (mInfos.find(key) == mInfos.end()) {
// we didn't see a start event before. do nothing.
return;
@@ -120,7 +133,7 @@
stopAnomalyAlarm();
duration.state = DurationState::kStopped;
int64_t durationTime = eventTime - duration.lastStartTime;
- VLOG("Max, key %s, Stop %lld %lld %lld", key.c_str(),
+ VLOG("Max, key %s, Stop %lld %lld %lld", key.toString().c_str(),
(long long)duration.lastStartTime, (long long)eventTime,
(long long)durationTime);
duration.lastDuration += durationTime;
@@ -241,13 +254,15 @@
std::unordered_set<HashableDimensionKey> conditionDimensionKeySet;
ConditionState conditionState = mWizard->query(
mConditionTrackerIndex, pair.second.conditionKeys, mDimensionInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
&conditionDimensionKeySet);
bool conditionMet =
(conditionState == ConditionState::kTrue) &&
(mDimensionInCondition.size() == 0 ||
conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) !=
conditionDimensionKeySet.end());
- VLOG("key: %s, condition: %d", pair.first.c_str(), conditionMet);
+ VLOG("key: %s, condition: %d", pair.first.toString().c_str(), conditionMet);
noteConditionChanged(pair.first, conditionMet, timestamp);
}
}
@@ -277,7 +292,7 @@
// In case any other dimensions are still started, we need to set the alarm.
startAnomalyAlarm(timestamp);
}
- VLOG("MaxDurationTracker Key: %s Started->Paused ", key.c_str());
+ VLOG("MaxDurationTracker Key: %s Started->Paused ", key.toString().c_str());
}
break;
case kStopped:
@@ -290,7 +305,7 @@
it->second.state = DurationState::kStarted;
it->second.lastStartTime = timestamp;
startAnomalyAlarm(timestamp);
- VLOG("MaxDurationTracker Key: %s Paused->Started", key.c_str());
+ VLOG("MaxDurationTracker Key: %s Paused->Started", key.toString().c_str());
}
break;
}
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index c731b75..0452d37 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -33,6 +33,7 @@
const std::vector<Matcher>& dimensionInCondition, bool nesting,
uint64_t currentBucketStartNs, uint64_t currentBucketNum,
uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
+ bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
MaxDurationTracker(const MaxDurationTracker& tracker) = default;
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index f583f91..2358415 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -28,14 +28,18 @@
const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, const vector<Matcher>& dimensionInCondition,
bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
- uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
+ uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced, bool fullLink,
const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
- conditionSliced, anomalyTrackers),
+ conditionSliced, fullLink, anomalyTrackers),
mStarted(),
mPaused() {
mLastStartTime = 0;
+ if (mWizard != nullptr) {
+ mSameConditionDimensionsInTracker =
+ mWizard->equalOutputDimensions(conditionIndex, mDimensionInCondition);
+ }
}
unique_ptr<DurationTracker> OringDurationTracker::clone(const uint64_t eventTime) {
@@ -57,7 +61,7 @@
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
ALOGE("OringDurTracker %lld dropping data for dimension key %s",
- (long long)mTrackerId, newKey.c_str());
+ (long long)mTrackerId, newKey.toString().c_str());
return true;
}
}
@@ -83,13 +87,13 @@
if (mConditionSliced && mConditionKeyMap.find(key) == mConditionKeyMap.end()) {
mConditionKeyMap[key] = conditionKey;
}
- VLOG("Oring: %s start, condition %d", key.c_str(), condition);
+ VLOG("Oring: %s start, condition %d", key.toString().c_str(), condition);
}
void OringDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_t timestamp,
const bool stopAll) {
declareAnomalyIfAlarmExpired(timestamp);
- VLOG("Oring: %s stop", key.c_str());
+ VLOG("Oring: %s stop", key.toString().c_str());
auto it = mStarted.find(key);
if (it != mStarted.end()) {
(it->second)--;
@@ -217,22 +221,26 @@
if (!mStarted.empty()) {
for (auto it = mStarted.begin(); it != mStarted.end();) {
const auto& key = it->first;
- if (mConditionKeyMap.find(key) == mConditionKeyMap.end()) {
- VLOG("Key %s dont have condition key", key.c_str());
+ const auto& condIt = mConditionKeyMap.find(key);
+ if (condIt == mConditionKeyMap.end()) {
+ VLOG("Key %s dont have condition key", key.toString().c_str());
++it;
continue;
}
std::unordered_set<HashableDimensionKey> conditionDimensionKeySet;
ConditionState conditionState =
- mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key],
- mDimensionInCondition, &conditionDimensionKeySet);
+ mWizard->query(mConditionTrackerIndex, condIt->second,
+ mDimensionInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
+ &conditionDimensionKeySet);
if (conditionState != ConditionState::kTrue ||
(mDimensionInCondition.size() != 0 &&
conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) ==
conditionDimensionKeySet.end())) {
startedToPaused.push_back(*it);
it = mStarted.erase(it);
- VLOG("Key %s started -> paused", key.c_str());
+ VLOG("Key %s started -> paused", key.toString().c_str());
} else {
++it;
}
@@ -250,21 +258,24 @@
for (auto it = mPaused.begin(); it != mPaused.end();) {
const auto& key = it->first;
if (mConditionKeyMap.find(key) == mConditionKeyMap.end()) {
- VLOG("Key %s dont have condition key", key.c_str());
+ VLOG("Key %s dont have condition key", key.toString().c_str());
++it;
continue;
}
std::unordered_set<HashableDimensionKey> conditionDimensionKeySet;
ConditionState conditionState =
mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key],
- mDimensionInCondition, &conditionDimensionKeySet);
+ mDimensionInCondition,
+ !mSameConditionDimensionsInTracker,
+ !mHasLinksToAllConditionDimensionsInTracker,
+ &conditionDimensionKeySet);
if (conditionState == ConditionState::kTrue &&
(mDimensionInCondition.size() == 0 ||
conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) !=
conditionDimensionKeySet.end())) {
pausedToStarted.push_back(*it);
it = mPaused.erase(it);
- VLOG("Key %s paused -> started", key.c_str());
+ VLOG("Key %s paused -> started", key.toString().c_str());
} else {
++it;
}
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 07c1329..610e3ea 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -32,6 +32,7 @@
int conditionIndex, const std::vector<Matcher>& dimensionInCondition,
bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
+ bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
OringDurationTracker(const OringDurationTracker& tracker) = default;
diff --git a/cmds/statsd/src/stats_util.h b/cmds/statsd/src/stats_util.h
index bbaf50a..80e46d6 100644
--- a/cmds/statsd/src/stats_util.h
+++ b/cmds/statsd/src/stats_util.h
@@ -32,7 +32,7 @@
// Minimum bucket size in seconds
const long kMinBucketSizeSec = 5 * 60;
-typedef std::map<int64_t, std::vector<HashableDimensionKey>> ConditionKey;
+typedef std::map<int64_t, HashableDimensionKey> ConditionKey;
typedef std::unordered_map<MetricDimensionKey, int64_t> DimToValMap;
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 3dc3fd1..e826a52 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -75,10 +75,10 @@
event->init();
}
-std::map<int64_t, std::vector<HashableDimensionKey>> getWakeLockQueryKey(
+std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
const Position position,
const std::vector<int> &uids, const string& conditionName) {
- std::map<int64_t, std::vector<HashableDimensionKey>> outputKeyMap;
+ std::map<int64_t, HashableDimensionKey> outputKeyMap;
std::vector<int> uid_indexes;
int pos[] = {1, 1, 1};
int depth = 2;
@@ -104,7 +104,7 @@
Value value((int32_t)uids[idx]);
HashableDimensionKey dim;
dim.addValue(FieldValue(field, value));
- outputKeyMap[StringToId(conditionName)].push_back(dim);
+ outputKeyMap[StringToId(conditionName)] = dim;
}
return outputKeyMap;
}
@@ -122,6 +122,7 @@
SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
simplePredicate, trackerNameIndexMap);
+ EXPECT_FALSE(conditionTracker.isSliced());
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
@@ -193,6 +194,7 @@
}
TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
+ std::vector<sp<ConditionTracker>> allConditions;
SimplePredicate simplePredicate;
simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
@@ -205,6 +207,7 @@
SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
+ EXPECT_FALSE(conditionTracker.isSliced());
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
@@ -257,14 +260,14 @@
conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
changedCache);
- // result should still be true
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
EXPECT_TRUE(changedCache[0]);
}
TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
+ std::vector<sp<ConditionTracker>> allConditions;
for (Position position :
- { Position::ANY, Position::FIRST, Position::LAST}) {
+ { Position::FIRST, Position::LAST}) {
vector<Matcher> dimensionInCondition;
std::unordered_set<HashableDimensionKey> dimensionKeys;
@@ -281,6 +284,7 @@
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
+
std::vector<int> uids = {111, 222, 333};
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
@@ -305,12 +309,20 @@
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
+ if (position == Position::FIRST ||
+ position == Position::LAST) {
+ EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
+ }
// Now test query
const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
@@ -331,6 +343,9 @@
} else {
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+
// wake lock 1 release
LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
@@ -350,6 +365,8 @@
} else {
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
@@ -362,18 +379,26 @@
changedCache);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
+ if (position == Position::FIRST ||
+ position == Position::LAST) {
+ EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
+ }
// query again
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-
}
}
TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
+ std::vector<sp<ConditionTracker>> allConditions;
vector<Matcher> dimensionInCondition;
std::unordered_set<HashableDimensionKey> dimensionKeys;
@@ -391,6 +416,8 @@
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
+ EXPECT_FALSE(conditionTracker.isSliced());
+
std::vector<int> uid_list1 = {111, 1111, 11111};
string uid1_wl1 = "wl1_1";
std::vector<int> uid_list2 = {222, 2222, 22222};
@@ -419,6 +446,7 @@
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ true, true,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
@@ -463,13 +491,15 @@
conditionCache[0] = ConditionState::kNotEvaluated;
dimensionKeys.clear();
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ true, true,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
TEST(SimpleConditionTrackerTest, TestStopAll) {
+ std::vector<sp<ConditionTracker>> allConditions;
for (Position position :
- {Position::ANY, Position::FIRST, Position::LAST}) {
+ { Position::FIRST, Position::LAST }) {
vector<Matcher> dimensionInCondition;
std::unordered_set<HashableDimensionKey> dimensionKeys;
SimplePredicate simplePredicate = getWakeLockHeldCondition(
@@ -510,12 +540,23 @@
EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
+ {
+ if (position == Position::FIRST ||
+ position == Position::LAST) {
+ EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ }
+ }
// Now test query
const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
@@ -538,11 +579,23 @@
conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
+ {
+ if (position == Position::FIRST ||
+ position == Position::LAST) {
+ EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ }
+ }
+
// TEST QUERY
const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
@@ -561,11 +614,22 @@
changedCache);
EXPECT_TRUE(changedCache[0]);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+ {
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(uid_list1.size() + uid_list2.size(),
+ conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ }
+ }
// TEST QUERY
const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
@@ -573,6 +637,7 @@
const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
+ false, false,
conditionCache, dimensionKeys);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
new file mode 100644
index 0000000..a08f606
--- /dev/null
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -0,0 +1,879 @@
+// 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.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto screenIsOffPredicate = CreateScreenIsOffPredicate();
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+ {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = screenIsOffPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+ auto combinationPredicate = config.add_predicate();
+ combinationPredicate->set_id(StringToId("CombinationPredicate"));
+ combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
+ addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
+ auto dimensionWhat = metric->mutable_dimensions_in_what();
+ dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensionWhat->add_child()->set_field(2); // job name field.
+ *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition) {
+ for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) {
+ for (auto aggregationType : {DurationMetric::MAX_SPARSE, DurationMetric::SUM}) {
+ ConfigKey cfgKey;
+ auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
+ aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 11));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 40));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 102));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 450));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 650));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 100));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + bucketSizeNs + 640));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 650));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 10));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 200));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 300));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 401));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job0"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+
+ data = metrics.data(1);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job1"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100 + 650 - 640);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job0"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job1"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 110);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+ }
+}
+
+namespace {
+
+StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *dimensions = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ auto screenIsOffPredicate = CreateScreenIsOffPredicate();
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = screenIsOffPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+ auto combinationPredicate = config.add_predicate();
+ combinationPredicate->set_id(StringToId("CombinationPredicate"));
+ combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
+ addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
+ *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+
+ auto links = metric->add_links();
+ links->set_condition(isSyncingPredicate.id());
+ *links->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *links->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition) {
+ for (bool isFullLink : {true, false}) {
+ for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+ ConfigKey cfgKey;
+ auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition(
+ aggregationType, !isFullLink);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions3 = {
+ CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 55));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 120));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 121));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 450));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 501));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 100));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",
+ bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(
+ CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs - 2));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 110));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 300));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 550));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 800));
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(metrics.data_size(), 3);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 3);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+ }
+}
+
+namespace {
+
+StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition(
+ DurationMetric::AggregationType aggregationType) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *dimensions = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ syncDimension->add_child()->set_field(2 /* name field*/);
+
+ auto screenIsOffPredicate = CreateScreenIsOffPredicate();
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = screenIsOffPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+ auto combinationPredicate = config.add_predicate();
+ combinationPredicate->set_id(StringToId("CombinationPredicate"));
+ combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
+ addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
+ *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *metric->mutable_dimensions_in_condition() = *syncDimension;
+
+
+ auto links = metric->add_links();
+ links->set_condition(isSyncingPredicate.id());
+ *links->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *links->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition) {
+ for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+ ConfigKey cfgKey;
+ auto config =
+ CreateDurationMetricConfig_PartialLink_AND_CombinationCondition(aggregationType);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions3 = {
+ CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 55));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 120));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 121));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 450));
+
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 501));
+ events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+ bucketStartTimeNs + bucketSizeNs + 100));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",
+ bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(
+ CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs - 2));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 110));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 300));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 550));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 800));
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 600 + 50);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 50);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
similarity index 85%
rename from cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
rename to cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index 01348bd..435e199 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -28,7 +28,7 @@
namespace {
-StatsdConfig CreateCountMetricWithNoLinkConfig() {
+StatsdConfig CreateCountMetric_NoLink_CombinationCondition_Config() {
StatsdConfig config;
auto screenBrightnessChangeAtomMatcher = CreateScreenBrightnessChangedAtomMatcher();
*config.add_atom_matcher() = screenBrightnessChangeAtomMatcher;
@@ -67,9 +67,9 @@
} // namespace
-TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) {
+TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition) {
ConfigKey cfgKey;
- auto config = CreateCountMetricWithNoLinkConfig();
+ auto config = CreateCountMetric_NoLink_CombinationCondition_Config();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
@@ -227,7 +227,7 @@
namespace {
-StatsdConfig CreateCountMetricWithLinkConfig() {
+StatsdConfig CreateCountMetric_Link_CombinationCondition() {
StatsdConfig config;
auto appCrashMatcher = CreateProcessCrashAtomMatcher();
*config.add_atom_matcher() = appCrashMatcher;
@@ -274,9 +274,9 @@
} // namespace
-TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) {
+TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition) {
ConfigKey cfgKey;
- auto config = CreateCountMetricWithLinkConfig();
+ auto config = CreateCountMetric_Link_CombinationCondition();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
@@ -413,7 +413,8 @@
namespace {
-StatsdConfig CreateDurationMetricConfigNoLink(DurationMetric::AggregationType aggregationType) {
+StatsdConfig CreateDurationMetricConfig_NoLink_CombinationCondition(
+ DurationMetric::AggregationType aggregationType) {
StatsdConfig config;
*config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
*config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
@@ -445,6 +446,7 @@
metric->set_id(StringToId("BatterySaverModeDurationMetric"));
metric->set_what(inBatterySaverModePredicate.id());
metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
*metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
android::util::SYNC_STATE_CHANGED, {Position::FIRST});
return config;
@@ -452,10 +454,10 @@
} // namespace
-TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) {
- for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition) {
+ for (auto aggregationType : { DurationMetric::MAX_SPARSE}) { // DurationMetric::SUM,
ConfigKey cfgKey;
- auto config = CreateDurationMetricConfigNoLink(aggregationType);
+ auto config = CreateDurationMetricConfig_NoLink_CombinationCondition(aggregationType);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
@@ -529,43 +531,77 @@
auto data = metrics.data(0);
EXPECT_FALSE(data.dimensions_in_what().has_field());
EXPECT_FALSE(data.dimensions_in_condition().has_field());
- EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
data = metrics.data(1);
EXPECT_FALSE(data.dimensions_in_what().has_field());
ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
android::util::SYNC_STATE_CHANGED, 111, "App1");
EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600);
+
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300);
+ } else {
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 300);
+ }
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
data = metrics.data(2);
EXPECT_FALSE(data.dimensions_in_what().has_field());
ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
android::util::SYNC_STATE_CHANGED, 333, "App2");
EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ } else {
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs + 700 - 600);
+ }
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
}
}
namespace {
-StatsdConfig CreateDurationMetricConfigWithLink(DurationMetric::AggregationType aggregationType) {
+StatsdConfig CreateDurationMetricConfig_Link_CombinationCondition(
+ DurationMetric::AggregationType aggregationType) {
StatsdConfig config;
*config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
*config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
@@ -599,6 +635,7 @@
metric->set_id(StringToId("AppInBackgroundMetric"));
metric->set_what(isInBackgroundPredicate.id());
metric->set_condition(combinationPredicate->id());
+ metric->set_aggregation_type(aggregationType);
*metric->mutable_dimensions_in_what() =
CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */});
*metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
@@ -617,10 +654,10 @@
} // namespace
-TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) {
+TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition) {
for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
ConfigKey cfgKey;
- auto config = CreateDurationMetricConfigWithLink(aggregationType);
+ auto config = CreateDurationMetricConfig_Link_CombinationCondition(aggregationType);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
@@ -701,26 +738,50 @@
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
android::util::SYNC_STATE_CHANGED, 111, "App1");
- EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 100 - 201);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
data = metrics.data(2);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
android::util::SYNC_STATE_CHANGED, 333, "App2");
- EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 299);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
}
}
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
new file mode 100644
index 0000000..75ceafb
--- /dev/null
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -0,0 +1,799 @@
+// 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.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateDurationMetricConfig_NoLink_SimpleCondition(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+ {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(isSyncingPredicate.id());
+ metric->set_aggregation_type(aggregationType);
+ auto dimensionWhat = metric->mutable_dimensions_in_what();
+ dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ dimensionWhat->add_child()->set_field(2); // job name field.
+ *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition) {
+ for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : {true, false}) {
+ for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+ ConfigKey cfgKey;
+ auto config = CreateDurationMetricConfig_NoLink_SimpleCondition(
+ aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 10));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 200));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 300));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 401));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job0"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job1"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job0"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job1"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 300);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ EXPECT_EQ(data.dimensions_in_what().field(),
+ android::util::SCHEDULED_JOB_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
+ 2); // job name field
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
+ "job2"); // job name
+ ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+ android::util::SYNC_STATE_CHANGED, 333, "App2");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 );
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+ }
+}
+
+namespace {
+
+StatsdConfig createDurationMetric_Link_SimpleConditionConfig(
+ DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *dimensions = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ if (addExtraDimensionInCondition) {
+ syncDimension->add_child()->set_field(2 /* name field*/);
+ }
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(isSyncingPredicate.id());
+ metric->set_aggregation_type(aggregationType);
+ *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+
+ auto links = metric->add_links();
+ links->set_condition(isSyncingPredicate.id());
+ *links->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *links->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition) {
+ for (bool isFullLink : {true, false}) {
+ for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+ ConfigKey cfgKey;
+ auto config = createDurationMetric_Link_SimpleConditionConfig(
+ aggregationType, !isFullLink);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions3 = {
+ CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(333, "App2")}, "job2",
+ bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(
+ CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs - 2));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 110));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 300));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 550));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 800));
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(metrics.data_size(), 3);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 3);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 701);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+ }
+}
+
+namespace {
+
+StatsdConfig createDurationMetric_PartialLink_SimpleConditionConfig(
+ DurationMetric::AggregationType aggregationType) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
+ *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
+
+ auto scheduledJobPredicate = CreateScheduledJobPredicate();
+ auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *dimensions = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ dimensions->add_child()->set_field(2); // job name field.
+
+ auto isSyncingPredicate = CreateIsSyncingPredicate();
+ auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
+ *syncDimension = CreateAttributionUidDimensions(
+ android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ syncDimension->add_child()->set_field(2 /* name field*/);
+
+ *config.add_predicate() = scheduledJobPredicate;
+ *config.add_predicate() = isSyncingPredicate;
+
+ auto metric = config.add_duration_metric();
+ metric->set_bucket(FIVE_MINUTES);
+ metric->set_id(StringToId("scheduledJob"));
+ metric->set_what(scheduledJobPredicate.id());
+ metric->set_condition(isSyncingPredicate.id());
+ metric->set_aggregation_type(aggregationType);
+ *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *metric->mutable_dimensions_in_condition() = *syncDimension;
+
+ auto links = metric->add_links();
+ links->set_condition(isSyncingPredicate.id());
+ *links->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(
+ android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *links->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ return config;
+}
+
+} // namespace
+
+TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition) {
+ for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+ ConfigKey cfgKey;
+ auto config = createDurationMetric_PartialLink_SimpleConditionConfig(
+ aggregationType);
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+ auto processor = CreateStatsLogProcessor(
+ bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {
+ CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(222, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions2 = {
+ CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<AttributionNodeInternal> attributions3 = {
+ CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(555, "GMSCoreModule2")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
+
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
+ events.push_back(CreateStartScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
+ events.push_back(CreateFinishScheduledJobEvent(
+ {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + bucketSizeNs + 850));
+
+ events.push_back(
+ CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs - 2));
+ events.push_back(
+ CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
+ bucketStartTimeNs + bucketSizeNs + 900));
+
+ events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 50));
+ events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
+ bucketStartTimeNs + 110));
+
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + 300));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
+ bucketStartTimeNs + bucketSizeNs + 700));
+ events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + 400));
+ events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 550));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + 800));
+ events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
+ bucketStartTimeNs + bucketSizeNs + 700));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ EXPECT_TRUE(buffer.size() > 0);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::DurationMetricDataWrapper metrics;
+ sortMetricDataByDimensionsValue(
+ reports.reports(0).metrics(0).duration_metrics(), &metrics);
+
+ if (aggregationType == DurationMetric::SUM) {
+ EXPECT_EQ(4, metrics.data_size());
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 400 - 100);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300 + bucketSizeNs - 600);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ } else {
+ EXPECT_EQ(metrics.data_size(), 4);
+ auto data = metrics.data(0);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+
+ data = metrics.data(1);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600);
+
+ data = metrics.data(2);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
+ EXPECT_EQ("ReadEmail",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300);
+ EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = metrics.data(3);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
+ ValidateAttributionUidDimension(
+ data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
+ EXPECT_EQ("ReadDoc",
+ data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).duration_nanos(), 701);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
+ bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
+ bucketStartTimeNs + 2 * bucketSizeNs);
+ }
+ }
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index 7d9c8a8..fc6e420 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -34,7 +34,7 @@
* Test merge isolated and host uid
*/
-int uidAtomTagId = android::util::CPU_TIME_PER_UID_FREQ;
+int uidAtomTagId = android::util::CPU_CLUSTER_TIME;
int nonUidAtomTagId = android::util::SYSTEM_UPTIME;
int timestamp = 1234;
int isolatedUid = 30;
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 9a0de0d..a07683e 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -175,9 +175,9 @@
{getMockedDimensionKey(conditionTagId, 2, "222")};
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, key1, _, _)).WillOnce(Return(ConditionState::kFalse));
+ EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
- EXPECT_CALL(*wizard, query(_, key2, _, _)).WillOnce(Return(ConditionState::kTrue));
+ EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
bucketStartTimeNs);
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 8246268..23d3171 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -113,9 +113,9 @@
key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, key1, _, _)).WillOnce(Return(ConditionState::kFalse));
+ EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
- EXPECT_CALL(*wizard, query(_, key2, _, _)).WillOnce(Return(ConditionState::kTrue));
+ EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 83b1cbf..57a8925 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -42,14 +42,13 @@
const int TagId = 1;
const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "1");
-const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
+const HashableDimensionKey conditionKey = getMockedDimensionKey(TagId, 4, "1");
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
const uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
@@ -66,7 +65,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- false, {});
+ false, false, {});
tracker.noteStart(key1, true, bucketStartTimeNs, ConditionKey());
// Event starts again. This would not change anything as it already starts.
@@ -86,7 +85,6 @@
TEST(MaxDurationTrackerTest, TestStopAll) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
@@ -103,7 +101,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- false, {});
+ false, false, {});
tracker.noteStart(key1, true, bucketStartTimeNs + 1, ConditionKey());
@@ -124,7 +122,6 @@
TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
vector<Matcher> dimensionInCondition;
@@ -140,7 +137,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- false, {});
+ false, false, {});
// The event starts.
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -166,7 +163,6 @@
TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
vector<Matcher> dimensionInCondition;
@@ -182,7 +178,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- false, {});
+ false, false, {});
// 2 starts
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -204,14 +200,14 @@
}
TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) {
- const std::vector<HashableDimensionKey> conditionKey = {key1};
+ const HashableDimensionKey conditionDimKey = key1;
vector<Matcher> dimensionInCondition;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
ConditionKey conditionKey1;
MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 1, "1");
- conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey;
+ conditionKey1[StringToId("APP_BACKGROUND")] = conditionDimKey;
/**
Start in first bucket, stop in second bucket. Condition turns on and off in the first bucket
@@ -229,7 +225,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, true,
- {});
+ false, {});
EXPECT_TRUE(tracker.mAnomalyTrackers.empty());
tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1);
@@ -250,8 +246,6 @@
}
TEST(MaxDurationTrackerTest, TestAnomalyDetection) {
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
-
vector<Matcher> dimensionInCondition;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
@@ -281,7 +275,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- true, {anomalyTracker});
+ true, false, {anomalyTracker});
tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
sp<const InternalAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
@@ -301,8 +295,6 @@
// This tests that we correctly compute the predicted time of an anomaly assuming that the current
// state continues forward as-is.
TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp) {
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
-
vector<Matcher> dimensionInCondition;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
@@ -310,7 +302,7 @@
MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps");
conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey;
ConditionKey conditionKey2;
- conditionKey2[StringToId("APP_BACKGROUND")] = {getMockedDimensionKey(TagId, 4, "2")};
+ conditionKey2[StringToId("APP_BACKGROUND")] = getMockedDimensionKey(TagId, 4, "2");
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -343,7 +335,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- true, {anomalyTracker});
+ true, false, {anomalyTracker});
tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1);
tracker.noteConditionChanged(key1, true, conditionStarts1);
@@ -360,8 +352,6 @@
// Suppose A starts, then B starts, and then A stops. We still need to set an anomaly based on the
// elapsed duration of B.
TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop) {
- const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
-
vector<Matcher> dimensionInCondition;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
@@ -369,7 +359,7 @@
MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps");
conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey;
ConditionKey conditionKey2;
- conditionKey2[StringToId("APP_BACKGROUND")] = {getMockedDimensionKey(TagId, 4, "2")};
+ conditionKey2[StringToId("APP_BACKGROUND")] = getMockedDimensionKey(TagId, 4, "2");
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -399,7 +389,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
- true, {anomalyTracker});
+ true, false, {anomalyTracker});
tracker.noteStart(key1, true, eventStartTimeNs1, conditionKey1);
tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2);
@@ -415,4 +405,4 @@
} // namespace android
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
+#endif
\ No newline at end of file
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index aa41038..54abcb2 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -40,7 +40,7 @@
const int64_t metricId = 123;
const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "event");
-const std::vector<HashableDimensionKey> kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")};
+const HashableDimensionKey kConditionKey1 = getMockedDimensionKey(TagId, 1, "maps");
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
const uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
@@ -48,8 +48,6 @@
TEST(OringDurationTrackerTest, TestDurationOverlap) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -65,7 +63,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, false, {});
+ bucketSizeNs, false, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -83,8 +81,6 @@
TEST(OringDurationTrackerTest, TestDurationNested) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -99,7 +95,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, false, {});
+ bucketSizeNs, false, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
@@ -132,7 +128,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, false, {});
+ bucketSizeNs, false, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
@@ -148,8 +144,6 @@
TEST(OringDurationTrackerTest, TestCrossBucketBoundary) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -165,7 +159,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, false, {});
+ bucketSizeNs, false, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -189,8 +183,6 @@
TEST(OringDurationTrackerTest, TestDurationConditionChange) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -199,7 +191,7 @@
ConditionKey key1;
key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
- EXPECT_CALL(*wizard, query(_, key1, _, _)) // #4
+ EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)) // #4
.WillOnce(Return(ConditionState::kFalse));
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -212,7 +204,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, true, {});
+ bucketSizeNs, true, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
@@ -229,8 +221,6 @@
TEST(OringDurationTrackerTest, TestDurationConditionChange2) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -239,7 +229,7 @@
ConditionKey key1;
key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
- EXPECT_CALL(*wizard, query(_, key1, _, _))
+ EXPECT_CALL(*wizard, query(_, key1, _, _, _, _))
.Times(2)
.WillOnce(Return(ConditionState::kFalse))
.WillOnce(Return(ConditionState::kTrue));
@@ -254,7 +244,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, true, {});
+ bucketSizeNs, true, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
// condition to false; record duration 5n
@@ -273,8 +263,6 @@
TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -283,7 +271,7 @@
ConditionKey key1;
key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
- EXPECT_CALL(*wizard, query(_, key1, _, _)) // #4
+ EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)) // #4
.WillOnce(Return(ConditionState::kFalse));
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -295,7 +283,7 @@
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, true, {});
+ bucketSizeNs, true, false, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1);
@@ -315,8 +303,6 @@
TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -339,7 +325,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, true, {anomalyTracker});
+ bucketSizeNs, true, false, {anomalyTracker});
// Nothing in the past bucket.
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
@@ -386,7 +372,6 @@
TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -410,7 +395,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true /*nesting*/, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
- bucketSizeNs, false, {anomalyTracker});
+ bucketSizeNs, false, false, {anomalyTracker});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false);
@@ -437,8 +422,6 @@
TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
- const std::vector<HashableDimensionKey> kConditionKey1 =
- {getMockedDimensionKey(TagId, 1, "maps")};
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
vector<Matcher> dimensionInCondition;
@@ -462,7 +445,7 @@
new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true /*nesting*/, bucketStartTimeNs, 0, bucketStartTimeNs,
- bucketSizeNs, false, {anomalyTracker});
+ bucketSizeNs, false, false, {anomalyTracker});
tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1
EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
@@ -508,4 +491,4 @@
} // namespace android
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
+#endif
\ No newline at end of file
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index a01de63..f040bf9 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -26,9 +26,10 @@
class MockConditionWizard : public ConditionWizard {
public:
- MOCK_METHOD4(query,
+ MOCK_METHOD6(query,
ConditionState(const int conditionIndex, const ConditionKey& conditionParameters,
const vector<Matcher>& dimensionFields,
+ const bool isSubsetDim, const bool isPartialLink,
std::unordered_set<HashableDimensionKey>* dimensionKeySet));
};
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 242b6eb..2678c8a 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -26,6 +26,28 @@
return atom_matcher;
}
+AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name,
+ ScheduledJobStateChanged::State state) {
+ AtomMatcher atom_matcher;
+ atom_matcher.set_id(StringToId(name));
+ auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+ simple_atom_matcher->set_atom_id(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+ field_value_matcher->set_field(3); // State field.
+ field_value_matcher->set_eq_int(state);
+ return atom_matcher;
+}
+
+AtomMatcher CreateStartScheduledJobAtomMatcher() {
+ return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobStart",
+ ScheduledJobStateChanged::STARTED);
+}
+
+AtomMatcher CreateFinishScheduledJobAtomMatcher() {
+ return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobFinish",
+ ScheduledJobStateChanged::FINISHED);
+}
+
AtomMatcher CreateScreenBrightnessChangedAtomMatcher() {
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId("ScreenBrightnessChanged"));
@@ -168,6 +190,14 @@
"ProcessCrashed", ProcessLifeCycleStateChanged::PROCESS_CRASHED);
}
+Predicate CreateScheduledJobPredicate() {
+ Predicate predicate;
+ predicate.set_id(StringToId("ScheduledJobRunningPredicate"));
+ predicate.mutable_simple_predicate()->set_start(StringToId("ScheduledJobStart"));
+ predicate.mutable_simple_predicate()->set_stop(StringToId("ScheduledJobFinish"));
+ return predicate;
+}
+
Predicate CreateBatterySaverModePredicate() {
Predicate predicate;
predicate.set_id(StringToId("BatterySaverIsOn"));
@@ -290,6 +320,32 @@
}
+std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
+ const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
+ const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
+ auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
+ event->write(attributions);
+ event->write(jobName);
+ event->write(state);
+ event->init();
+ return event;
+}
+
+std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs) {
+ return CreateScheduledJobStateChangedEvent(
+ attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
+}
+
+// Create log event when scheduled job finishes.
+std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs) {
+ return CreateScheduledJobStateChangedEvent(
+ attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
+}
+
std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
const WakelockStateChanged::State state, uint64_t timestampNs) {
@@ -419,7 +475,6 @@
void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid) {
EXPECT_EQ(value.field(), atomId);
- EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
// Attribution field.
EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
// Uid only.
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 1708cc3..14eba1f 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -28,6 +28,15 @@
// Create AtomMatcher proto to simply match a specific atom type.
AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
+// Create AtomMatcher proto for scheduled job state changed.
+AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
+
+// Create AtomMatcher proto for starting a scheduled job.
+AtomMatcher CreateStartScheduledJobAtomMatcher();
+
+// Create AtomMatcher proto for a scheduled job is done.
+AtomMatcher CreateFinishScheduledJobAtomMatcher();
+
// Create AtomMatcher proto for screen brightness state changed.
AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
@@ -73,6 +82,9 @@
// Create Predicate proto for screen is off.
Predicate CreateScreenIsOffPredicate();
+// Create Predicate proto for a running scheduled job.
+Predicate CreateScheduledJobPredicate();
+
// Create Predicate proto for battery saver mode.
Predicate CreateBatterySaverModePredicate();
@@ -107,6 +119,16 @@
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
int level, uint64_t timestampNs);
+// Create log event when scheduled job starts.
+std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs);
+
+// Create log event when scheduled job finishes.
+std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+ const std::vector<AttributionNodeInternal>& attributions,
+ const string& name, uint64_t timestampNs);
+
// Create log event when battery saver starts.
std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
// Create log event when battery saver stops.
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 9528ff1..68f6546 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -246,6 +246,7 @@
Landroid/app/Dialog;->mShowMessage:Landroid/os/Message;
Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
+Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
Landroid/app/Fragment;->mWho:Ljava/lang/String;
Landroid/app/IActivityManager;->bindService(Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/content/Intent;Ljava/lang/String;Landroid/app/IServiceConnection;ILjava/lang/String;I)I
@@ -576,6 +577,7 @@
Landroid/content/res/Resources;->loadXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser;
Landroid/content/res/Resources;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser;
Landroid/content/res/Resources;->mResourcesImpl:Landroid/content/res/ResourcesImpl;
+Landroid/content/res/Resources;->mSystem:Landroid/content/res/Resources;
Landroid/content/res/Resources;->mTmpValue:Landroid/util/TypedValue;
Landroid/content/res/Resources;->mTypedArrayPool:Landroid/util/Pools$SynchronizedPool;
Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
@@ -1279,6 +1281,7 @@
Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
Landroid/os/HwBlob;-><init>(I)V
Landroid/os/HwParcel;-><init>(Z)V
+Landroid/os/HwRemoteBinder;-><init>()V
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index ef41b10..d568662 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2237,6 +2237,22 @@
return mWindowNodes.get(index);
}
+ // TODO(b/35708678): temporary method that disable one-way warning flag on binder.
+ /** @hide */
+ public void ensureDataForAutofill() {
+ if (mHaveData) {
+ return;
+ }
+ mHaveData = true;
+ Binder.allowBlocking(mReceiveChannel);
+ try {
+ ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
+ reader.go();
+ } finally {
+ Binder.defaultBlocking(mReceiveChannel);
+ }
+ }
+
/** @hide */
public void ensureData() {
if (mHaveData) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4a8f61c..efa90d3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -763,15 +763,13 @@
public String[] resourceDirs;
/**
- * String retrieved from the seinfo tag found in selinux policy. This value
- * can be overridden with a value set through the mac_permissions.xml policy
- * construct. This value is useful in setting an SELinux security context on
- * the process as well as its data directory. The String default is being used
- * here to represent a catchall label when no policy matches.
+ * String retrieved from the seinfo tag found in selinux policy. This value can be set through
+ * the mac_permissions.xml policy construct. This value is used for setting an SELinux security
+ * context on the process as well as its data directory.
*
* {@hide}
*/
- public String seInfo = "default";
+ public String seInfo;
/**
* The seinfo tag generated per-user. This value may change based upon the
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 7717b8d..2a791ec 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -292,8 +292,10 @@
final boolean walEnabled =
(mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
// Use compatibility WAL unless an app explicitly set journal/synchronous mode
+ // or DISABLE_COMPATIBILITY_WAL flag is set
final boolean useCompatibilityWal = mConfiguration.journalMode == null
- && mConfiguration.syncMode == null && mConfiguration.useCompatibilityWal;
+ && mConfiguration.syncMode == null
+ && (mConfiguration.openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
if (walEnabled || useCompatibilityWal) {
setJournalMode("WAL");
if (useCompatibilityWal && SQLiteCompatibilityWalFlags.areFlagsSet()) {
@@ -423,8 +425,8 @@
boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled
!= mConfiguration.foreignKeyConstraintsEnabled;
boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
- & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0
- || configuration.useCompatibilityWal != mConfiguration.useCompatibilityWal;
+ & (SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING
+ | SQLiteDatabase.DISABLE_COMPATIBILITY_WAL)) != 0;
boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
// Update configuration parameters.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index dc60612..dadb95b 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -315,7 +315,12 @@
}
}
- if (mConfiguration.openFlags != configuration.openFlags) {
+ // We should do in-place switching when transitioning from compatibility WAL
+ // to rollback journal. Otherwise transient connection state will be lost
+ boolean onlyCompatWalChanged = (mConfiguration.openFlags ^ configuration.openFlags)
+ == SQLiteDatabase.DISABLE_COMPATIBILITY_WAL;
+
+ if (!onlyCompatWalChanged && mConfiguration.openFlags != configuration.openFlags) {
// If we are changing open flags and WAL mode at the same time, then
// we have no choice but to close the primary connection beforehand
// because there can only be one connection open when we change WAL mode.
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index ae1f57d..b463d8d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -253,6 +253,13 @@
public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
/**
+ * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
+ *
+ * @hide
+ */
+ public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
+
+ /**
* Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
*
* Each prepared-statement is between 1K - 6K, depending on the complexity of the
@@ -288,10 +295,10 @@
mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
mConfigurationLocked.journalMode = journalMode;
mConfigurationLocked.syncMode = syncMode;
- mConfigurationLocked.useCompatibilityWal = SQLiteGlobal.isCompatibilityWalSupported();
- if (!mConfigurationLocked.isInMemoryDb() && SQLiteCompatibilityWalFlags.areFlagsSet()) {
- mConfigurationLocked.useCompatibilityWal = SQLiteCompatibilityWalFlags
- .isCompatibilityWalSupported();
+ if (!SQLiteGlobal.isCompatibilityWalSupported() || (
+ SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
+ .isCompatibilityWalSupported())) {
+ mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
}
}
@@ -2082,21 +2089,21 @@
synchronized (mLock) {
throwIfNotOpenLocked();
- final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal;
final int oldFlags = mConfigurationLocked.openFlags;
- if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
+ final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
+ final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
+ if (walDisabled && compatibilityWalDisabled) {
return;
}
mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
- // If an app explicitly disables WAL, do not even use compatibility mode
- mConfigurationLocked.useCompatibilityWal = false;
+ // If an app explicitly disables WAL, compatibility mode should be disabled too
+ mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.openFlags = oldFlags;
- mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal;
throw ex;
}
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index a14df1e..275043f 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -111,15 +111,6 @@
public long idleConnectionTimeoutMs = Long.MAX_VALUE;
/**
- * Enables compatibility WAL mode. Applications cannot explicitly choose compatibility WAL mode,
- * therefore it is not exposed as a flag.
- *
- * <p>In this mode, only database journal mode will be changed, connection pool
- * size will still be limited to a single connection.
- */
- public boolean useCompatibilityWal;
-
- /**
* Journal mode to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} is not set.
* <p>Default is returned by {@link SQLiteGlobal#getDefaultJournalMode()}
*/
@@ -191,7 +182,6 @@
lookasideSlotSize = other.lookasideSlotSize;
lookasideSlotCount = other.lookasideSlotCount;
idleConnectionTimeoutMs = other.idleConnectionTimeoutMs;
- useCompatibilityWal = other.useCompatibilityWal;
journalMode = other.journalMode;
syncMode = other.syncMode;
}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 64e9e5d..7ff6635 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -197,6 +197,8 @@
}
mOpenParamsBuilder.setWriteAheadLoggingEnabled(enabled);
}
+ // Compatibility WAL is disabled if an app disables or enables WAL
+ mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.DISABLE_COMPATIBILITY_WAL);
}
}
diff --git a/core/java/android/hardware/radio/RadioMetadata.java b/core/java/android/hardware/radio/RadioMetadata.java
index 3cc4b56..6e51060 100644
--- a/core/java/android/hardware/radio/RadioMetadata.java
+++ b/core/java/android/hardware/radio/RadioMetadata.java
@@ -96,6 +96,48 @@
*/
public static final String METADATA_KEY_CLOCK = "android.hardware.radio.metadata.CLOCK";
+ /**
+ * Technology-independent program name (station name).
+ */
+ public static final String METADATA_KEY_PROGRAM_NAME =
+ "android.hardware.radio.metadata.PROGRAM_NAME";
+
+ /**
+ * DAB ensemble name.
+ */
+ public static final String METADATA_KEY_DAB_ENSEMBLE_NAME =
+ "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME";
+
+ /**
+ * DAB ensemble name - short version (up to 8 characters).
+ */
+ public static final String METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME_SHORT";
+
+ /**
+ * DAB service name.
+ */
+ public static final String METADATA_KEY_DAB_SERVICE_NAME =
+ "android.hardware.radio.metadata.DAB_SERVICE_NAME";
+
+ /**
+ * DAB service name - short version (up to 8 characters).
+ */
+ public static final String METADATA_KEY_DAB_SERVICE_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_SERVICE_NAME_SHORT";
+
+ /**
+ * DAB component name.
+ */
+ public static final String METADATA_KEY_DAB_COMPONENT_NAME =
+ "android.hardware.radio.metadata.DAB_COMPONENT_NAME";
+
+ /**
+ * DAB component name.
+ */
+ public static final String METADATA_KEY_DAB_COMPONENT_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_COMPONENT_NAME_SHORT";
+
private static final int METADATA_TYPE_INVALID = -1;
private static final int METADATA_TYPE_INT = 0;
@@ -119,6 +161,13 @@
METADATA_KEYS_TYPE.put(METADATA_KEY_ICON, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_CLOCK, METADATA_TYPE_CLOCK);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_PROGRAM_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME_SHORT, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME_SHORT, METADATA_TYPE_TEXT);
}
// keep in sync with: system/media/radio/include/system/radio_metadata.h
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 8588df7..a132730 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -788,8 +788,8 @@
com.android.internal.R.style.Animation_Wallpaper;
mInputChannel = new InputChannel();
if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
- Display.DEFAULT_DISPLAY, mContentInsets, mStableInsets, mOutsets,
- mDisplayCutout, mInputChannel) < 0) {
+ Display.DEFAULT_DISPLAY, mWinFrame, mContentInsets, mStableInsets,
+ mOutsets, mDisplayCutout, mInputChannel) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index c211e2d..b740193 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -211,7 +211,8 @@
return mHyphenationFrequency;
}
- private boolean isSameTextMetricsInternal(@NonNull TextPaint paint,
+ /** @hide */
+ public boolean isSameTextMetricsInternal(@NonNull TextPaint paint,
@NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
@Layout.HyphenationFrequency int frequency) {
return mTextDir == textDir
@@ -247,6 +248,23 @@
mPaint.getFontVariationSettings(), mPaint.isElegantTextHeight(), mTextDir,
mBreakStrategy, mHyphenationFrequency);
}
+
+ @Override
+ public String toString() {
+ return "{"
+ + "textSize=" + mPaint.getTextSize()
+ + ", textScaleX=" + mPaint.getTextScaleX()
+ + ", textSkewX=" + mPaint.getTextSkewX()
+ + ", letterSpacing=" + mPaint.getLetterSpacing()
+ + ", textLocale=" + mPaint.getTextLocales()
+ + ", typeface=" + mPaint.getTypeface()
+ + ", variationSettings=" + mPaint.getFontVariationSettings()
+ + ", elegantTextHeight=" + mPaint.isElegantTextHeight()
+ + ", textDir=" + mTextDir
+ + ", breakStrategy=" + mBreakStrategy
+ + ", hyphenationFrequency=" + mHyphenationFrequency
+ + "}";
+ }
};
// The original text.
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 62222b5..533d725 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -213,7 +213,9 @@
byte[] verityRootHash = null;
if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
- verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+ byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+ verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength(
+ verityDigest, apk.length(), signatureInfo);
}
return new VerifiedSigner(
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 9436b29..4431bcef1 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -165,7 +165,7 @@
private static VerifiedSigner verify(
RandomAccessFile apk,
SignatureInfo signatureInfo,
- boolean doVerifyIntegrity) throws SecurityException {
+ boolean doVerifyIntegrity) throws SecurityException, IOException {
int signerCount = 0;
Map<Integer, byte[]> contentDigests = new ArrayMap<>();
VerifiedSigner result = null;
@@ -214,7 +214,9 @@
}
if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
- result.verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+ byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+ result.verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength(
+ verityDigest, apk.length(), signatureInfo);
}
return result;
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 40db758..1c67434 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -285,11 +285,46 @@
return result;
}
+ /**
+ * Return the verity digest only if the length of digest content looks correct.
+ * When verity digest is generated, the last incomplete 4k chunk is padded with 0s before
+ * hashing. This means two almost identical APKs with different number of 0 at the end will have
+ * the same verity digest. To avoid this problem, the length of the source content (excluding
+ * Signing Block) is appended to the verity digest, and the digest is returned only if the
+ * length is consistent to the current APK.
+ */
+ static byte[] parseVerityDigestAndVerifySourceLength(
+ byte[] data, long fileSize, SignatureInfo signatureInfo) throws SecurityException {
+ // FORMAT:
+ // OFFSET DATA TYPE DESCRIPTION
+ // * @+0 bytes uint8[32] Merkle tree root hash of SHA-256
+ // * @+32 bytes int64 Length of source data
+ int kRootHashSize = 32;
+ int kSourceLengthSize = 8;
+
+ if (data.length != kRootHashSize + kSourceLengthSize) {
+ throw new SecurityException("Verity digest size is wrong: " + data.length);
+ }
+ ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ buffer.position(kRootHashSize);
+ long expectedSourceLength = buffer.getLong();
+
+ long signingBlockSize = signatureInfo.centralDirOffset
+ - signatureInfo.apkSigningBlockOffset;
+ if (expectedSourceLength != fileSize - signingBlockSize) {
+ throw new SecurityException("APK content size did not verify");
+ }
+
+ return Arrays.copyOfRange(data, 0, kRootHashSize);
+ }
+
private static void verifyIntegrityForVerityBasedAlgorithm(
- byte[] expectedRootHash,
+ byte[] expectedDigest,
RandomAccessFile apk,
SignatureInfo signatureInfo) throws SecurityException {
try {
+ byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest,
+ apk.length(), signatureInfo);
ApkVerityBuilder.ApkVerityResult verity = ApkVerityBuilder.generateApkVerity(apk,
signatureInfo, new ByteBufferFactory() {
@Override
@@ -373,9 +408,9 @@
static final int SIGNATURE_ECDSA_WITH_SHA256 = 0x0201;
static final int SIGNATURE_ECDSA_WITH_SHA512 = 0x0202;
static final int SIGNATURE_DSA_WITH_SHA256 = 0x0301;
- static final int SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0411;
- static final int SIGNATURE_VERITY_ECDSA_WITH_SHA256 = 0x0413;
- static final int SIGNATURE_VERITY_DSA_WITH_SHA256 = 0x0415;
+ static final int SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0421;
+ static final int SIGNATURE_VERITY_ECDSA_WITH_SHA256 = 0x0423;
+ static final int SIGNATURE_VERITY_DSA_WITH_SHA256 = 0x0425;
static final int CONTENT_DIGEST_CHUNKED_SHA256 = 1;
static final int CONTENT_DIGEST_CHUNKED_SHA512 = 2;
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d7fd329..d8a5609 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -41,8 +41,8 @@
in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets,
out InputChannel outInputChannel);
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
- in int viewVisibility, in int layerStackId, out Rect outContentInsets,
- out Rect outStableInsets, out Rect outOutsets,
+ in int viewVisibility, in int layerStackId, out Rect outFrame,
+ out Rect outContentInsets, out Rect outStableInsets, out Rect outOutsets,
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel);
int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets);
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 137e820..7a10364 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -51,6 +51,7 @@
private View mHeaderText;
private View mSecondaryHeaderText;
private OnClickListener mExpandClickListener;
+ private OnClickListener mAppOpsListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private ImageView mExpandButton;
private CachingIconView mIcon;
@@ -267,15 +268,26 @@
}
private void updateTouchListener() {
- if (mExpandClickListener != null) {
- mTouchListener.bindTouchRects();
+ if (mExpandClickListener == null && mAppOpsListener == null) {
+ setOnTouchListener(null);
+ return;
}
+ setOnTouchListener(mTouchListener);
+ mTouchListener.bindTouchRects();
+ }
+
+ /**
+ * Sets onclick listener for app ops icons.
+ */
+ public void setAppOpsOnClickListener(OnClickListener l) {
+ mAppOpsListener = l;
+ mAppOps.setOnClickListener(mAppOpsListener);
+ updateTouchListener();
}
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
mExpandClickListener = l;
- setOnTouchListener(mExpandClickListener != null ? mTouchListener : null);
mExpandButton.setOnClickListener(mExpandClickListener);
updateTouchListener();
}
@@ -308,7 +320,7 @@
* Shows or hides 'app op in use' icons based on app usage.
*/
public void showAppOpsIcons(ArraySet<Integer> appOps) {
- if (mOverlayIcon == null || mCameraIcon == null || mMicIcon == null) {
+ if (mOverlayIcon == null || mCameraIcon == null || mMicIcon == null || appOps == null) {
return;
}
@@ -366,6 +378,7 @@
private final ArrayList<Rect> mTouchRects = new ArrayList<>();
private Rect mExpandButtonRect;
+ private Rect mAppOpsRect;
private int mTouchSlop;
private boolean mTrackGesture;
private float mDownX;
@@ -378,6 +391,7 @@
mTouchRects.clear();
addRectAroundView(mIcon);
mExpandButtonRect = addRectAroundView(mExpandButton);
+ mAppOpsRect = addRectAroundView(mAppOps);
addWidthRect();
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@@ -399,16 +413,18 @@
private Rect getRectAroundView(View view) {
float size = 48 * getResources().getDisplayMetrics().density;
+ float width = Math.max(size, view.getWidth());
+ float height = Math.max(size, view.getHeight());
final Rect r = new Rect();
if (view.getVisibility() == GONE) {
view = getFirstChildNotGone();
- r.left = (int) (view.getLeft() - size / 2.0f);
+ r.left = (int) (view.getLeft() - width / 2.0f);
} else {
- r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - size / 2.0f);
+ r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - width / 2.0f);
}
- r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - size / 2.0f);
- r.bottom = (int) (r.top + size);
- r.right = (int) (r.left + size);
+ r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - height / 2.0f);
+ r.bottom = (int) (r.top + height);
+ r.right = (int) (r.left + width);
return r;
}
@@ -436,6 +452,11 @@
break;
case MotionEvent.ACTION_UP:
if (mTrackGesture) {
+ if (mAppOps.isVisibleToUser() && (mAppOpsRect.contains((int) x, (int) y)
+ || mAppOpsRect.contains((int) mDownX, (int) mDownY))) {
+ mAppOps.performClick();
+ return true;
+ }
mExpandButton.performClick();
}
break;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index e996ea1..8d076f7 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -1068,11 +1068,15 @@
mInitialized = true;
mAppContext = context.getApplicationContext();
- nSetDebuggingEnabled(
- (mAppContext.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
- || Build.IS_DEBUGGABLE);
initSched(renderProxy);
- initGraphicsStats();
+
+ if (mAppContext != null) {
+ final boolean appDebuggable =
+ (mAppContext.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)
+ != 0;
+ nSetDebuggingEnabled(appDebuggable || Build.IS_DEBUGGABLE);
+ initGraphicsStats();
+ }
}
private void initSched(long renderProxy) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 03c3ded..bf0e2eb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7289,16 +7289,18 @@
}
/**
- * If this view is a visually distinct portion of a window, for example the content view of
- * a fragment that is replaced, it is considered a pane for accessibility purposes. In order
- * for accessibility services to understand the views role, and to announce its title as
- * appropriate, such views should have pane titles.
+ * Visually distinct portion of a window with window-like semantics are considered panes for
+ * accessibility purposes. One example is the content view of a fragment that is replaced.
+ * In order for accessibility services to understand a pane's window-like behavior, panes
+ * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
+ * when they appear, disappear, or change title.
*
- * @param accessibilityPaneTitle The pane's title.
+ * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
+ * View is not a pane.
*
* {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
*/
- public void setAccessibilityPaneTitle(CharSequence accessibilityPaneTitle) {
+ public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
mAccessibilityPaneTitle = accessibilityPaneTitle;
notifyViewAccessibilityStateChangedIfNeeded(
@@ -7313,7 +7315,7 @@
*
* {@see #setAccessibilityPaneTitle}.
*/
- public CharSequence getAccessibilityPaneTitle() {
+ @Nullable public CharSequence getAccessibilityPaneTitle() {
return mAccessibilityPaneTitle;
}
@@ -7978,6 +7980,10 @@
private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
if (provider != null) {
+ if (android.view.autofill.Helper.sVerbose && forAutofill) {
+ Log.v(VIEW_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
+ }
+
final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
structure.setChildCount(1);
final ViewStructure root = structure.newChild(0);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 95e4abb..d908e79 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -753,7 +753,7 @@
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
+ getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
} catch (RemoteException e) {
@@ -1711,8 +1711,8 @@
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
} else {
- desiredWindowWidth = dipToPx(config.screenWidthDp);
- desiredWindowHeight = dipToPx(config.screenHeightDp);
+ desiredWindowWidth = mWinFrame.width();
+ desiredWindowHeight = mWinFrame.height();
}
// We used to use the following condition to choose 32 bits drawing caches:
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5b1dd5c..fdd3f73 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3333,7 +3333,7 @@
final int actionCount = mActions.size();
int nonStandardActionCount = 0;
- int defaultStandardActions = 0;
+ long defaultStandardActions = 0;
for (int i = 0; i < actionCount; i++) {
AccessibilityAction action = mActions.get(i);
if (isDefaultStandardAction(action)) {
@@ -3342,7 +3342,7 @@
nonStandardActionCount++;
}
}
- parcel.writeInt(defaultStandardActions);
+ parcel.writeLong(defaultStandardActions);
parcel.writeInt(nonStandardActionCount);
for (int i = 0; i < actionCount; i++) {
@@ -3353,7 +3353,7 @@
}
}
} else {
- parcel.writeInt(0);
+ parcel.writeLong(0);
parcel.writeInt(0);
}
}
@@ -3540,7 +3540,7 @@
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
- final int standardActions = parcel.readInt();
+ final long standardActions = parcel.readLong();
addStandardActions(standardActions);
final int nonStandardActionCount = parcel.readInt();
for (int i = 0; i < nonStandardActionCount; i++) {
@@ -3621,7 +3621,7 @@
}
private static boolean isDefaultStandardAction(AccessibilityAction action) {
- return action.mSerializationFlag != -1 && TextUtils.isEmpty(action.getLabel());
+ return (action.mSerializationFlag != -1L) && TextUtils.isEmpty(action.getLabel());
}
private static AccessibilityAction getActionSingleton(int actionId) {
@@ -3636,7 +3636,7 @@
return null;
}
- private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) {
+ private static AccessibilityAction getActionSingletonBySerializationFlag(long flag) {
final int actions = AccessibilityAction.sStandardActions.size();
for (int i = 0; i < actions; i++) {
AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
@@ -3648,10 +3648,10 @@
return null;
}
- private void addStandardActions(int serializationIdMask) {
- int remainingIds = serializationIdMask;
+ private void addStandardActions(long serializationIdMask) {
+ long remainingIds = serializationIdMask;
while (remainingIds > 0) {
- final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
+ final long id = 1L << Long.numberOfTrailingZeros(remainingIds);
remainingIds &= ~id;
AccessibilityAction action = getActionSingletonBySerializationFlag(id);
addAction(action);
@@ -4276,7 +4276,7 @@
private final CharSequence mLabel;
/** @hide */
- public int mSerializationFlag = -1;
+ public long mSerializationFlag = -1L;
/**
* Creates a new AccessibilityAction. For adding a standard action without a specific label,
@@ -4310,7 +4310,7 @@
private AccessibilityAction(int standardActionId) {
this(standardActionId, null);
- mSerializationFlag = (int) bitAt(sStandardActions.size());
+ mSerializationFlag = bitAt(sStandardActions.size());
sStandardActions.add(this);
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 1e562ea..158c2ee0b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -986,6 +986,7 @@
* @param virtualId id identifying the virtual child inside the parent view.
*/
public void notifyViewExited(@NonNull View view, int virtualId) {
+ if (sVerbose) Log.v(TAG, "notifyViewExited(" + view.getAutofillId() + ", " + virtualId);
if (!hasAutofillFeature()) {
return;
}
@@ -2190,6 +2191,7 @@
public int getRelevantEventTypes(int relevantEventTypes) {
return relevantEventTypes | AccessibilityEvent.TYPE_VIEW_FOCUSED
| AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_CLICKED
| AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
}
@@ -2248,6 +2250,12 @@
}
} break;
+ case AccessibilityEvent.TYPE_VIEW_CLICKED: {
+ synchronized (mLock) {
+ notifyViewClicked(event.getWindowId(), event.getSourceNodeId());
+ }
+ } break;
+
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
final AutofillClient client = getClient();
if (client != null) {
@@ -2319,6 +2327,22 @@
AutofillValue.forText(node.getText()));
}
+ private void notifyViewClicked(int windowId, long nodeId) {
+ final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId(nodeId);
+ if (!isVirtualNode(virtualId)) {
+ return;
+ }
+ final View view = findViewByAccessibilityId(windowId, nodeId);
+ if (view == null) {
+ return;
+ }
+ final AccessibilityNodeInfo node = findVirtualNodeByAccessibilityId(view, virtualId);
+ if (node == null) {
+ return;
+ }
+ AutofillManager.this.notifyViewClicked(view, virtualId);
+ }
+
@GuardedBy("mLock")
private void updateTrackedViewsLocked() {
if (mTrackedViews != null) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 519a7dd..225497b 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1990,28 +1990,15 @@
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- // special case for the back key, we do not even try to send it
- // to the drop down list but instead, consume it immediately
- if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
- KeyEvent.DispatcherState state = getKeyDispatcherState();
- if (state != null) {
- state.startTracking(event, this);
- }
- return true;
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- KeyEvent.DispatcherState state = getKeyDispatcherState();
- if (state != null) {
- state.handleUpEvent(event);
- }
- if (event.isTracking() && !event.isCanceled()) {
- mSearchView.clearFocus();
- setImeVisibility(false);
- return true;
- }
- }
+ final boolean consume = super.onKeyPreIme(keyCode, event);
+ if (consume && keyCode == KeyEvent.KEYCODE_BACK
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ // If AutoCompleteTextView closed its pop-up, it will return true, in which case
+ // we should also close the IME. Otherwise, the popup is already closed and we can
+ // leave the BACK event alone.
+ setImeVisibility(false);
}
- return super.onKeyPreIme(keyCode, event);
+ return consume;
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6e40ea8..6fe64a0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4141,6 +4141,7 @@
*/
public void setTextMetricsParams(@NonNull PrecomputedText.Params params) {
mTextPaint.set(params.getTextPaint());
+ mUserSetTextScaleX = true;
mTextDir = params.getTextDirection();
mBreakStrategy = params.getBreakStrategy();
mHyphenationFrequency = params.getHyphenationFrequency();
@@ -5528,9 +5529,16 @@
* {@link android.text.Editable.Factory} to create final or intermediate
* {@link Editable Editables}.
*
+ * If the passed text is a {@link PrecomputedText} but the parameters used to create the
+ * PrecomputedText mismatches with this TextView, IllegalArgumentException is thrown. To ensure
+ * the parameters match, you can call {@link TextView#setTextMetricsParams} before calling this.
+ *
* @param text text to be displayed
*
* @attr ref android.R.styleable#TextView_text
+ * @throws IllegalArgumentException if the passed text is a {@link PrecomputedText} but the
+ * parameters used to create the PrecomputedText mismatches
+ * with this TextView.
*/
@android.view.RemotableViewMethod
public final void setText(CharSequence text) {
@@ -5644,7 +5652,21 @@
if (imm != null) imm.restartInput(this);
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
- } else if (!(text instanceof PrecomputedText || text instanceof CharWrapper)) {
+ } else if (text instanceof PrecomputedText) {
+ PrecomputedText precomputed = (PrecomputedText) text;
+ if (mTextDir == null) {
+ mTextDir = getTextDirectionHeuristic();
+ }
+ if (!precomputed.getParams().isSameTextMetricsInternal(
+ getPaint(), mTextDir, mBreakStrategy, mHyphenationFrequency)) {
+ throw new IllegalArgumentException(
+ "PrecomputedText's Parameters don't match the parameters of this TextView."
+ + "Consider using setTextMetricsParams(precomputedText.getParams()) "
+ + "to override the settings of this TextView: "
+ + "PrecomputedText: " + precomputed.getParams()
+ + "TextView: " + getTextMetricsParams());
+ }
+ } else if (!(text instanceof CharWrapper)) {
text = TextUtils.stringOrSpannedString(text);
}
@@ -8062,7 +8084,9 @@
return false;
}
- private void nullLayouts() {
+ /** @hide */
+ @VisibleForTesting
+ public void nullLayouts() {
if (mLayout instanceof BoringLayout && mSavedLayout == null) {
mSavedLayout = (BoringLayout) mLayout;
}
@@ -8156,7 +8180,8 @@
* not the full view width with padding.
* {@hide}
*/
- protected void makeNewLayout(int wantWidth, int hintWidth,
+ @VisibleForTesting
+ public void makeNewLayout(int wantWidth, int hintWidth,
BoringLayout.Metrics boring,
BoringLayout.Metrics hintBoring,
int ellipsisWidth, boolean bringIntoView) {
@@ -8446,7 +8471,9 @@
return mIncludePad;
}
- private static final BoringLayout.Metrics UNKNOWN_BORING = new BoringLayout.Metrics();
+ /** @hide */
+ @VisibleForTesting
+ public static final BoringLayout.Metrics UNKNOWN_BORING = new BoringLayout.Metrics();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
index ce45f3c..e790e08 100644
--- a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
@@ -123,6 +123,17 @@
}
}
+ public void readAbsolute(Callback cb) {
+ synchronized (mProcReader) {
+ readDelta(null);
+ int total = mLastUidCpuActiveTimeMs.size();
+ for (int i = 0; i < total; i ++){
+ int uid = mLastUidCpuActiveTimeMs.keyAt(i);
+ cb.onUidCpuActiveTime(uid, mLastUidCpuActiveTimeMs.get(uid).longValue());
+ }
+ }
+ }
+
public void removeUid(int uid) {
mLastUidCpuActiveTimeMs.delete(uid);
}
diff --git a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
index c21b766..bf5b520 100644
--- a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
@@ -65,6 +65,7 @@
private double[] mCurTime; // Reuse to avoid GC.
private long[] mDeltaTime; // Reuse to avoid GC.
+ private long[] mCurTimeRounded; // Reuse to avoid GC.
public interface Callback extends KernelUidCpuTimeReaderBase.Callback {
/**
@@ -137,6 +138,21 @@
}
}
+ public void readAbsolute(Callback cb) {
+ synchronized (mProcReader) {
+ readDelta(null);
+ int total = mLastUidPolicyTimeMs.size();
+ for (int i = 0; i < total; i ++){
+ int uid = mLastUidPolicyTimeMs.keyAt(i);
+ double[] lastTimes = mLastUidPolicyTimeMs.get(uid);
+ for (int j = 0; j < mNumClusters; j++) {
+ mCurTimeRounded[j] = (long) lastTimes[j];
+ }
+ cb.onUidCpuPolicyTime(uid, mCurTimeRounded);
+ }
+ }
+ }
+
private void processUid(IntBuffer buf, @Nullable Callback cb) {
int uid = buf.get();
double[] lastTimes = mLastUidPolicyTimeMs.get(uid);
@@ -189,6 +205,7 @@
mNumCoresOnCluster = numCoresOnCluster;
mCurTime = new double[numClusters];
mDeltaTime = new long[numClusters];
+ mCurTimeRounded = new long[numClusters];
return true;
}
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index a0787a0..f65074f 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -226,6 +226,17 @@
}
}
+ public void readAbsolute(Callback cb) {
+ synchronized (mProcReader) {
+ readDelta(null);
+ int total = mLastUidCpuFreqTimeMs.size();
+ for (int i = 0; i < total; i ++){
+ int uid = mLastUidCpuFreqTimeMs.keyAt(i);
+ cb.onUidCpuFreqTime(uid, mLastUidCpuFreqTimeMs.get(uid));
+ }
+ }
+ }
+
public void removeUid(int uid) {
mLastUidCpuFreqTimeMs.delete(uid);
}
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index 4263b83..97b7211 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -135,6 +135,30 @@
}
/**
+ * Reads the proc file, calling into the callback with raw absolute value of time for each UID.
+ * @param callback The callback to invoke for each line of the proc file.
+ */
+ public void readAbsolute(Callback callback) {
+ final int oldMask = StrictMode.allowThreadDiskReadsMask();
+ try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
+ TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
+ String line;
+ while ((line = reader.readLine()) != null) {
+ splitter.setString(line);
+ final String uidStr = splitter.next();
+ final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
+ final long userTimeUs = Long.parseLong(splitter.next(), 10);
+ final long systemTimeUs = Long.parseLong(splitter.next(), 10);
+ callback.onUidCpuTime(uid, userTimeUs, systemTimeUs);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
+ } finally {
+ StrictMode.setThreadPolicyMask(oldMask);
+ }
+ }
+
+ /**
* Removes the UID from the kernel module and from internal accounting data. Only
* {@link BatteryStatsImpl} and its child processes should call this, as the change on Kernel is
* visible system wide.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e871003..7eb2f38 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -42,6 +42,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;
+import android.util.SparseLongArray;
import com.android.internal.annotations.VisibleForTesting;
import com.google.android.collect.Lists;
@@ -120,8 +121,6 @@
@Deprecated
public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
- public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
- public final static String LOCKOUT_ATTEMPT_TIMEOUT_MS = "lockscreen.lockoutattempttimeoutmss";
public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
@Deprecated
@@ -164,6 +163,7 @@
private ILockSettings mLockSettingsService;
private UserManager mUserManager;
private final Handler mHandler;
+ private final SparseLongArray mLockoutDeadlines = new SparseLongArray();
/**
* Use {@link TrustManager#isTrustUsuallyManaged(int)}.
@@ -1237,8 +1237,7 @@
// enforces the deadline. Since we cannot store settings for the FRP user, don't.
return deadline;
}
- setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
- setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, timeoutMs, userId);
+ mLockoutDeadlines.put(userId, deadline);
return deadline;
}
@@ -1248,22 +1247,13 @@
* enter a pattern.
*/
public long getLockoutAttemptDeadline(int userId) {
- long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
- final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId);
+ final long deadline = mLockoutDeadlines.get(userId, 0L);
final long now = SystemClock.elapsedRealtime();
if (deadline < now && deadline != 0) {
// timeout expired
- setLong(LOCKOUT_ATTEMPT_DEADLINE, 0, userId);
- setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0, userId);
+ mLockoutDeadlines.put(userId, 0);
return 0L;
}
-
- if (deadline > (now + timeoutMs)) {
- // device was rebooted, set new deadline
- deadline = now + timeoutMs;
- setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
- }
-
return deadline;
}
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index d5cad02..d6496cd 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -213,6 +213,12 @@
drawable->markInvisible();
}
+static void AnimatedImageDrawable_nSetMirrored(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
+ jboolean mirrored) {
+ auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+ drawable->setStagingMirrored(mirrored);
+}
+
static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
{ "nCreate", "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate },
{ "nGetNativeFinalizer", "()J", (void*) AnimatedImageDrawable_nGetNativeFinalizer },
@@ -228,6 +234,7 @@
{ "nSetOnAnimationEndListener", "(JLandroid/graphics/drawable/AnimatedImageDrawable;)V", (void*) AnimatedImageDrawable_nSetOnAnimationEndListener },
{ "nNativeByteSize", "(J)J", (void*) AnimatedImageDrawable_nNativeByteSize },
{ "nMarkInvisible", "(J)V", (void*) AnimatedImageDrawable_nMarkInvisible },
+ { "nSetMirrored", "(JZ)V", (void*) AnimatedImageDrawable_nSetMirrored },
};
int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 12da273..da4cdb6 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -78,11 +78,11 @@
case ENCODING_AAC_ELD:
return AUDIO_FORMAT_AAC_ELD;
case ENCODING_AAC_XHE:
- return AUDIO_FORMAT_AAC; // FIXME temporary value, needs addition of xHE-AAC
+ return AUDIO_FORMAT_AAC_XHE;
case ENCODING_AC4:
return AUDIO_FORMAT_AC4;
- // case ENCODING_E_AC3_JOC: // FIXME Not defined on the native side yet
- // return AUDIO_FORMAT_E_AC3_JOC;
+ case ENCODING_E_AC3_JOC:
+ return AUDIO_FORMAT_E_AC3_JOC;
case ENCODING_DEFAULT:
return AUDIO_FORMAT_DEFAULT;
default:
@@ -133,8 +133,8 @@
// return ENCODING_AAC_XHE;
case AUDIO_FORMAT_AC4:
return ENCODING_AC4;
- // case AUDIO_FORMAT_E_AC3_JOC: // FIXME Not defined on the native side yet
- // return ENCODING_E_AC3_JOC;
+ case AUDIO_FORMAT_E_AC3_JOC:
+ return ENCODING_E_AC3_JOC;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/proto/android/os/backtrace.proto b/core/proto/android/os/backtrace.proto
new file mode 100644
index 0000000..ba81386
--- /dev/null
+++ b/core/proto/android/os/backtrace.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+package android.os;
+
+option java_multiple_files = true;
+
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+message BackTraceProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ message Stack {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional int32 pid = 1;
+ optional string dump = 2;
+ // Time it took to dump the stacktrace.
+ optional int64 dump_duration_ns = 3;
+ }
+ repeated Stack traces = 1;
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 7326829..bb9568b 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -17,6 +17,7 @@
syntax = "proto2";
option java_multiple_files = true;
+import "frameworks/base/core/proto/android/os/backtrace.proto";
import "frameworks/base/core/proto/android/os/batterytype.proto";
import "frameworks/base/core/proto/android/os/cpufreq.proto";
import "frameworks/base/core/proto/android/os/cpuinfo.proto";
@@ -115,6 +116,22 @@
(section).args = "LOG_ID_KERNEL"
];
+ // Stack dumps
+ optional android.os.BackTraceProto native_traces = 1200 [
+ (section).type = SECTION_TOMBSTONE,
+ (section).args = "native"
+ ];
+
+ optional android.os.BackTraceProto hal_traces = 1201 [
+ (section).type = SECTION_TOMBSTONE,
+ (section).args = "hal"
+ ];
+
+ optional android.os.BackTraceProto java_traces = 1202 [
+ (section).type = SECTION_TOMBSTONE,
+ (section).args = "java"
+ ];
+
// Linux services
optional ProcrankProto procrank = 2000 [
(section).type = SECTION_NONE, // disable procrank until figure out permission
diff --git a/core/res/res/color/control_nodisable_material.xml b/core/res/res/color/config_progress_background_tint.xml
similarity index 92%
rename from core/res/res/color/control_nodisable_material.xml
rename to core/res/res/color/config_progress_background_tint.xml
index 4a73e93..b086e20 100644
--- a/core/res/res/color/control_nodisable_material.xml
+++ b/core/res/res/color/config_progress_background_tint.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
diff --git a/core/res/res/drawable/progress_horizontal_material.xml b/core/res/res/drawable/progress_horizontal_material.xml
index 2f94d0c..d59abf4 100644
--- a/core/res/res/drawable/progress_horizontal_material.xml
+++ b/core/res/res/drawable/progress_horizontal_material.xml
@@ -18,7 +18,7 @@
<item android:id="@id/background"
android:gravity="center_vertical|fill_horizontal">
<shape android:shape="rectangle"
- android:tint="?attr/colorControlNormal">
+ android:tint="?attr/colorProgressBackgroundNormal">
<corners android:radius="?attr/progressBarCornerRadius" />
<size android:height="@dimen/progress_bar_height_material" />
<solid android:color="@color/white_disabled_material" />
diff --git a/core/res/res/drawable/seekbar_track_material.xml b/core/res/res/drawable/seekbar_track_material.xml
index 62ef136..2076fee 100644
--- a/core/res/res/drawable/seekbar_track_material.xml
+++ b/core/res/res/drawable/seekbar_track_material.xml
@@ -18,7 +18,7 @@
<item android:id="@id/background"
android:gravity="center_vertical|fill_horizontal">
<shape android:shape="rectangle"
- android:tint="@color/control_nodisable_material">
+ android:tint="?attr/colorProgressBackgroundNormal">
<corners android:radius="?attr/progressBarCornerRadius" />
<size android:height="@dimen/seekbar_track_background_height_material" />
<solid android:color="@color/white_disabled_material" />
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index c03cf51..3196d00 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -129,8 +129,9 @@
<LinearLayout
android:id="@+id/app_ops"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_width="wrap_content"
+ android:layout_marginStart="6dp"
android:orientation="horizontal" >
<ImageButton
android:id="@+id/camera"
@@ -139,7 +140,6 @@
android:src="@drawable/ic_camera"
android:tint="@color/notification_secondary_text_color_light"
android:background="?android:selectableItemBackgroundBorderless"
- android:layout_marginStart="6dp"
android:visibility="gone"
/>
<ImageButton
diff --git a/core/res/res/values-as-watch/strings.xml b/core/res/res/values-as-watch/strings.xml
new file mode 100644
index 0000000..1c91d10
--- /dev/null
+++ b/core/res/res/values-as-watch/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for android_upgrading_apk (1090732262010398759) -->
+ <skip />
+ <string name="permgrouplab_sensors" msgid="202675452368612754">"ছেন্সৰসমূহ"</string>
+</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
new file mode 100644
index 0000000..5ab2fa6
--- /dev/null
+++ b/core/res/res/values-as/strings.xml
@@ -0,0 +1,2006 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="byteShort" msgid="8340973892742019101">"বা."</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"কে. বি."</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"এম. বি."</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"জি. বি."</string>
+ <string name="terabyteShort" msgid="231613018159186962">"টি. বি."</string>
+ <string name="petabyteShort" msgid="5637816680144990219">"পি. বি."</string>
+ <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+ <string name="untitled" msgid="4638956954852782576">"<শিৰোনামবিহীন>"</string>
+ <string name="emptyPhoneNumber" msgid="7694063042079676517">"(কোনো ফ\'ন নম্বৰ নাই)"</string>
+ <string name="unknownName" msgid="6867811765370350269">"অজ্ঞাত"</string>
+ <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ভইচমেইল"</string>
+ <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
+ <string name="mmiError" msgid="5154499457739052907">"সংযোগৰ সমস্যা বা MMI ক\'ড মান্য নহয়।"</string>
+ <string name="mmiFdnError" msgid="5224398216385316471">"কেৱল ফিক্সড ডায়েলিং নম্বৰৰ বাবে কার্য সীমাবদ্ধ কৰা হৈছে।"</string>
+ <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"আপুনি ৰ\'মিঙত থকাৰ সময়ত কল ফৰৱাৰ্ডিঙৰ ছেটিংসমূহ সলনি কৰিব নোৱাৰি।"</string>
+ <string name="serviceEnabled" msgid="8147278346414714315">"সেৱা সক্ষম কৰা হ\'ল।"</string>
+ <string name="serviceEnabledFor" msgid="6856228140453471041">"সেৱা সক্ষম কৰা হ\'ল:"</string>
+ <string name="serviceDisabled" msgid="1937553226592516411">"সেৱা অক্ষম কৰা হ\'ল।"</string>
+ <string name="serviceRegistered" msgid="6275019082598102493">"পঞ্জীকৰণ সফল হ\'ল।"</string>
+ <string name="serviceErased" msgid="1288584695297200972">"সফলভাৱে মচা হ\'ল৷"</string>
+ <string name="passwordIncorrect" msgid="7612208839450128715">"ভুল পাছৱৰ্ড৷"</string>
+ <string name="mmiComplete" msgid="8232527495411698359">"MMI সম্পূৰ্ণ হ’ল।"</string>
+ <string name="badPin" msgid="9015277645546710014">"আপুনি লিখা পুৰণি পিনটো শুদ্ধ নহয়।"</string>
+ <string name="badPuk" msgid="5487257647081132201">"আপুনি লিখা PUKটো শুদ্ধ নহয়।"</string>
+ <string name="mismatchPin" msgid="609379054496863419">"আপুনি লিখা পিনবিলাক মিলা নাই।"</string>
+ <string name="invalidPin" msgid="3850018445187475377">"৪টাৰ পৰা ৮টা সংখ্যাযুক্ত এটা পিন লিখক।"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"৮টা সংখ্যা বা তাতকৈ বেছি সংখ্যাৰ এটা PUK লিখক।"</string>
+ <string name="needPuk" msgid="919668385956251611">"আপোনাৰ ছিমটো PUK ক\'ডেৰে লক কৰা আছে। PUK ক\'ড লিখি ইয়াক আনলক কৰক।"</string>
+ <string name="needPuk2" msgid="4526033371987193070">"ছিম কার্ড আনলক কৰিবলৈ PUK2 দিয়ক৷"</string>
+ <string name="enablePin" msgid="209412020907207950">"অসফল, ছিম/RUIM লক সক্ষম কৰক।"</string>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">ছিম লক হোৱাৰ পূৰ্বে আপোনাৰ <xliff:g id="NUMBER_1">%d</xliff:g>টা প্ৰয়াস বাকী আছে।</item>
+ <item quantity="other">ছিম লক হোৱাৰ পূৰ্বে আপোনাৰ <xliff:g id="NUMBER_1">%d</xliff:g>টা প্ৰয়াস বাকী আছে।</item>
+ </plurals>
+ <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+ <string name="meid" msgid="4841221237681254195">"MEID"</string>
+ <string name="ClipMmi" msgid="6952821216480289285">"অন্তৰ্গামী কলাৰ আইডি"</string>
+ <string name="ClirMmi" msgid="7784673673446833091">"বহিৰ্গামী কলাৰ আইডি"</string>
+ <string name="ColpMmi" msgid="3065121483740183974">"সংযোজিত লাইন আইডি"</string>
+ <string name="ColrMmi" msgid="4996540314421889589">"সংযোজিত লাইন আইডিৰ সীমাবদ্ধতা"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"কল ফৰৱাৰ্ডিং"</string>
+ <string name="CwMmi" msgid="9129678056795016867">"কল অপেক্ষাৰত"</string>
+ <string name="BaMmi" msgid="455193067926770581">"কল অৱৰোধ কৰা সুবিধা"</string>
+ <string name="PwdMmi" msgid="7043715687905254199">"পাছৱর্ড সলনি কৰা"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"পিন সলনি কৰা"</string>
+ <string name="CnipMmi" msgid="3110534680557857162">"বর্তমান কল কৰা নম্বৰ"</string>
+ <string name="CnirMmi" msgid="3062102121430548731">"বর্তমান কল কৰা নম্বৰ সীমিত কৰা হ\'ল"</string>
+ <string name="ThreeWCMmi" msgid="9051047170321190368">"ত্ৰিপক্ষীয় কলিং"</string>
+ <string name="RuacMmi" msgid="7827887459138308886">"আমনিদায়ক কল প্ৰত্যাখ্যান"</string>
+ <string name="CndMmi" msgid="3116446237081575808">"কল কৰা নম্বৰত ডেলিভাৰী"</string>
+ <string name="DndMmi" msgid="1265478932418334331">"অসুবিধা নিদিব"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"কলাৰ আইডি সীমিত কৰিবলৈ পূর্বনির্ধাৰণ কৰা হৈছে। পৰৱৰ্তী কল: সীমিত কৰা হৈছে"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"কলাৰ আইডি সীমিত কৰিবলৈ পূর্বনির্ধাৰণ কৰা হৈছে। পৰৱৰ্তী কল: সীমিত কৰা হৈছে"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"কলাৰ আইডি সীমিত নকৰিবলৈ পূর্বনির্ধাৰণ কৰা হৈছে। পৰৱৰ্তী কল: সীমিত কৰা হোৱা নাই"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"কলাৰ আইডি সীমিত নকৰিবলৈ পূর্বনির্ধাৰণ কৰা হৈছে। পৰৱৰ্তী কল: সীমিত কৰা হোৱা নাই"</string>
+ <string name="serviceNotProvisioned" msgid="8614830180508686666">"সুবিধা যোগান ধৰা হোৱা নাই।"</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"আপুনি কলাৰ আইডি ছেটিং সলনি কৰিব নোৱাৰে।"</string>
+ <string name="RestrictedOnDataTitle" msgid="1322504692764166532">"কোনো ডেটা সেৱা নাই"</string>
+ <string name="RestrictedOnEmergencyTitle" msgid="3646729271176394091">"জৰুৰীকালীন কল অৱৰোধিত কৰা হৈছে"</string>
+ <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"কোনো ভইচ সেৱা নাই"</string>
+ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"কোনো ভইচ/জৰুৰীকালীন সেৱা নাই"</string>
+ <string name="RestrictedStateContent" msgid="4278821484643362350">"আপোনাৰ এলেকাত সাময়িকভাৱে ম\'বাইল নেটৱৰ্কটোৱে যোগান ধৰা নাই"</string>
+ <string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"নেটৱর্ক পাব পৰা নাই"</string>
+ <string name="NetworkPreferenceSwitchSummary" msgid="7056776609127756440">"বেতাঁৰ সম্প্ৰচাৰ লাভৰ মান উন্নত কৰিবলৈ, ছেটিংসমূহ > নেটৱৰ্ক আৰু ইণ্টাৰনেট > ম\'বাইল নেটৱৰ্কসমূহ > পচন্দৰ নেটৱৰ্কৰ প্ৰকাৰ-লৈ গৈ বাছনি কৰি থোৱা নেটৱৰ্কৰ প্ৰকাৰটো সলনি কৰি চাওক।"</string>
+ <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"ৱাই-ফাই কলিং সক্ৰিয় হৈ আছে"</string>
+ <string name="EmergencyCallWarningSummary" msgid="8973232888021643293">"জৰুৰীকালীন কল কৰিবলৈ নেটৱৰ্কৰ প্ৰয়োজন।"</string>
+ <string name="notification_channel_network_alert" msgid="4427736684338074967">"সতৰ্কবাণীসমূহ"</string>
+ <string name="notification_channel_call_forward" msgid="2419697808481833249">"কল ফৰৱাৰ্ডিং"</string>
+ <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"জৰুৰীকালীন ক\'লবেক ম\'ড"</string>
+ <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"ম\'বাইল ডেটাৰ স্থিতি"</string>
+ <string name="notification_channel_sms" msgid="3441746047346135073">"এছএমএছ বার্তাবোৰ"</string>
+ <string name="notification_channel_voice_mail" msgid="3954099424160511919">"ভইচমেইলৰ বাৰ্তাসমূহ"</string>
+ <string name="notification_channel_wfc" msgid="2130802501654254801">"ৱাই-ফাই কলিং"</string>
+ <!-- no translation found for notification_channel_sim (4052095493875188564) -->
+ <skip />
+ <string name="peerTtyModeFull" msgid="6165351790010341421">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড FULLলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
+ <string name="peerTtyModeHco" msgid="5728602160669216784">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড HCOলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
+ <string name="peerTtyModeVco" msgid="1742404978686538049">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড VCO লৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
+ <string name="peerTtyModeOff" msgid="3280819717850602205">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড OFFলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
+ <string name="serviceClassVoice" msgid="1258393812335258019">"কণ্ঠস্বৰ"</string>
+ <string name="serviceClassData" msgid="872456782077937893">"ডেটা"</string>
+ <string name="serviceClassFAX" msgid="5566624998840486475">"ফেক্স"</string>
+ <string name="serviceClassSMS" msgid="2015460373701527489">"এছএমএছ"</string>
+ <string name="serviceClassDataAsync" msgid="4523454783498551468">"এছিংক"</string>
+ <string name="serviceClassDataSync" msgid="7530000519646054776">"ছিংক"</string>
+ <string name="serviceClassPacket" msgid="6991006557993423453">"পেকেট"</string>
+ <string name="serviceClassPAD" msgid="3235259085648271037">"পেড"</string>
+ <string name="roamingText0" msgid="7170335472198694945">"ৰ\'মিঙৰ সূচক অন হৈ আছে"</string>
+ <string name="roamingText1" msgid="5314861519752538922">"ৰ\'মিঙৰ সূচক অফ আছে"</string>
+ <string name="roamingText2" msgid="8969929049081268115">"ৰ\'মিঙৰ সূচক জিলিকি আছে"</string>
+ <string name="roamingText3" msgid="5148255027043943317">"চুবুৰিৰ বাহিৰত"</string>
+ <string name="roamingText4" msgid="8808456682550796530">"বিল্ডিঙৰ বাহিৰত"</string>
+ <string name="roamingText5" msgid="7604063252850354350">"ৰ\'মিং - পচন্দৰ ছিষ্টেম"</string>
+ <string name="roamingText6" msgid="2059440825782871513">"ৰ\'মিং- উপলব্ধ ছিষ্টেম"</string>
+ <string name="roamingText7" msgid="7112078724097233605">"ৰ\'মিং - মিত্ৰ-গোষ্ঠীৰ অংশীদাৰ"</string>
+ <string name="roamingText8" msgid="5989569778604089291">"ৰ\'মিং- প্ৰিমিয়াম অংশীদাৰ"</string>
+ <string name="roamingText9" msgid="7969296811355152491">"ৰ\'মিং - সেৱা সম্পূর্ণভাৱে কৰ্মক্ষম"</string>
+ <string name="roamingText10" msgid="3992906999815316417">"ৰ\'মিং - সেৱা আংশীকভাৱে কৰ্মক্ষম"</string>
+ <string name="roamingText11" msgid="4154476854426920970">"ৰ\'মিঙৰ বেনাৰ অন অৱস্থাত আছে"</string>
+ <string name="roamingText12" msgid="1189071119992726320">"ৰ\'মিঙৰ বেনাৰ অফ অৱস্থাত আছে"</string>
+ <string name="roamingTextSearching" msgid="8360141885972279963">"সেৱাৰ বাবে অনুসন্ধান কৰি থকা হৈছে"</string>
+ <!-- no translation found for wfcRegErrorTitle (2301376280632110664) -->
+ <skip />
+ <string-array name="wfcOperatorErrorAlertMessages">
+ <item msgid="3910386316304772394">"ৱাই-ফাইৰ জৰিয়তে কল কৰিবলৈ আৰু বাৰ্তা পঠাবলৈ, প্ৰথমে আপোনাৰ বাহকক আপোনাৰ ডিভাইচটো ছেট আপ কৰিব দিবলৈ কওক। তাৰ পিচত, ছেটিংসমূহলৈ গৈ আকৌ ৱাই-ফাই কলিং অন কৰক। (ত্ৰুটি ক\'ড: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ </string-array>
+ <string-array name="wfcOperatorErrorNotificationMessages">
+ <item msgid="7472393097168811593">"আপোনাৰ বাহকৰ ওচৰত পঞ্জীয়ন কৰক (ত্ৰুটি ক\'ড: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ </string-array>
+ <string-array name="wfcSpnFormats">
+ <item msgid="6830082633573257149">"%s"</item>
+ <item msgid="4397097370387921767">"%s ৱাই- ফাই কলিং"</item>
+ </string-array>
+ <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+ <skip />
+ <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+ <skip />
+ <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ম\'বাইলক অগ্ৰাধিকাৰ দিয়া হৈছে"</string>
+ <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+ <skip />
+ <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
+ <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
+ <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ছেকেণ্ডৰ পাছত"</string>
+ <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
+ <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
+ <string name="fcComplete" msgid="3118848230966886575">"সুবিধাৰ ক\'ড সম্পূর্ণ হ\'ল।"</string>
+ <string name="fcError" msgid="3327560126588500777">"সংযোগত সমস্যা হৈছে বা সুবিধাৰ ক\'ড অমান্য।"</string>
+ <string name="httpErrorOk" msgid="1191919378083472204">"ঠিক আছে"</string>
+ <string name="httpError" msgid="7956392511146698522">"ইণ্টাৰনেট সম্পর্কীয় আসোঁৱাহ হ\'ল৷"</string>
+ <string name="httpErrorLookup" msgid="4711687456111963163">"URL বিচাৰি পোৱা নগ\'ল।"</string>
+ <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"ছাইট সত্যাপন আঁচনিটো সমৰ্থিত নহয়৷"</string>
+ <string name="httpErrorAuth" msgid="1435065629438044534">"বিশ্বাসযোগ্যতাৰ প্ৰমাণ কৰিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorProxyAuth" msgid="1788207010559081331">"প্ৰ\'ক্সী ছার্ভাৰৰ জৰিয়তে বিশ্বাসযোগ্যতা প্ৰমাণ কৰিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorConnect" msgid="8714273236364640549">"ছার্ভাৰত সংযোগ কৰিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorIO" msgid="2340558197489302188">"ছার্ভাৰৰ সৈতে যোগাযোগ কৰিব পৰা নগ\'ল। আকৌ চেষ্টা কৰক।"</string>
+ <string name="httpErrorTimeout" msgid="4743403703762883954">"ছার্ভাৰৰ লগত সংযোগৰ চেষ্টাৰ সময়সীমা উকলিল৷"</string>
+ <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"এই পৃষ্টাটোত অত্যধিক ছাৰ্ভাৰ ৰিডাইৰেক্ট আছে।"</string>
+ <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"ছাৰ্ভাৰৰ প্ৰ\'ট\'কল সমৰ্থিত নহয়৷"</string>
+ <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"এটা সুৰক্ষিত সংযোগ স্থাপন কৰিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorBadUrl" msgid="3636929722728881972">"অমান্য URLৰ বাবে পৃষ্ঠাটো খুলিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorFile" msgid="2170788515052558676">"ফাইলত খুলিব পৰা নগ\'ল।"</string>
+ <string name="httpErrorFileNotFound" msgid="6203856612042655084">"অনুৰোধ কৰা ফাইলটো বিচাৰি পোৱা নগ\'ল।"</string>
+ <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"বহুত বেছি অনুৰোধৰ প্ৰক্ৰিয়া চলি আছে৷ অনুগ্ৰহ কৰি পিছত আকৌ চেষ্টা কৰক৷"</string>
+ <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g>ত ছাইন ইন কৰাত আসোঁৱাহ"</string>
+ <string name="contentServiceSync" msgid="8353523060269335667">"ছিংক ত্ৰুটি"</string>
+ <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ছিংক ত্ৰুটি"</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"বহুতো <xliff:g id="CONTENT_TYPE">%s</xliff:g> একেলগে মচা হৈছে।"</string>
+ <string name="low_memory" product="tablet" msgid="6494019234102154896">"টেবলেটৰ সঞ্চয়াগাৰত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ঘড়ীৰ সঞ্চয়াগাৰ ভৰি পৰিছে। খালী স্থান উলিয়াবলৈ কিছুমান ফাইল মচক।"</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"টিভিৰ সঞ্চয়াগাৰ ভৰি পৰিছে। খালী ঠাই উলিয়াবলৈ কিছুমান ফাইল মচক।"</string>
+ <string name="low_memory" product="default" msgid="3475999286680000541">"ফ\'নৰ সঞ্চয়াগাৰত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
+ <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
+ <item quantity="one">প্ৰমাণপত্ৰ প্ৰদানকাৰী কৰ্তৃপক্ষ ইনষ্টল কৰা হ\'ল</item>
+ <item quantity="other">প্ৰমাণপত্ৰ প্ৰদানকাৰী কৰ্তৃপক্ষ ইনষ্টল কৰা হ\'ল</item>
+ </plurals>
+ <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"এটা অজ্ঞাত তৃতীয় পক্ষৰদ্বাৰা"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলৰ প্ৰশাসকে পৰ্যবেক্ষণ কৰি আছে"</string>
+ <string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g>ৰ দ্বাৰা"</string>
+ <string name="work_profile_deleted" msgid="5005572078641980632">"কৰ্মস্থানৰ প্ৰ\'ফাইল মচা হ\'ল"</string>
+ <string name="work_profile_deleted_description" msgid="1100529432509639864">"প্ৰশাসক এপ্ নথকাৰ বাবে কৰ্মস্থানৰ প্ৰ\'ফাইল মচা হ\'ল"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ প্ৰশাসক এপ্ নাই বা ব্যৱহাৰযোগ্য হৈ থকা নাই। যাৰ ফলত আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইল আৰু ইয়াৰ লগত জড়িত অন্য ডেটাসমূহ মচা হৈছে। সহায়ৰ বাবে আপোনাৰ প্ৰশাসকৰ সৈতে সম্পর্ক কৰক।"</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইল এই ডিভাইচটোত আৰু উপলব্ধ নহয়"</string>
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"বহুতবাৰ ভুলকৈ পাছৱৰ্ড দিয়া হৈছে"</string>
+ <string name="network_logging_notification_title" msgid="6399790108123704477">"পৰিচালিত ডিভাইচ"</string>
+ <string name="network_logging_notification_text" msgid="7930089249949354026">"আপোনাৰ প্ৰতিষ্ঠানটোৱে এই ডিভাইচটো পৰিচালনা কৰে আৰু ই নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ কৰিব পাৰে। সবিশেষ জানিবলৈ টিপক।"</string>
+ <string name="factory_reset_warning" msgid="5423253125642394387">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
+ <!-- no translation found for factory_reset_message (9024647691106150160) -->
+ <skip />
+ <!-- no translation found for printing_disabled_by (8936832919072486965) -->
+ <skip />
+ <string name="me" msgid="6545696007631404292">"মই"</string>
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"টে\'বলেটৰ বিকল্পসমূহ"</string>
+ <string name="power_dialog" product="tv" msgid="6153888706430556356">"টিভিৰ বিকল্পসমূহ"</string>
+ <string name="power_dialog" product="default" msgid="1319919075463988638">"ফ\'নৰ বিকল্পসমূহ"</string>
+ <string name="silent_mode" msgid="7167703389802618663">"নিঃশব্দ ম\'ড"</string>
+ <string name="turn_on_radio" msgid="3912793092339962371">"ৱায়াৰলেছ অন কৰক"</string>
+ <string name="turn_off_radio" msgid="8198784949987062346">"ৱায়াৰলেছ অফ কৰক"</string>
+ <string name="screen_lock" msgid="799094655496098153">"স্ক্ৰীণ লক"</string>
+ <string name="power_off" msgid="4266614107412865048">"পাৱাৰ অফ"</string>
+ <string name="silent_mode_silent" msgid="319298163018473078">"ৰিংগাৰ অফ আছে"</string>
+ <string name="silent_mode_vibrate" msgid="7072043388581551395">"ৰিংগাৰ কম্পন অৱস্থাত আছে"</string>
+ <string name="silent_mode_ring" msgid="8592241816194074353">"ৰিংগাৰ অন আছে"</string>
+ <string name="reboot_to_update_title" msgid="6212636802536823850">"Android ছিষ্টেমৰ আপডেট"</string>
+ <string name="reboot_to_update_prepare" msgid="6305853831955310890">"আপডেট সাজু কৰি থকা হৈছে…"</string>
+ <string name="reboot_to_update_package" msgid="3871302324500927291">"পেকেজ আপডেট কৰা প্ৰক্ৰিয়া চলি আছে…"</string>
+ <string name="reboot_to_update_reboot" msgid="6428441000951565185">"ৰিষ্টাৰ্ট কৰা হৈছে…"</string>
+ <string name="reboot_to_reset_title" msgid="4142355915340627490">"ফেক্টৰী ডেটা ৰিছেট কৰক"</string>
+ <!-- no translation found for reboot_to_reset_message (2432077491101416345) -->
+ <skip />
+ <string name="shutdown_progress" msgid="2281079257329981203">"বন্ধ কৰি থকা হৈছে…"</string>
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"আপোনাৰ টে\'বলেটটো বন্ধ হ\'ব।"</string>
+ <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"আপোনাৰ টিভি বন্ধ কৰা হ\'ব৷"</string>
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"আপোনাৰ ঘড়ী বন্ধ কৰা হ\'ব।"</string>
+ <string name="shutdown_confirm" product="default" msgid="649792175242821353">"আপোনাৰ ফ\'নটো বন্ধ হ\'ব।"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"আপুনি ফ\'নটোৰ পাৱাৰ অফ কৰিব বিচাৰেনে?"</string>
+ <string name="reboot_safemode_title" msgid="7054509914500140361">"সুৰক্ষিত ম\'ডলৈ ৰিবুট কৰক"</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"আপুনি সুৰক্ষিত ম\'ডলৈ ৰিবুট কৰিব বিচাৰেনে? এই কার্যই আপুনি ইনষ্টল কৰা তৃতীয় পক্ষৰ সকলো এপ্লিকেশ্বন অক্ষম কৰিব। আপুনি পুনৰ ৰিবুট কৰিলে সেইবোৰ পুনঃস্থাপন কৰা হ\'ব।"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"শেহতীয়া"</string>
+ <string name="no_recent_tasks" msgid="8794906658732193473">"কোনো শেহতীয়া এপ্ নাই।"</string>
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"টে\'বলেটৰ বিকল্পসমূহ"</string>
+ <string name="global_actions" product="tv" msgid="7240386462508182976">"টিভিৰ বিকল্পসমূহ"</string>
+ <string name="global_actions" product="default" msgid="2406416831541615258">"ফ\'নৰ বিকল্পসমূহ"</string>
+ <string name="global_action_lock" msgid="2844945191792119712">"স্ক্ৰীণ ল\'ক"</string>
+ <string name="global_action_power_off" msgid="4471879440839879722">"পাৱাৰ অফ"</string>
+ <string name="global_action_emergency" msgid="7112311161137421166">"জৰুৰীকালীন কল"</string>
+ <string name="global_action_bug_report" msgid="7934010578922304799">"বাগ সম্পর্কীয় অভিযোগ"</string>
+ <string name="global_action_logout" msgid="935179188218826050">"ছেশ্বন সমাপ্ত কৰক"</string>
+ <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+ <skip />
+ <string name="bugreport_title" msgid="2667494803742548533">"বাগ সম্পর্কীয় অভিযোগ লওক"</string>
+ <string name="bugreport_message" msgid="398447048750350456">"এই কার্যই ইমেইল বাৰ্তা হিচাপে পঠিয়াবলৈ আপোনাৰ ডিভাইচৰ বৰ্তমান অৱস্থাৰ বিষয়ে তথ্য সংগ্ৰহ কৰিব৷ ইয়াক বাগ সম্পর্কীয় অভিযোগ পঠিওৱা কাৰ্য আৰম্ভ কৰোঁতে অলপ সময় লাগিব; অনুগ্ৰহ কৰি ধৈৰ্য ধৰক।"</string>
+ <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ইণ্টাৰেক্টিভ অভিযোগ"</string>
+ <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"বেছিভাগ পৰিস্থিতিত এয়া ব্যৱহাৰ কৰক। ই আপোনাক অভিযোগৰ অগ্ৰগতি ট্ৰেক কৰিবলৈ, সমস্যাটোৰ সম্পর্কে অধিক বিৱৰণ দিবলৈ আৰু স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি দিয়ে। ই কম ব্যৱহাৰ হোৱা সেই শাখাসমূহক অন্তৰ্ভুক্ত নকৰিব পাৰে যিবোৰক অভিযোগ কৰিবলৈ দীৰ্ঘ সময়ৰ প্ৰয়োজন হয়।"</string>
+ <string name="bugreport_option_full_title" msgid="6354382025840076439">"সম্পূৰ্ণ অভিযোগ"</string>
+ <string name="bugreport_option_full_summary" msgid="7210859858969115745">"যেতিয়া আপোনাৰ ডিভাইচটোৱে সঁহাৰি নিদিয়া হয় বা ই অতি লেহেমীয়া হৈ পৰে বা যেতিয়া আপোনাক সকলো অভিযোগৰ শাখাৰ প্ৰয়োজন হয় তেতিয়া ছিষ্টেমত কম হস্তক্ষেপৰ বাবে এই বিকল্প ব্যৱহাৰ কৰক। আপোনাক অধিক বিৱৰণ দিবলৈ বা অতিৰিক্ত স্ক্ৰীণশ্বট ল’বলৈ নিদিয়ে।"</string>
+ <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
+ <item quantity="one">ত্ৰুটি সম্পর্কীয় অভিযোগৰ বাবে <xliff:g id="NUMBER_1">%d</xliff:g>ছেকেণ্ডৰ ভিতৰত স্ক্ৰীণশ্বট লোৱা হ\'ব।</item>
+ <item quantity="other">ত্ৰুটি সম্পর্কীয় অভিযোগৰ বাবে <xliff:g id="NUMBER_1">%d</xliff:g>ছেকেণ্ডৰ ভিতৰত স্ক্ৰীণশ্বট লোৱা হ\'ব।</item>
+ </plurals>
+ <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"নিঃশব্দ ম\'ড"</string>
+ <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ধ্বনি অফ আছে"</string>
+ <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"ধ্বনি অন আছে"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"এয়াৰপ্লেইন ম\'ড"</string>
+ <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"এয়াৰপ্লেইন ম\'ড অন কৰা আছে"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"এয়াৰপ্লেইন ম\'ড অফ কৰা আছে"</string>
+ <!-- no translation found for global_action_toggle_battery_saver (708515500418994208) -->
+ <skip />
+ <!-- no translation found for global_action_battery_saver_on_status (484059130698197787) -->
+ <skip />
+ <!-- no translation found for global_action_battery_saver_off_status (75550964969478405) -->
+ <skip />
+ <string name="global_action_settings" msgid="1756531602592545966">"ছেটিংসমূহ"</string>
+ <!-- no translation found for global_action_assist (3892832961594295030) -->
+ <skip />
+ <!-- no translation found for global_action_voice_assist (7751191495200504480) -->
+ <skip />
+ <!-- no translation found for global_action_lockdown (1099326950891078929) -->
+ <skip />
+ <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"৯৯৯+"</string>
+ <string name="notification_hidden_text" msgid="6351207030447943784">"নতুন জাননী"</string>
+ <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"ভাৰ্শ্বুৱল কীব\'ৰ্ড"</string>
+ <string name="notification_channel_physical_keyboard" msgid="7297661826966861459">"কায়িক কীব’ৰ্ড"</string>
+ <string name="notification_channel_security" msgid="7345516133431326347">"সুৰক্ষা"</string>
+ <string name="notification_channel_car_mode" msgid="3553380307619874564">"গাড়ী ম\'ড"</string>
+ <string name="notification_channel_account" msgid="7577959168463122027">"একাউণ্টৰ স্থিতি"</string>
+ <string name="notification_channel_developer" msgid="7579606426860206060">"বিকাশকৰ্তাৰ বাৰ্তাসমূহ"</string>
+ <string name="notification_channel_updates" msgid="4794517569035110397">"আপডেটবোৰ"</string>
+ <string name="notification_channel_network_status" msgid="5025648583129035447">"নেটৱৰ্কৰ স্থিতি"</string>
+ <string name="notification_channel_network_alerts" msgid="2895141221414156525">"নেটৱৰ্ক সম্পৰ্কীয় সতৰ্কবাণী"</string>
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"নেটৱৰ্ক উপলব্ধ"</string>
+ <string name="notification_channel_vpn" msgid="8330103431055860618">"ভিপিএনৰ স্থিতি"</string>
+ <string name="notification_channel_device_admin" msgid="1568154104368069249">"ডিভাইচৰ প্ৰশাসন"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"সতৰ্কবাণীসমূহ"</string>
+ <string name="notification_channel_retail_mode" msgid="6088920674914038779">"খুচুৰা ডেম\'"</string>
+ <string name="notification_channel_usb" msgid="9006850475328924681">"ইউএছবি সংযোগ"</string>
+ <string name="notification_channel_heavy_weight_app" msgid="6218742927792852607">"এপ্ চলি আছে"</string>
+ <string name="notification_channel_foreground_service" msgid="3931987440602669158">"বেটাৰি খৰচ কৰা এপসমূহ"</string>
+ <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
+ <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
+ <string name="foreground_service_tap_for_details" msgid="372046743534354644">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
+ <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
+ <string name="safeMode" msgid="2788228061547930246">"সুৰক্ষিত ম\'ড"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android ছিষ্টেম"</string>
+ <!-- no translation found for user_owner_label (8836124313744349203) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (8947929265267690522) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contacts (3657758145679177612) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_contacts (6951499528303668046) -->
+ <skip />
+ <string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক আপোনাৰ সম্পৰ্কসূচী চাবলৈ অনুমতি দিয়ক"</string>
+ <!-- no translation found for permgrouplab_location (7275582855722310164) -->
+ <skip />
+ <string name="permgroupdesc_location" msgid="1346617465127855033">"এই ডিভাইচৰ অৱস্থান ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permgrouprequest_location" msgid="8903573681261610809">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক ডিভাইচৰ অৱস্থান জানিবলৈ অনুমতি দিয়ক"</string>
+ <string name="permgrouplab_calendar" msgid="5863508437783683902">"কেলেণ্ডাৰ"</string>
+ <!-- no translation found for permgroupdesc_calendar (3889615280211184106) -->
+ <skip />
+ <string name="permgrouprequest_calendar" msgid="6704529828699071445">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক আপোনাৰ কেলেণ্ডাৰ চাবলৈ অনুমতি দিয়ক"</string>
+ <!-- no translation found for permgrouplab_sms (228308803364967808) -->
+ <skip />
+ <string name="permgroupdesc_sms" msgid="4656988620100940350">"এছএমএছ বার্তা পঠিয়াব আৰু চাব পাৰে"</string>
+ <string name="permgrouprequest_sms" msgid="605618939583628306">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক এছএমএছ বাৰ্তা পঠিয়াবলৈ আৰু চাবলৈ অনুমতি দিয়ক"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"সঞ্চয়াগাৰ"</string>
+ <string name="permgroupdesc_storage" msgid="637758554581589203">"আপোনাৰ ডিভাইচৰ ফট\', মিডিয়া আৰু ফাইলসমূহ ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permgrouprequest_storage" msgid="7429669910547860218">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক আপোনাৰ ডিভাইচত থকা ফট\', মিডিয়া আৰু ফাইল চাবলৈ অনুমতি দিয়ক"</string>
+ <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্ৰ\'ফ\'ন"</string>
+ <!-- no translation found for permgroupdesc_microphone (4988812113943554584) -->
+ <skip />
+ <string name="permgrouprequest_microphone" msgid="8065941268709600606">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক অডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিয়ক"</string>
+ <string name="permgrouplab_camera" msgid="4820372495894586615">"কেমেৰা"</string>
+ <!-- no translation found for permgroupdesc_camera (3250611594678347720) -->
+ <skip />
+ <string name="permgrouprequest_camera" msgid="810824326507258410">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক ছবি তুলিবলৈ আৰু ভিডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিয়ক"</string>
+ <!-- no translation found for permgrouplab_phone (5229115638567440675) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_phone (6234224354060641055) -->
+ <skip />
+ <string name="permgrouprequest_phone" msgid="7084161459732093690">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক ফ\'ন কল কৰিবলৈ আৰু পৰিচালনা কৰিবলৈ অনুমতি দিয়ক"</string>
+ <string name="permgrouplab_sensors" msgid="416037179223226722">"শৰীৰৰ ছেন্সৰসমূহ"</string>
+ <string name="permgroupdesc_sensors" msgid="7147968539346634043">"আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিব পাৰে"</string>
+ <string name="permgrouprequest_sensors" msgid="8631146669524259656">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ক আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিবলৈ অনুমতি দিয়ক"</string>
+ <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ৱিণ্ড\' সমল বিচাৰি উলিয়াওক"</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"আপুনি যোগাযোগ কৰি থকা ৱিণ্ড\'খনৰ সমল পৰীক্ষা কৰক।"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"স্পৰ্শৰদ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰক"</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"টেপ কৰা বস্তুসমূহ ডাঙৰকৈ কোৱা হ\'ব আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ দি স্ক্ৰীণ অন্বেষণ কৰিব পাৰিব।"</string>
+ <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"আপুনি লিখা পাঠ নিৰীক্ষণ কৰক"</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ক্ৰেডিট কাৰ্ডৰ নম্বৰ আৰু পাছৱৰ্ডৰ দৰে ব্যক্তিগত ডেটা অন্তৰ্ভুক্ত হ\'ব পাৰে।"</string>
+ <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ডিছপ্লেৰ বিবৰ্ধন নিয়ন্ত্ৰণ কৰক"</string>
+ <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ডিছপ্লেৰ জুমৰ স্তৰ আৰু অৱস্থান নিয়ন্ত্ৰণ কৰক।"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ কৰা কার্যসমূহ কৰক"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"টেপ কৰা, ছোৱাইপ কৰা, পিঞ্চ কৰা আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ কৰা অন্যান্য কাৰ্যসমূহ কৰিব পাৰে।"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ফিংগাৰপ্ৰিণ্ট নিৰ্দেশসমূহ"</string>
+ <!-- no translation found for capability_desc_canCaptureFingerprintGestures (4386487962402228670) -->
+ <skip />
+ <string name="permlab_statusBar" msgid="7417192629601890791">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
+ <string name="permdesc_statusBar" msgid="8434669549504290975">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_statusBarService" msgid="4826835508226139688">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
+ <string name="permdesc_statusBarService" msgid="716113660795976060">"নিজকে স্থিতি দণ্ডৰূপে দেখুওৱাবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_expandStatusBar" msgid="1148198785937489264">"স্থিতি দণ্ড সম্প্ৰসাৰিত বা সংকোচিত কৰক"</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"স্থিতি দণ্ড বিস্তাৰিত বা সংকুচিত কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_install_shortcut" msgid="4279070216371564234">"শ্বৰ্টকাট ইনষ্টল কৰিব পাৰে"</string>
+ <string name="permdesc_install_shortcut" msgid="8341295916286736996">"এটা এপ্লিকেশ্বনক ব্যৱহাৰকাৰীৰ হস্তক্ষেপৰ অবিহনে গৃহ স্ক্ৰীণ শ্বৰ্টকাট যোগ কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"শ্বৰ্টকাট আনইনষ্টল কৰিব পাৰে"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ব্যৱহাৰকাৰীৰ হস্তক্ষেপৰ অবিহনে গৃহ স্ক্ৰীণৰ শ্বৰ্টকাটসমূহ আঁতৰাবলৈ এপ্লিকেশ্বনক অনুমতি দিয়ে।"</string>
+ <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"বহিৰ্গামী কলসমূহ অন্য ক\'ৰবালৈ পঠিয়াওক"</string>
+ <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"এটা বৰ্হিগামী কল কৰি থকাৰ সময়ত ডায়েল কৰা নম্বৰ চাবলৈ আৰু লগতে এটা পৃথক নম্বৰলৈ কল সংযোগ কৰিবলৈ বা সকলোকে একেলগে বন্ধ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"ফ\'ন কলৰ উত্তৰ দিব পাৰে"</string>
+ <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"এপটোক অন্তৰ্গামী ফ\'ন কলৰ উত্তৰ দিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_receiveSms" msgid="8673471768947895082">"পাঠ বার্তা (এছএমএছ) বোৰ লাভ কৰক"</string>
+ <string name="permdesc_receiveSms" msgid="6424387754228766939">"এপটোক এছএমএছ বাৰ্তাবোৰ পাবলৈ আৰু প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ অনুমতি দিয়ে৷ ইয়াৰ অৰ্থ এইটোৱেই যে এপটোৱে আপোনাক বাৰ্তাবোৰ নেদেখুৱাকৈয়ে আপোনাৰ ডিভাইচলৈ পঠিওৱা বাৰ্তাবোৰ নিৰীক্ষণ কৰিব বা মচিব পাৰে৷"</string>
+ <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ বার্তা (এমএমএছ) বোৰ লাভ কৰক"</string>
+ <string name="permdesc_receiveMms" msgid="533019437263212260">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
+ <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"বৰ্তমান ছিংক কৰা ফীডৰ সবিশেষ লাভ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <!-- no translation found for permlab_sendSms (7544599214260982981) -->
+ <skip />
+ <string name="permdesc_sendSms" msgid="7094729298204937667">"এপটোক এছএমএছ বাৰ্তা পঠিয়াবলৈ অনুমতি দিয়ে৷ ইয়াৰ ফলত অপ্ৰত্যাশিত মাচুল ভৰিবলগা হ\'ব পাৰে৷ ক্ষতিকাৰক এপসমূহে আপোনাৰ অনুমতি নোলোৱাকৈয়ে বাৰ্তা পঠিয়াই আপোনাৰ পৰা মাচুল কাটিব পাৰে৷"</string>
+ <string name="permlab_readSms" msgid="8745086572213270480">"আপোনাৰ পাঠ বার্তাবোৰ পঢ়ক (এছএমএছ বা এমএমএছ)"</string>
+ <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"এই এপটোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"এই এপটোৱে আপোনাৰ টিভিটোত সংৰক্ষিত সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"এই এপটোৱে আপোনাৰ ফ\'নত সংৰক্ষিত সকলো এছএমএছ (পাঠ) বাৰ্তা পঢ়িব পাৰে।"</string>
+ <string name="permlab_receiveWapPush" msgid="5991398711936590410">"পাঠ বার্তা (WAP) বোৰ লাভ কৰক"</string>
+ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"এপটোক WAP বাৰ্তাবোৰ পাবলৈ আৰু প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ অনুমতি দিয়ে৷ এই অনুমতিত আপোনালৈ পঠিওৱা বাৰ্তাবোৰ আপোনাক নেদেখুৱাকৈয়ে নিৰীক্ষণ বা মচাৰ সক্ষমতা অন্তৰ্ভুক্ত থাকে৷"</string>
+ <string name="permlab_getTasks" msgid="6466095396623933906">"চলি থকা এপসমূহ বিচাৰি উলিয়াওক"</string>
+ <string name="permdesc_getTasks" msgid="7454215995847658102">"এপটোক বৰ্তমানে আৰু শেহতীয়াভাৱে চলি থকা কাৰ্যসমূহৰ বিষয়ে তথ্য পুনৰুদ্ধাৰ কৰিবলৈ অনুমতি দিয়ে৷ এইটোৱে এপটোক ডিভাইচটোত কোনবোৰ এপ্লিকেশ্বন ব্যৱহাৰ হৈ আছে তাৰ বিষয়ে তথ্য বিচাৰি উলিয়াবলৈ অনুমতি দিব পাৰে৷"</string>
+ <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"প্ৰ\'ফাইল আৰু ডিভাইচৰ গৰাকীসকলক পৰিচালনা কৰিব পাৰে"</string>
+ <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) -->
+ <skip />
+ <string name="permlab_reorderTasks" msgid="2018575526934422779">"চলি থকা এপসমূহক পুনৰাই ক্ৰমবদ্ধ কৰক"</string>
+ <string name="permdesc_reorderTasks" msgid="7734217754877439351">"গতিবিধিক অগ্ৰভাগ আৰু নেপথ্যলৈ নিবলৈ এপক অনুমতি দিয়ে। এপে এই কার্য আপোনাৰ ইনপুট অবিহনেই কৰিব পাৰে।"</string>
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"গাড়ীৰ ম\'ড সক্ষম কৰক"</string>
+ <string name="permdesc_enableCarMode" msgid="4853187425751419467">"গাড়ী ম\'ড সক্ষম কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"অন্য এপবোৰ বন্ধ কৰক"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"এপটোক অন্য এপসমূহৰ নেপথ্যৰ প্ৰক্ৰিয়াসমূহ শেষ কৰিবলৈ অনুমতি দিয়ে৷ এই কার্যৰ বাবে অন্য এপসমূহ চলাটো বন্ধ হ\'ব পাৰে৷"</string>
+ <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"এই এপটো অইন এপৰ ওপৰত প্ৰদৰ্শিত হ\'ব পাৰে"</string>
+ <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"এই এপটো অইন এপৰ ওপৰত বা স্ক্ৰীণৰ অইন অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপসমূহৰ স্বাভাৱিক কাৰ্যকলাপত ব্যাঘাত জন্মাব পাৰে আৰু অইন এপসমূহক স্ক্ৰীণত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string>
+ <string name="permlab_runInBackground" msgid="7365290743781858803">"নেপথ্যত চলিব পাৰে"</string>
+ <string name="permdesc_runInBackground" msgid="7370142232209999824">"এই এপটো নেপথ্যত চলিব পাৰে। ইয়াৰ ফলত বেটাৰি সোনকালে শেষ হ\'ব পাৰে।"</string>
+ <string name="permlab_useDataInBackground" msgid="8694951340794341809">"নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"এই এপটোৱে নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে। ইয়াৰ ফলত ডেটা বেছি খৰছ হ\'ব পাৰে।"</string>
+ <string name="permlab_persistentActivity" msgid="8841113627955563938">"এপক সদায়ে চলি থকা কৰক"</string>
+ <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"মেম\'ৰিত নিজৰ বাবে প্ৰয়োজনীয় ঠাই পৃথক কৰিবলৈ এপক অনুমতি দিয়ে। এই কার্যই টেবলেটৰ কার্যক লেহেমীয়া কৰি অন্য এপবোৰৰ বাবে উপলব্ধ মেম\'ৰিক সীমাবদ্ধ কৰে।"</string>
+ <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"মেম\'ৰিত নিজৰ বাবে প্ৰয়োজনীয় ঠাই পৃথক কৰিবলৈ এপটোক অনুমতি দিয়ে। এই কার্যই অন্য এপবোৰৰ বাবে উপলব্ধ মেম\'ৰিক সীমাবদ্ধ কৰে যাৰ বাবে টিভিটো লেহেমীয়া হয়।"</string>
+ <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"মেম\'ৰিত নিজৰ বাবে প্ৰয়োজনীয় ঠাই পৃথক কৰিবলৈ এপক অনুমতি দিয়ে। এই কার্যই ফ\'নৰ কার্যক লেহেমীয়া কৰি অন্য এপবোৰৰ বাবে উপলব্ধ মেম\'ৰিক সীমাবদ্ধ কৰে।"</string>
+ <!-- no translation found for permlab_foregroundService (3310786367649133115) -->
+ <skip />
+ <!-- no translation found for permdesc_foregroundService (6471634326171344622) -->
+ <skip />
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"এপৰ সঞ্চয়াগাৰৰ খালী ঠাই হিচাপ কৰক"</string>
+ <string name="permdesc_getPackageSize" msgid="3921068154420738296">"এপটোক ইয়াৰ ক\'ড, ডেটা আৰু কেশ্বৰ আকাৰ বিচাৰি উলিয়াবলৈ অনুমতি দিয়ে"</string>
+ <string name="permlab_writeSettings" msgid="2226195290955224730">"ছিষ্টেম ছেটিংসমূহ সংশোধন কৰক"</string>
+ <string name="permdesc_writeSettings" msgid="7775723441558907181">"এপটোক ছিষ্টেমৰ ছেটিংসমূহৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ ক্ষতিকাৰক এপসমূহে আপোনাৰ ছিষ্টেম কনফিগাৰেশ্বনক ক্ষতিগ্ৰস্ত কৰিব পাৰে৷"</string>
+ <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"আৰম্ভ হোৱাৰ সময়ত চলাওক"</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ছিষ্টেমে বুট কৰা কাৰ্য সমাপ্ত কৰাৰ লগে লগে এপটোক নিজে নিজে আৰম্ভ হ\'বলৈ অনুমতি দিয়ে। ইয়াৰ ফলত ফ\'নটো ষ্টাৰ্ট হওতে বেছি সময়ৰ প্ৰয়োজন হ\'ব পাৰে, আৰু এপটো সদায় চলি থকাৰ কাৰণে ফ\'নটো সামগ্ৰিকভাৱে লেহেমীয়া হ\'ব পাৰে।"</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"ছিষ্টেমে বুটিং সমাপ্ত কৰাৰ লগে লগে এপটোক নিজে নিজে আৰম্ভ হ\'বলৈ অনুমতি দিয়ে। এই কাৰ্যটোৰ বাবে টিভিটো আৰম্ভ হ\'বলৈ দীৰ্ঘ সময়ৰ প্ৰয়োজন হ\'ব পাৰে আৰু সদায়ে ই চলি থকাৰ বাবে টে\'বলেটটো সামগ্ৰিকভাৱে লেহেমীয়া হৈ পৰিব পাৰে।"</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"ছিষ্টেমে বুট কৰা কাৰ্য সমাপ্ত কৰাৰ লগে লগে এপটোক নিজে নিজে আৰম্ভ হ\'বলৈ অনুমতি দিয়ে। ইয়াৰ ফলত ফ\'নটো ষ্টাৰ্ট হওতে বেছি সময়ৰ প্ৰয়োজন হ\'ব পাৰে, আৰু এপটো সদায় চলি থকাৰ কাৰণে ফ\'নটো সামগ্ৰিকভাৱে লেহেমীয়া হ\'ব পাৰে।"</string>
+ <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ষ্টিকী ব্ৰ\'ডকাষ্ট পঠিয়াওক"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"সম্প্ৰচাৰৰ শেষত বাকী ৰোৱা ষ্টিকী ব্ৰ\'ডকাষ্টবোৰ প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াক অত্য়ধিক ব্যৱহাৰ কৰাৰ ফলত মেম\'ৰি অধিক খৰচ হোৱাৰ বাবে টেবলেট লেহেমীয়া বা অস্থিৰ হৈ পৰে।"</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"এপটোক ষ্টিকী ব্ৰ\'ডকাষ্ট প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে, যিবোৰ সম্প্ৰচাৰ শেষ হোৱাৰ পিছতো ৰৈ যায়। ইয়াক অত্য়ধিক ব্যৱহাৰ কৰিলে মেম\'ৰি অধিক খৰচ হোৱাৰ বাবে টিভিটো লেহেমীয়া বা অস্থিৰ হৈ পৰিব পাৰে।"</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"সম্প্ৰচাৰৰ শেষত বাকী ৰোৱা ষ্টিকী ব্ৰ\'ডকাষ্টবোৰ প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াক অত্য়ধিক ব্যৱহাৰ কৰাৰ ফলত মেম\'ৰি অধিক খৰচ হোৱাৰ বাবে ফ\'নটো লেহেমীয়া বা অস্থিৰ হৈ পৰে।"</string>
+ <string name="permlab_readContacts" msgid="8348481131899886131">"নিজৰ সম্পর্ক সূচী পঢ়ক"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"আপুনি কোনো ব্যক্তি বিশেষৰ সৈতে টেবলেট, ইমেইল বা অন্য মাধ্যমেৰে কিমান সঘনাই যোগাযোগ কৰিছে সেই তথ্য়সহ ফ\'নৰ সম্পর্কসূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে৷ এই কার্যই এপক আপোনাৰ সম্পর্কৰ ডেটা ছেভ কৰিবলৈ অনুমতি দিয়ে আৰু ক্ষতিকাৰক এপবোৰে সম্পর্কসূচীৰ ডেটা আপোনাৰ অজ্ঞাতেই শ্বেয়াৰ কৰিব পাৰে৷"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"এপটোক আপোনাৰ টিভিত জমা থকা সম্পৰ্কসমূৰ বিষয়ে থকা ডেটা পঢ়িবলৈ অনুমতি দিয়াৰ লগতে আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই কল, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰিছে তাকো জানিবলৈ সুযোগ দিয়ে। এই বিশেষ অনুমতিটোৰ বাবে এপটোৱে আপোনাৰ সম্পর্ক ডেটা ছেভ কৰিব পাৰে, আৰু ক্ষতিকাৰক এপবোৰে সম্পর্কসূচীৰ ডেটা আপুনি নজনাকৈ শ্বেয়াৰ কৰিব পাৰে৷"</string>
+ <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই ফ\'ন, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰে সেই সম্পর্কে ফ\'নৰ সম্পর্ক সূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে। এই অনুমতিএ এপক আপোনাৰ সম্পর্কৰ ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপবোৰে সম্পর্কৰ ডেটা আপোনাৰ অজ্ঞাতেই শ্বেয়াৰ কৰিব পাৰে।"</string>
+ <string name="permlab_writeContacts" msgid="5107492086416793544">"আপোনাৰ সম্পর্ক সূচী সংশোধন কৰক"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"আপুনি ব্য়ক্তি বিশেষক কিমান সঘনাই কল কৰিছে, ইমেইল কৰিছে বা অন্য উপায়েৰে যোগাযোগ কৰিছে তাক অন্তৰ্ভুক্ত কৰি এপটোক আপোনাৰ টেবলেটত সঞ্চয় কৰি ৰখা সম্পৰ্ক সূচীৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ এই অনুমতি দিলে এপসমূহে সম্পৰ্কসূচীৰ ডেটা মচিব পাৰে।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"আপুনি যিসকল লোকক কল কৰিছে, ইমেইল কৰিছে বা সম্পৰ্কসূচীৰ বিশেষ লোকসকলৰ লগত অন্য উপায়েৰে যোগাযোগ কৰিছে তাক অন্তৰ্ভুক্ত কৰি এপটোক আপোনাৰ টিভিত সঞ্চয় কৰি ৰখা ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে। এই অনুমতিয়ে এপসমূহক সম্পৰ্কসূচীৰ ডেটা মচি পেলাবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই ফ\'ন, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰে সেই সম্পর্কে ফ\'নৰ সম্পর্ক সূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে। এই কার্যই এপক সম্পর্কৰ ডেটা মচিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_readCallLog" msgid="3478133184624102739">"কল লগ পঢ়ক"</string>
+ <string name="permdesc_readCallLog" msgid="3204122446463552146">"এই এপে আপোনাৰ কলৰ ইতিহাস পঢ়িব পাৰে।"</string>
+ <string name="permlab_writeCallLog" msgid="8552045664743499354">"কল লগ লিখক"</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"অন্তৰ্গামী আৰু বহিৰ্গামী কলৰ ডেটাকে ধৰি আপোনাৰ টেবলেটৰ কল লগ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। ক্ষতিকাৰক এপবোৰে আপোনাৰ কল লগ মচিবলৈ বা সংশোধন কৰিবলৈ ইয়াক ব্যৱহাৰ কৰিব পাৰে।"</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"অন্তৰ্গামী আৰু বহিৰ্গামী কলৰ ডেটাকে ধৰি আপোনাৰ টিভিৰ কল লগ সংশোধন কৰিবলৈ এপটোক অনুমতি দিয়ক। ক্ষতিকাৰক এপ্বোৰে আপোনাৰ কল লগ মচিবলৈ বা সংশোধন কৰিবলৈ এয়া ব্যৱহাৰ কৰিব পাৰে।"</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"অন্তৰ্গামী আৰু বহিৰ্গামী কলৰ ডেটাকে ধৰি আপোনাৰ ফ\'নৰ কল লগ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। ক্ষতিকাৰক এপবোৰে আপোনাৰ কল লগ মচিবলৈ বা সংশোধন কৰিবলৈ ইয়াক ব্যৱহাৰ কৰিব পাৰে।"</string>
+ <string name="permlab_bodySensors" msgid="4683341291818520277">"শৰীৰৰ ছেন্সৰসমূহ (যেনে হৃদপিণ্ডৰ গতিৰ হাৰ নিৰীক্ষক) ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"আপোনাৰ হৃদস্পন্দনৰ দৰে শাৰীৰিক অৱস্থাক নিৰীক্ষণ কৰা ছেন্সৰৰ পৰা ডেটা লাভ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_readCalendar" msgid="6716116972752441641">"কেলেণ্ডাৰৰ কাৰ্যক্ৰম আৰু সবিশেষ পঢ়িব পাৰে"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"এই এপটোৱে আপোনাৰ টেবলেটটোত সংৰক্ষিত সকলো কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"এই এপটোৱে আপোনাৰ টিভিটোত সংৰক্ষিত সকলো কেলেণ্ডাৰৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
+ <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"এই এপটোৱে আপোনাৰ ফ\'নটোত সংৰক্ষিত সকলো কেলেণ্ডাৰ কাৰ্যক্ৰম পঢ়িব পাৰে আৰু আপোনাৰ কেলেণ্ডাৰৰ ডেটা শ্বেয়াৰ বা ছেভ কৰিব পাৰে।"</string>
+ <string name="permlab_writeCalendar" msgid="8438874755193825647">"গৰাকীয়ে নজনাকৈয়ে কেলেণ্ডাৰৰ কাৰ্যক্ৰম সংশোধন কৰি অতিথিসকললৈ ইমেইল প্ৰেৰণ কৰক"</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"এই এপটোৱে আপোনাৰ টেবলেটত কেলেণ্ডাৰ কাৰ্যক্ৰম যোগ কৰিব, আঁতৰাব বা সলনি কৰিব পাৰে। ই এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা যেন লাগিব বা ই গৰাকীক নজনোৱাকৈ কাৰ্যক্ৰম সলনি কৰিব পাৰে৷"</string>
+ <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"এই এপটোৱে আপোনাৰ টিভিত কেলেণ্ডাৰ কাৰ্যক্ৰম যোগ কৰিব, আঁতৰাব বা সলনি কৰিব পাৰে। এই এপে এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা যেন লাগিব বা ই গৰাকীক নজনোৱাকৈ কাৰ্যক্ৰম সলনি কৰিব পাৰে৷"</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"এই এপে আপোনাৰ ফ\'নৰ কেলেণ্ডাৰত কার্যক্ৰম যোগ দিব, আঁতৰাব বা সলনি কৰিব পাৰে। ই এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা যেন লাগে বা ই গৰাকীক নজনোৱাকৈ কাৰ্যক্ৰম সলনি কৰিব পাৰে৷"</string>
+ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"অতিৰিক্ত অৱস্থান দেখুওৱা নির্দেশত প্ৰৱেশ কৰক"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"অৱস্থানৰ অতিৰিক্ত নির্দেশনাসমূহত প্ৰৱেশ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়ে এপটোক জিপিএছ বা অন্য অৱস্থান উৎসসমূহৰ কাৰ্যকলাপত হস্তক্ষেপ কৰাৰ সুযোগ দিব পাৰে।"</string>
+ <string name="permlab_accessFineLocation" msgid="251034415460950944">"সঠিক অৱস্থান (জিপিএছ আৰু নেটৱর্ক ভিত্তিক) ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"এই এপটোৱে জিপিএছ বা নেটৱর্কৰ উৎসসমূহ যেনে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্ক আদিক ভিত্তি কৰি আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ ফ\'নটোত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব। এই কার্যই অধিক বেটাৰি খৰচ কৰিব পাৰে।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"অনুমানিক অৱস্থান (নেটৱর্ক ভিত্তিক) ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টেবলেটটোত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
+ <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টিভিত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
+ <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"এই এপটোৱে ম\'বাইলৰ টাৱাৰ আৰু ৱাই-ফাইৰ নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্কৰ উৎসসমূহক ভিত্তি কৰি আপোনাৰ অৱস্থান চিনাক্ত কৰিব পাৰে। সেই অৱস্থান সেৱাসমূহ আপোনাৰ ফ\'নত সক্ষম অৱস্থাত থাকিলেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিব পাৰিব।"</string>
+ <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপোনাৰ অডিঅ\' ছেটিংসমূহ সলনি কৰক"</string>
+ <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"এপটোক ভলিউমৰ দৰে গ্ল\'বেল অডিঅ\' ছেটিংসমূহ যাৰ স্পীকাৰক আউটপুটৰ বাবে ব্যৱহাৰ হয় তাক সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"অডিঅ\' ৰেকর্ড কৰক"</string>
+ <string name="permdesc_recordAudio" msgid="4245930455135321433">"এই এপটোৱে যিকোনো সময়তে মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰি অডিঅ\' ৰেকৰ্ড কৰিব পাৰে।"</string>
+ <string name="permlab_sim_communication" msgid="2935852302216852065">"ছিমলৈ নিৰ্দেশ পঠিয়াব পাৰে"</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"ছিমলৈ নিৰ্দেশসমূহ প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে। ই অতি ক্ষতিকাৰক।"</string>
+ <string name="permlab_camera" msgid="3616391919559751192">"ফট\' তোলা আৰু ভিডিঅ\' ৰেকৰ্ড কৰা"</string>
+ <string name="permdesc_camera" msgid="5392231870049240670">"এই এপে যিকোনো সময়তে কেমেৰা ব্যৱহাৰ কৰি ফট\' তুলিব আৰু ভিডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string>
+ <string name="permlab_vibrate" msgid="7696427026057705834">"কম্পন নিয়ন্ত্ৰণ কৰক"</string>
+ <string name="permdesc_vibrate" msgid="6284989245902300945">"ভাইব্ৰেটৰ নিয়ন্ত্ৰণ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_callPhone" msgid="3925836347681847954">"পোনপটীয়াকৈ ফ\'ন নম্বৰলৈ কল কৰক"</string>
+ <string name="permdesc_callPhone" msgid="3740797576113760827">"আপোনাৰ কোনো ব্যাঘাত নোহোৱাকৈ ফ\'ন নম্বৰবোৰত কল কৰিবলৈ এপক অনুমতি দিয়ে৷ ইয়াৰ ফলত অপ্ৰত্যাশিত মাচুল ভৰিবলগা বা কলবোৰ কৰা হ\'ব পাৰে৷ মনত ৰাখিব যে ই এপটোক জৰুৰীকালীন নম্বৰবোৰত কল কৰিবলৈ অনুমতি নিদিয়ে৷ ক্ষতিকাৰক এপসমূহে আপোনাৰ অনুমতি নোলোৱাকৈয়ে কল কৰি আপোনাক টকা খৰছ কৰাব পাৰে৷"</string>
+ <string name="permlab_accessImsCallService" msgid="3574943847181793918">"আইএমএছ কল সেৱা ব্যৱহাৰ কৰিব পাৰে"</string>
+ <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"আপোনাৰ হস্তক্ষেপৰ অবিহনে আইএমএছ সেৱা ব্যৱহাৰ কৰি কল কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_readPhoneState" msgid="9178228524507610486">"ফ\'নৰ স্থিতি আৰু পৰিচয় পঢ়ক"</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ডিভাইচত থকা ফ\'নৰ সুবিধাসমূহ ব্য়ৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷ এই অনুমতিয়ে কোনো কল সক্ৰিয় হৈ থাককেই বা নাথাকক আৰু দূৰবৰ্তী নম্বৰটো কলৰ দ্বাৰা সংযোজিত হওকেই বা নহওক এপটোক ফ\'ন নম্বৰ আৰু ডিভাইচৰ পৰিচয় নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"ছিষ্টেমৰ জৰিয়তে কল কৰিব পাৰে"</string>
+ <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"কল কৰাৰ অভিজ্ঞতাক উন্নত কৰিবলৈ এপটোক ছিষ্টেমৰ জৰিয়তে কলসমূহ কৰিবলৈ দিয়ে।"</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ফ\'ন নম্বৰসমূহ পঢ়ে"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"এপটোক ডিভাইচটোৰ ফ\'ন নম্বৰসমূহ চাবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"টে\'বলেট সুপ্ত অৱস্থালৈ যোৱাত বাধা দিয়ক"</string>
+ <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"টিভি সুপ্ত অৱস্থালৈ যোৱাত বাধা দিয়ে"</string>
+ <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ফ\'ন সুপ্ত অৱস্থালৈ যোৱাত বাধা দিয়ক"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"টে\'বলেট সুপ্ত অৱস্থালৈ যোৱাৰ পৰা প্ৰতিৰোধ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"টিভিটোক সুপ্ত অৱস্থালৈ যোৱাৰ পৰা প্ৰতিৰোধ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"ফ\'ন সুপ্ত অৱস্থালৈ যোৱাৰ পৰা প্ৰতিৰোধ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_transmitIr" msgid="7545858504238530105">"ইনফ্ৰাৰেড ট্ৰান্সমিট কৰিব পাৰে"</string>
+ <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"টে\'বলেটৰ ইনফ্ৰাৰেড ট্ৰান্সমিটাৰ ব্যৱহাৰ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"টিভিৰ ইনফ্ৰাৰেড ট্ৰান্সমিটাৰ ব্যৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ফ\'নৰ ইনফ্ৰাৰেড ট্ৰান্সমিটাৰ ব্যৱহাৰ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_setWallpaper" msgid="6627192333373465143">"ৱালপেপাৰ ছেট কৰক"</string>
+ <string name="permdesc_setWallpaper" msgid="7373447920977624745">"ছিষ্টেমৰ ৱালপেপাৰ ছেট কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"আপোনাৰ ৱালপেপাৰৰ আকাৰ মিলাওক"</string>
+ <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ছিষ্টেমৰ ৱালপেপাৰৰ আকাৰ হিণ্ট ছেট কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_setTimeZone" msgid="2945079801013077340">"সময় মণ্ডল ছেট কৰক"</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"টে\'বলেটৰ সময় মণ্ডল সলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"টিভিৰ সময় মণ্ডল সলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ফ\'নৰ সময় মণ্ডল সলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_getAccounts" msgid="1086795467760122114">"ডিভাইচত একাউণ্টবোৰ বিচাৰক"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"এপটোক টেবলেটটোৰ জ্ঞাত একাউণ্টসমূহৰ সূচীখন পাবলৈ অনুমতি দিয়ে৷ এইটোৱে আপুনি ইনষ্টল কৰি ৰখা এপ্লিকেশ্বনসমূহে সৃষ্টি কৰা যিকোনো একাউণ্টক অন্তৰ্ভুক্ত কৰিব পাৰে৷"</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"এপটোক টিভিটোৱে জনা একাউণ্টসমূহৰ সূচীখন পাবলৈ অনুমতি দিয়ে। এইটোৱে আপুনি ইনষ্টল কৰি ৰখা এপ্লিকেশ্বনসমূহৰ দ্বাৰা সৃষ্ট যিকোনো একাউণ্টক অন্তৰ্ভুক্ত কৰিব পাৰে৷"</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"এপটোক ফ\'নটোৰ জ্ঞাত একাউণ্টসমূহৰ সূচীখন পাবলৈ অনুমতি দিয়ে৷ এইটোৱে আপুনি ইনষ্টল কৰি ৰখা এপ্লিকেশ্বনসমূহে সৃষ্টি কৰা যিকোনো একাউণ্টক অন্তৰ্ভুক্ত কৰিব পাৰে৷"</string>
+ <string name="permlab_accessNetworkState" msgid="4951027964348974773">"নেটৱৰ্কৰ সংযোগবোৰ চাওক"</string>
+ <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"মজুত থকা আৰু সংযোগ হৈ থকা নেটৱৰ্ক সংযোগসমূহৰ বিষয়ে তথ্য চাবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"সম্পূর্ণ নেটৱর্কৰ সুবিধা লাভ কৰিব পাৰে"</string>
+ <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"এপটোক নেটৱৰ্ক ছ\'কেটবোৰ সৃষ্টি কৰিবলৈ আৰু কাষ্টম নেটৱৰ্ক প্ৰ\'ট\'কল ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে৷ ব্ৰাউজাৰ আৰু অন্য এপ্লিকেশ্বনসমূহে ইণ্টাৰনেটলৈ ডেটা পঠিওৱা মাধ্য়ম প্ৰদান কৰে, গতিকে ইণ্টাৰনেটলৈ ডেটা পঠিয়াবলৈ এই অনুমতিৰ প্ৰয়োজন নাই৷"</string>
+ <string name="permlab_changeNetworkState" msgid="958884291454327309">"নেটৱৰ্কৰ সংযোগ সলনি কৰক"</string>
+ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"নেটৱৰ্ক সংযোগৰ অৱস্থাটো সলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_changeTetherState" msgid="5952584964373017960">"টেডাৰিং সংযোগ সলনি কৰক"</string>
+ <string name="permdesc_changeTetherState" msgid="1524441344412319780">"টেডাৰ হৈ থকা ইণ্টাৰনেট সংযোগৰ অৱস্থা সলনি কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"ৱাই-ফাইৰ সংযোগবোৰ চাওক"</string>
+ <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ৱাই-ফাই সক্ষম কৰা হ\'ল নে নাই আৰু সংযোগ হৈ থকা ৱাই-ফাই ডিভাইচসমূহৰ নামবোৰৰ দৰে ৱাই-ফাইৰ ইণ্টাৰনেট সম্পর্কীয় তথ্য চাবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_changeWifiState" msgid="6550641188749128035">"ৱাই-ফাই সংযোগ কৰক আৰু ইয়াৰ সংযোগ বিচ্ছিন্ন কৰক"</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"এপটোক ৱাই-ফাই এক্সেছ পইণ্টলৈ সংযোগ কৰিবলৈ আৰু তাৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ আৰু ৱাই-ফাই নেটৱৰ্কসমূহৰ বাবে ডিভাইচ কনফিগাৰেশ্বনত সাল-সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ৱাই-ফাই মাল্টিকাষ্ট প্ৰচাৰৰ অনুমতি দিয়ক"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"আপোনাৰ টেবলেটৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"কেৱল আপোনাৰ টিভিটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনা ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট লাভ কৰিবলৈ এপটোক অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ অধিক বেটাৰি ব্যৱহাৰ কৰে।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"আপোনাৰ ফ\'নৰ লগতে মাল্টিকাষ্ট ঠিকনাবোৰ ও ব্যৱহাৰ কৰি এপক ৱাই-ফাই নেটৱর্কত থকা সকলো ডিভাইচলৈ পঠোৱা পেকেট প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ে। এই কার্যই ন\'ন মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰিৰ অধিক চ্চাৰ্জ ব্যৱহাৰ কৰে।"</string>
+ <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ব্লুটুথ ছেটিংসমূহ ব্যৱহাৰ কৰক"</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"স্থানীয় ব্লুটুথ টে\'বলেট কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"স্থানীয় ব্লুটুথ টিভি কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰাবদ্ধ কৰিবলৈ আৰু বিচাৰি উলিয়াবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"স্থানীয় ব্লুটুথ ফ\'ন কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAXৰ লগত সংযোগ কৰক আৰু ইয়াৰ পৰা সংযোগ বিচ্ছিন্ন কৰক"</string>
+ <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"WiMAX সক্ষম হৈ আছেনে নাই আৰু সংযোজিত যিকোনো WiMAX নেটৱৰ্কৰ বিষয়ে তথ্য নিৰ্ধাৰণ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAXৰ স্থিতি সলনি কৰক"</string>
+ <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"এপটোক টেবলেটলৈ সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা টেবলেটৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"এপটোক টিভিৰ লগত সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা টিভিৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"এপটোক ফ\'নলৈ সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা ফ\'নৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে৷"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"ব্লুটুথ ডিভাইচবোৰৰ সৈতে যোৰা লগাওক"</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"টেবলেটত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"টিভিটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰ পাতি থোৱা ডিভাইচসমূহৰ সৈতে সংযোগ কৰিবলৈ আৰু গ্ৰহণ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ফ\'নটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string>
+ <string name="permlab_nfc" msgid="4423351274757876953">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string>
+ <string name="permdesc_nfc" msgid="7120611819401789907">"এপটোক নিয়েৰ ফিল্ড কমিউনিকেশ্বন (NFC) টেগ, কাৰ্ড আৰু ৰিডাৰসমূহৰ সৈতে যোগাযোগ কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"আপোনাৰ স্ক্ৰীণ ল\'ক অক্ষম কৰক"</string>
+ <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"এপটোক কী ল\'ক আৰু জড়িত হোৱা যিকোনো পাছৱৰ্ডৰ সুৰক্ষা অক্ষম কৰিব দিয়ে৷ উদাহৰণ স্বৰূপে, কোনো অন্তৰ্গামী ফ\'ন কল উঠোৱাৰ সময়ত ফ\'নটোৱে কী-লকটো অক্ষম কৰে, তাৰপিছত কল শেষ হ\'লেই কী লকটো পুনৰ সক্ষম কৰে৷"</string>
+ <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
+ <skip />
+ <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
+ <skip />
+ <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
+ <skip />
+ <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_partial (735082772341716043) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_insufficient (4596546021310923214) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_imager_dirty (1087209702421076105) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_fast (6470642383109155969) -->
+ <skip />
+ <!-- no translation found for fingerprint_acquired_too_slow (59250885689661653) -->
+ <skip />
+ <string-array name="fingerprint_acquired_vendor">
+ </string-array>
+ <!-- no translation found for fingerprint_not_recognized (2690661881608146617) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_hw_not_available (7955921658939936596) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_no_space (1055819001126053318) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_timeout (3927186043737732875) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_canceled (4402024612660774395) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_lockout (5536934748136933450) -->
+ <skip />
+ <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"অত্যধিক প্ৰয়াস। ফিংগাৰপ্ৰিণ্ট ছেন্সৰ অক্ষম কৰা হ\'ল।"</string>
+ <!-- no translation found for fingerprint_error_unable_to_process (6107816084103552441) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_no_fingerprints (7654382120628334248) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_hw_not_present (5729436878065119329) -->
+ <skip />
+ <!-- no translation found for fingerprint_name_template (5870957565512716938) -->
+ <skip />
+ <string-array name="fingerprint_error_vendor">
+ </string-array>
+ <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
+ <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ছিংকৰ ছেটিংসমূহ পঢ়ক"</string>
+ <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"একাউণ্টৰ ছিংক ছেটিংবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। যেনে, People এপ কোনো একাউণ্টত ছিংক কৰা হৈছে নে নাই সেয়া নির্ধাৰণ কৰিব পাৰে।"</string>
+ <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ছিংকক অন আৰু অফ ট\'গল কৰক"</string>
+ <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"এপটোক কোনো একাউণ্টৰ ছিংক সম্পৰ্কীয় ছেটিংসমূহ সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ উদাহৰণ স্বৰূপে, এই কাৰ্যক কোনো একাউণ্টৰ জৰিয়তে People এপটোৰ ছিংক সক্ষম কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি৷"</string>
+ <string name="permlab_readSyncStats" msgid="7396577451360202448">"ছিংকৰ পৰিসংখ্যা পঢ়ক"</string>
+ <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ছিংকৰ কাৰ্যক্ৰমসমূহৰ ইতিহাস আৰু ছিংক কৰা ডেটাৰ পৰিমাণসহ কোনো একাউণ্টৰ ছিংকৰ তথ্য পঢ়িবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"আপোনাৰ ইউএছবি সঞ্চয়াগাৰৰ সমলবোৰ পঢ়ক"</string>
+ <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"আপোনাৰ এছডি কাৰ্ডৰ সমলবোৰ পঢ়ক"</string>
+ <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"আপোনাৰ ইউএছবি সঞ্চয়াগাৰৰ সমলসমূহ পঢ়িবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"আপোনাৰ এছডি কাৰ্ডৰ সমল পঢ়িবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"আপোনাৰ ইউএছবি সঞ্চয়াগাৰৰ সমলবোৰ সংশোধন কৰক বা মচক"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"আপোনাৰ এছডি কাৰ্ডৰ সমলবোৰ সংশোধন কৰক বা মচক"</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"এপটোক ইউএছবি সঞ্চয়াগাৰত লিখাৰ অনুমতি দিয়ে।"</string>
+ <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"এপটোক এছডি কাৰ্ডত লিখাৰ অনুমতি দিয়ে।"</string>
+ <string name="permlab_use_sip" msgid="2052499390128979920">"SIP কল কৰা/পোৱা"</string>
+ <string name="permdesc_use_sip" msgid="2297804849860225257">"এপটোক SIP কলসমূহ কৰিবলৈ আৰু পাবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"নতুন টেলিকম ছিম সংযোগসমূহ পঞ্জীয়ন কৰা"</string>
+ <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"এপটোক নতুন টেলিকম সংযোগ পঞ্জীয়ন কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_register_call_provider" msgid="108102120289029841">"নতুন টেলিকম সংযোগসমূহ পঞ্জীয়ন কৰা"</string>
+ <string name="permdesc_register_call_provider" msgid="7034310263521081388">"এপটোক নতুন টেলিকম সংযোগ পঞ্জীয়ন কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"টেলিকম সংযোগ পৰিচালনা কৰা"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"এপটোক টেলিকম সংযোগ পৰিচালনা কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ইন-কল স্ক্ৰীণৰ সৈতে সংযোগ স্থাপন"</string>
+ <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ব্যৱহাৰকাৰীয়ে কেতিয়া আৰু কেনেদৰে ইন-কল-স্ক্ৰীণ চাব, তাক নিয়ন্ত্ৰণ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"টেলিফ\'নী সেৱাসমূহৰ সৈতে সংযোগ স্থাপন"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"কল কৰিবলৈ/লাভ কৰিবলৈ টেলিফ\'নী সেৱাসমূহৰ সৈতে এপক সংযোগ স্থাপনৰ বাবে অনুমতি দিয়ে।"</string>
+ <string name="permlab_control_incall_experience" msgid="9061024437607777619">"ইন-কল ব্যৱহাৰকাৰীৰ অভিজ্ঞতা প্ৰদান কৰা"</string>
+ <string name="permdesc_control_incall_experience" msgid="915159066039828124">"এপটোক ইন-কল ব্যৱহাৰকাৰীৰ অভিজ্ঞতা প্ৰদান কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"নেটৱর্কৰ পূৰ্বতে হোৱা ব্যৱহাৰৰ বিষয়ে পঢ়ক"</string>
+ <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"এপটোক বিশেষ নেটৱৰ্কবিলাকৰ আৰু এপ্সমূহৰ নেটৱৰ্ক ব্যৱহাৰৰ ইতিহাস পঢ়িবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"নেটৱর্কৰ নীতি পৰিচালনা কৰক"</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"এপটোক নেটৱৰ্ক সংযোগৰ নীতিসমূহ পৰিচালনা কৰিবলৈ আৰু এপ্-বিশেষ নিয়ম সংজ্ঞাবদ্ধ কৰিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"নেটৱর্ক ব্যৱহাৰৰ হিচাপ সলনি কৰক"</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"এপ অনুসুৰি নেটৱর্কৰ ব্যৱহাৰৰ হিচাপ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। এয়া সাধাৰণ এপবোৰৰ ব্যৱহাৰৰ বাবে নহয়।"</string>
+ <string name="permlab_accessNotifications" msgid="7673416487873432268">"প্ৰৱেশ জাননীসমূহ"</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"অন্য এপসমূহৰদ্বাৰা প\'ষ্ট কৰা জাননীসমূহকে ধৰি জাননী বিচাৰি উলিয়াবলৈ, পৰীক্ষা কৰিবলৈ আৰু মচিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"এটা জাননী শুনা সেৱাৰ লগত সংযুক্ত হ\'ব পাৰে"</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"এটা জাননী শ্ৰৱণ সেৱা প্ৰদানকাৰীৰ শীৰ্ষ স্তৰৰ ইণ্টাৰফেইচৰ লগত সংযুক্ত হ\'বলৈ ধাৰকক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"এটা অৱস্থা প্ৰদানকাৰী সেৱাৰ লগত সংযুক্ত হ\'ব পাৰে"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"অৱস্থা প্ৰদানকাৰী সেৱাৰ শীৰ্ষ স্তৰৰ ইণ্টাৰফেচইলৈ সংযুক্ত হ\'বলৈ বাহকক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_bindDreamService" msgid="4153646965978563462">"এটা ড্ৰিম সেৱাৰ লগত সংযুক্ত হ\'ব পাৰে"</string>
+ <string name="permdesc_bindDreamService" msgid="7325825272223347863">"এটা ড্ৰিম সেৱাৰ শীৰ্ষ স্তৰৰ ইণ্টাৰফেইচলৈ সংযুক্ত হ\'বলৈ ধাৰকক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"বাহকৰদ্বাৰা প্ৰদান কৰা কনফিগাৰেশ্বন এপক কামত লগাব পাৰে"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"বাহকে যোগান ধৰা কনফিগাৰেশ্বন এপ্ ব্যৱহাৰ কৰিবলৈ ধাৰকক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"নেটৱৰ্ক অৱস্থাসমূহৰ ওপৰত নিৰীক্ষণৰ বাবে শুনিব পাৰে"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"এটা এপ্লিকেশ্বনক নেটৱৰ্ক অৱস্থাসমূহত নিৰীক্ষণৰ বাবে শুনিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ইনপুট ডিভাইচ কেলিব্ৰেশ্বন সলনি কৰিব পাৰে"</string>
+ <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"টাচ্চ স্ক্ৰীণৰ কেলিব্ৰেশ্বন পেৰামিটাৰ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM প্ৰমাণপত্ৰসমূহলৈ প্ৰৱেশ"</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"এটা এপ্লিকেশ্বনক DRM প্ৰমাণপত্ৰ গোটাবলৈ আৰু ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_handoverStatus" msgid="7820353257219300883">"Android বীম স্থানান্তৰণৰ স্থিতি লাভ কৰিব পাৰে"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"বৰ্তমানৰ Android Beam স্থানান্তৰণসমূহৰ বিষয়ে তথ্য পাবলৈ এই এপ্লিকেশ্বনক অনুমতি দিয়ে"</string>
+ <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM প্ৰমাণপত্ৰসমূহ আঁতৰোৱা"</string>
+ <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"এটা এপ্লিকেশ্বনক DRM প্ৰমাণপত্ৰ আঁতৰাবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে কেতিয়াও প্ৰয়োজন নহয়।"</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"বাহকৰ মেছেজিং সেৱাৰ লগত সংযোগ কৰে"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"বাহক মেছেজিং সেৱাৰ উচ্চ স্তৰৰ ইণ্টাৰফেইচত সংযোগ কৰিবলৈ ধাৰকক অনুমতি দিয়ে। এয়া সাধাৰণ এপবোৰৰ বাবে কেতিয়াও প্ৰয়োজন নহয়।"</string>
+ <!-- no translation found for permlab_bindCarrierServices (3233108656245526783) -->
+ <skip />
+ <!-- no translation found for permdesc_bindCarrierServices (1391552602551084192) -->
+ <skip />
+ <!-- no translation found for permlab_access_notification_policy (4247510821662059671) -->
+ <skip />
+ <!-- no translation found for permdesc_access_notification_policy (3296832375218749580) -->
+ <skip />
+ <string name="policylab_limitPassword" msgid="4497420728857585791">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
+ <!-- no translation found for policydesc_limitPassword (2502021457917874968) -->
+ <skip />
+ <string name="policylab_watchLogin" msgid="5091404125971980158">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে টে\'বলেটটো লক কৰক বা টে\'বলেটটোৰ সকলো ডেটা মোহাৰক।"</string>
+ <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে টিভিটো লক কৰক বা টিভিটোৰ সকলো ডেটা মোহাৰক।"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে ফ\'নটো লক কৰক বা ফ\'নটোৰ সকলো ডেটা মোহাৰক।"</string>
+ <!-- no translation found for policydesc_watchLogin_secondaryUser (4280246270601044505) -->
+ <skip />
+ <!-- no translation found for policydesc_watchLogin_secondaryUser (3484832653564483250) -->
+ <skip />
+ <!-- no translation found for policydesc_watchLogin_secondaryUser (2185480427217127147) -->
+ <skip />
+ <!-- no translation found for policylab_resetPassword (4934707632423915395) -->
+ <skip />
+ <!-- no translation found for policydesc_resetPassword (1278323891710619128) -->
+ <skip />
+ <string name="policylab_forceLock" msgid="2274085384704248431">"স্ক্ৰীণখন লক কৰক"</string>
+ <string name="policydesc_forceLock" msgid="1141797588403827138">"স্ক্ৰীণ কেনেকৈ আৰু কেতিয়া ল\'ক হ\'ব লাগে সেয়া নিয়ন্ত্ৰণ কৰক।"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"সকলো ডেটা মচক"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টেবলেটৰ ডেটা মচক।"</string>
+ <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টিভিৰ ডেটা মোহাৰক।"</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ফ\'নৰ ডেটা মচক।"</string>
+ <!-- no translation found for policylab_wipeData_secondaryUser (8362863289455531813) -->
+ <skip />
+ <!-- no translation found for policydesc_wipeData_secondaryUser (6336255514635308054) -->
+ <skip />
+ <!-- no translation found for policydesc_wipeData_secondaryUser (2086473496848351810) -->
+ <skip />
+ <!-- no translation found for policydesc_wipeData_secondaryUser (6787904546711590238) -->
+ <skip />
+ <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক"</string>
+ <!-- no translation found for policydesc_setGlobalProxy (8459859731153370499) -->
+ <skip />
+ <!-- no translation found for policylab_expirePassword (5610055012328825874) -->
+ <skip />
+ <!-- no translation found for policydesc_expirePassword (5367525762204416046) -->
+ <skip />
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"সঞ্চয়াগাৰৰ এনক্ৰিপশ্বন ছেট কৰক"</string>
+ <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"সঞ্চয় কৰি ৰখা ডেটাক এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন।"</string>
+ <string name="policylab_disableCamera" msgid="6395301023152297826">"কেমেৰাবোৰ অক্ষম কৰক"</string>
+ <string name="policydesc_disableCamera" msgid="2306349042834754597">"সকলো ডিভাইচৰ কেমেৰাবোৰ ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা ব্যৱহাৰ হোৱাত বাধা দিয়ক।"</string>
+ <string-array name="phoneTypes">
+ <item msgid="8901098336658710359">"ঘৰ"</item>
+ <item msgid="869923650527136615">"ম\'বাইল"</item>
+ <item msgid="7897544654242874543">"কৰ্মস্থান"</item>
+ <item msgid="1103601433382158155">"কর্মস্থানৰ ফেক্সৰ নম্বৰ"</item>
+ <item msgid="1735177144948329370">"ঘৰৰ ফেক্স নম্বৰ"</item>
+ <item msgid="603878674477207394">"পেজাৰ"</item>
+ <item msgid="1650824275177931637">"অন্যান্য"</item>
+ <item msgid="9192514806975898961">"নিজৰ উপযোগিতা অনুযায়ী"</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item msgid="8073994352956129127">"ঘৰ"</item>
+ <item msgid="7084237356602625604">"কৰ্মস্থান"</item>
+ <item msgid="1112044410659011023">"অন্যান্য"</item>
+ <item msgid="2374913952870110618">"নিজৰ উপযোগিতা অনুযায়ী"</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item msgid="6880257626740047286">"ঘৰ"</item>
+ <item msgid="5629153956045109251">"কৰ্মস্থান"</item>
+ <item msgid="4966604264500343469">"অন্যান্য"</item>
+ <item msgid="4932682847595299369">"নিজৰ উপযোগিতা অনুযায়ী"</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item msgid="1738585194601476694">"ঘৰ"</item>
+ <item msgid="1359644565647383708">"কৰ্মস্থান"</item>
+ <item msgid="7868549401053615677">"অন্যান্য"</item>
+ <item msgid="3145118944639869809">"নিজৰ উপযোগিতা অনুযায়ী"</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item msgid="7546335612189115615">"কৰ্মস্থান"</item>
+ <item msgid="4378074129049520373">"অন্যান্য"</item>
+ <item msgid="3455047468583965104">"নিজৰ উপযোগিতা অনুযায়ী"</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item msgid="8595261363518459565">"এআইএম"</item>
+ <item msgid="7390473628275490700">"Windows Live"</item>
+ <item msgid="7882877134931458217">"Yahoo"</item>
+ <item msgid="5035376313200585242">"Skype"</item>
+ <item msgid="7532363178459444943">"QQ"</item>
+ <item msgid="3713441034299660749">"Google Talk"</item>
+ <item msgid="2506857312718630823">"ICQ"</item>
+ <item msgid="1648797903785279353">"Jabber"</item>
+ </string-array>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="phoneTypeHome" msgid="2570923463033985887">"ঘৰৰ ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeMobile" msgid="6501463557754751037">"ম\'বাইল"</string>
+ <string name="phoneTypeWork" msgid="8863939667059911633">"কৰ্মস্থানৰ ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"কর্মস্থানৰ ফেক্সৰ নম্বৰ"</string>
+ <string name="phoneTypeFaxHome" msgid="2067265972322971467">"ঘৰৰ ফেক্স নম্বৰ"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"পেজাৰৰ নম্বৰ"</string>
+ <string name="phoneTypeOther" msgid="1544425847868765990">"অন্যান্য"</string>
+ <string name="phoneTypeCallback" msgid="2712175203065678206">"কলবেক কৰক"</string>
+ <string name="phoneTypeCar" msgid="8738360689616716982">"গাড়ী"</string>
+ <string name="phoneTypeCompanyMain" msgid="540434356461478916">"কোম্পানীৰ মুখ্য ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeIsdn" msgid="8022453193171370337">"আইএছডিএন"</string>
+ <string name="phoneTypeMain" msgid="6766137010628326916">"মুখ্য ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeOtherFax" msgid="8587657145072446565">"অন্য ফেক্স নম্বৰ"</string>
+ <string name="phoneTypeRadio" msgid="4093738079908667513">"ৰেডিঅ’ ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeTelex" msgid="3367879952476250512">"টেলেক্স ফ\'ন নম্বৰ"</string>
+ <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"কৰ্মস্থানৰ ম\'বাইল নম্বৰ"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"কৰ্মস্থানৰ পেজাৰৰ নম্বৰ"</string>
+ <string name="phoneTypeAssistant" msgid="5596772636128562884">"সহায়ক"</string>
+ <string name="phoneTypeMms" msgid="7254492275502768992">"এমএমএছ"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="eventTypeBirthday" msgid="2813379844211390740">"জন্মদিন"</string>
+ <string name="eventTypeAnniversary" msgid="3876779744518284000">"বর্ষপূর্তি"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"অন্যান্য"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="emailTypeHome" msgid="449227236140433919">"ঘৰ"</string>
+ <string name="emailTypeWork" msgid="3548058059601149973">"কৰ্মস্থান"</string>
+ <string name="emailTypeOther" msgid="2923008695272639549">"অন্যান্য"</string>
+ <string name="emailTypeMobile" msgid="119919005321166205">"ম\'বাইল"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="postalTypeHome" msgid="8165756977184483097">"ঘৰৰ ঠিকনা"</string>
+ <string name="postalTypeWork" msgid="5268172772387694495">"কৰ্মস্থানৰ ঠিকনা"</string>
+ <string name="postalTypeOther" msgid="2726111966623584341">"অন্যান্য"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="imTypeHome" msgid="6241181032954263892">"ঘৰ"</string>
+ <string name="imTypeWork" msgid="1371489290242433090">"কৰ্মস্থান"</string>
+ <string name="imTypeOther" msgid="5377007495735915478">"অন্যান্য"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="imProtocolAim" msgid="7050360612368383417">"এআইএম"</string>
+ <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
+ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
+ <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string>
+ <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string>
+ <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string>
+ <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string>
+ <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string>
+ <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
+ <string name="orgTypeWork" msgid="29268870505363872">"কৰ্মস্থান"</string>
+ <string name="orgTypeOther" msgid="3951781131570124082">"অন্যান্য"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"সহায়ক"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"ভাতৃ"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"শিশু"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"সংগী"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"দেউতা"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"বন্ধু"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"মেনেজাৰ"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"মাতৃ"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"অভিভাৱক"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"সংগী"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"মাধ্যমেৰে"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"সম্বন্ধীয়"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"ভনী"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"পতি-পত্নী"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"নিজৰ উপযোগিতা অনুযায়ী"</string>
+ <string name="sipAddressTypeHome" msgid="6093598181069359295">"ঘৰৰ ঠিকনা"</string>
+ <string name="sipAddressTypeWork" msgid="6920725730797099047">"কৰ্মস্থান"</string>
+ <string name="sipAddressTypeOther" msgid="4408436162950119849">"অন্যান্য"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"এই সম্পৰ্ক চাবলৈ কোনো এপ্লিকেশ্বন পোৱা ন\'গল।"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"পিন ক\'ড লিখক"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK আৰু নতুন পিন ক\'ড লিখক"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK ক\'ড"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"নতুন পিন ক\'ড"</string>
+ <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17"></font>" পাছৱর্ড লিখিবলৈ টিপক"</string>
+ <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"আনলক কৰিবলৈ পাছৱৰ্ড লিখক"</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"আনলক কৰিবলৈ পিন লিখক"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ভুল পিন ক\'ড।"</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"আনলক কৰিবলৈ মেনু টিপাৰ পিছত ০ টিপক।"</string>
+ <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"জৰুৰীকালীন নম্বৰ"</string>
+ <string name="lockscreen_carrier_default" msgid="6169005837238288522">"কোনো সেৱা নাই"</string>
+ <string name="lockscreen_screen_locked" msgid="7288443074806832904">"স্ক্ৰীণ লক কৰা হ\'ল।"</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"আনলক কৰিবলৈ বা জৰুৰীকালীন কল কৰিবলৈ মেনু টিপক।"</string>
+ <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"আনলক কৰিবলৈ মেনু টিপক।"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"আনলক কৰিবলৈ আর্হি আঁকক"</string>
+ <!-- no translation found for lockscreen_emergency_call (5298642613417801888) -->
+ <skip />
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"কললৈ উভতি যাওক"</string>
+ <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"শুদ্ধ!"</string>
+ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"আকৌ চেষ্টা কৰক"</string>
+ <string name="lockscreen_password_wrong" msgid="5737815393253165301">"আকৌ চেষ্টা কৰক"</string>
+ <string name="lockscreen_storage_locked" msgid="9167551160010625200">"সকলো সুবিধা আৰু ডেটাৰ বাবে আনলক কৰক"</string>
+ <string name="faceunlock_multiple_failures" msgid="754137583022792429">"গৰাকীৰ মুখাৱয়বৰ দ্বাৰা আনলক কৰা সর্বধিক সীমা অতিক্ৰম কৰা হ\'ল"</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"কোনো ছিম কাৰ্ড নাই"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"টে\'বলেটত ছিম কার্ড নাই।"</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"টিভিত ছিম কার্ড নাই।"</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ফ\'নত ছিম কার্ড নাই।"</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"এখন ছিম কাৰ্ড ভৰাওক।"</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"ছিম কাৰ্ডখন নাই বা পঢ়িব পৰা নগ\'ল। এখন ছিম কাৰ্ড ভৰাওক।"</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"ব্যৱহাৰৰ অযোগ্য ছিম কাৰ্ড।"</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"আপোনাৰ ছিম কাৰ্ডখন স্থায়ীভাৱে অক্ষম হৈছে।\n অন্য এখন ছিমৰ বাবে আপোনাৰ ৱায়াৰলেছ সেৱা প্ৰদানকাৰীৰ সৈতে যোগাযোগ কৰক।"</string>
+ <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"পূৰ্বৱৰ্তী ট্ৰেক"</string>
+ <string name="lockscreen_transport_next_description" msgid="573285210424377338">"পৰৱৰ্তী ট্ৰেক"</string>
+ <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"পজ কৰক"</string>
+ <string name="lockscreen_transport_play_description" msgid="1901258823643886401">"প্লে কৰক"</string>
+ <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"বন্ধ কৰক"</string>
+ <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"ৰিৱাইণ্ড কৰক"</string>
+ <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"ফাষ্ট ফৰৱাৰ্ড"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"জৰুৰীকালীন কল মাত্ৰ"</string>
+ <string name="lockscreen_network_locked_message" msgid="143389224986028501">"নেটৱর্ক অৱৰোধিত"</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"PUKৰ দ্বাৰা লক কৰা ছিম কার্ড।"</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ব্যৱহাৰকাৰীৰ নিৰ্দেশনা চাওক বা গ্ৰাহক সেৱা কেন্দ্ৰৰ সৈতে যোগাযোগ কৰক।"</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"ছিম কাৰ্ড লক কৰা হৈছে।"</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"ছিম কার্ড আনলক কৰি থকা হৈছে…"</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"আপুনি অশুদ্ধভাৱে আপোনাৰ আনলক আৰ্হি <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_password_attempts_dialog_message" msgid="2725973286239344555">"আপুনি অশুদ্ধভাৱে আপোনাৰ পাছৱৰ্ড <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="6216672706545696955">"আপুনি অশুদ্ধভাৱে আপোনাৰ পিন <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="9191611984625460820">"আপুনি অশুদ্ধভাৱে আপোনাৰ লক খোলাৰ আৰ্হিটো <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="5316664559603394684">"আপুনি অশুদ্ধভাৱে আপোনাৰ আনলক আৰ্হি <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="default" msgid="2590227559763762751">"আপুনি অশুদ্ধভাৱে আপোনাৰ লক খোলাৰ আৰ্হিটো <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="6128106399745755604">"আপুনি টে\'বলেটটো <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="950408382418270260">"আপুনি টিভিটো আনলক কৰিবলৈ <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="default" msgid="8603565142156826565">"আপুনি ফ\'নটো <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="280873516493934365">"আপুনি অশুদ্ধভাৱে টে\'বলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ চেষ্টা কৰিছিল। টে\'বলেটটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"আপুনি টিভিটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। টিভিটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"আপুনি অশুদ্ধভাৱে ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ চেষ্টা কৰিছিল। ফ\'নটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডৰ পাছত চেষ্টা কৰক।"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"আর্হি পাহৰিলে নেকি?"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"একাউণ্ট আনলক"</string>
+ <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"বহুতবাৰ ভুলকৈ আর্হি অঁকা হ\'ল"</string>
+ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"আনলক কৰিবলৈ নিজৰ Google একাউণ্টৰ জৰিয়তে ছাইন ইন কৰক।"</string>
+ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ব্যৱহাৰকাৰীৰ নাম (ইমেইল)"</string>
+ <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"পাছৱৰ্ড"</string>
+ <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ছাইন ইন কৰক"</string>
+ <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ব্যৱহাৰকাৰীৰ নাম আৰু পাছৱর্ড মান্য নহয়।"</string>
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"আপোনাৰ ব্যৱহাৰকাৰী নাম আৰু পাছৱর্ড পাহৰিলে নেকি?\n"<b>"google.com/accounts/recovery"</b>" চাওক।"</string>
+ <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"পৰীক্ষা কৰি থকা হৈছে…"</string>
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"আনলক"</string>
+ <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ধ্বনি অন হৈ আছে"</string>
+ <string name="lockscreen_sound_off_label" msgid="996822825154319026">"ধ্বনি অফ হৈ আছে"</string>
+ <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"আর্হি অঁকা কার্য আৰম্ভ হ\'ল"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"আর্হি মচি পেলোৱা হ\'ল"</string>
+ <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"আৰ্হিত এটা বিন্দু যোগ কৰিছে"</string>
+ <string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"চেল <xliff:g id="CELL_INDEX">%1$s</xliff:g> যোগ কৰা হ\'ল"</string>
+ <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"আর্হি অঁকা সর্ম্পূণ হ\'ল"</string>
+ <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"আর্হিৰ ক্ষেত্ৰ।"</string>
+ <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. ৱিজেট %3$d-ৰ %2$d।"</string>
+ <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ৱিজেট যোগ কৰক।"</string>
+ <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"খালী"</string>
+ <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"আনলক ক্ষেত্ৰ বিস্তাৰিত হৈছে।"</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"আনলক ক্ষেত্ৰ সংকুচিত হৈছে।"</string>
+ <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ৱিজেট।"</string>
+ <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ব্যৱহাৰকাৰী নিৰ্বাচক"</string>
+ <string name="keyguard_accessibility_status" msgid="8008264603935930611">"স্থিতি"</string>
+ <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"কেমেৰা"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"মিডিয়াৰ নিয়ন্ত্ৰণসমূহ"</string>
+ <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"ৱিজেটৰ পুনঃক্ৰম আৰম্ভ হ\'ল।"</string>
+ <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"ৱিজেটৰ পুনঃক্ৰম সমাপ্ত হ\'ল।"</string>
+ <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ৱিজেট <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> মচা হ\'ল।"</string>
+ <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"আনলক ক্ষেত্ৰ বিস্তাৰ কৰক।"</string>
+ <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"শ্লাইডৰদ্বাৰা আনলক।"</string>
+ <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"আৰ্হিৰদ্বাৰা আনলক।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"গৰাকীৰ মুখাৱয়বৰদ্বাৰা আনলক।"</string>
+ <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"পিনৰদ্বাৰা আনলক।"</string>
+ <!-- no translation found for keyguard_accessibility_sim_pin_unlock (9149698847116962307) -->
+ <skip />
+ <!-- no translation found for keyguard_accessibility_sim_puk_unlock (9106899279724723341) -->
+ <skip />
+ <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"পাছৱৰ্ডৰদ্বাৰা আনলক।"</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"আৰ্হি ক্ষেত্ৰ।"</string>
+ <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"শ্লাইড ক্ষেত্ৰ।"</string>
+ <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?১২৩"</string>
+ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
+ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
+ <string name="granularity_label_character" msgid="7336470535385009523">"বর্ণ"</string>
+ <string name="granularity_label_word" msgid="7075570328374918660">"শব্দ"</string>
+ <string name="granularity_label_link" msgid="5815508880782488267">"লিংক"</string>
+ <string name="granularity_label_line" msgid="5764267235026120888">"লাইন"</string>
+ <string name="factorytest_failed" msgid="5410270329114212041">"ফেক্টৰীৰ পৰীক্ষা কৰিব পৰা নগ\'ল"</string>
+ <string name="factorytest_not_system" msgid="4435201656767276723">"কেৱল /ছিষ্টেম/এপ-ত ইনষ্টল কৰি থোৱা পেকেজৰ বাবেহে FACTORY_TEST কৰিব পৰা যায়।"</string>
+ <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST কার্যৰ বাবে কোনো পেকেজ পোৱা নগ\'ল।"</string>
+ <string name="factorytest_reboot" msgid="6320168203050791643">"ৰিবুট কৰক"</string>
+ <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\"ত পৃষ্ঠাৰ প্ৰত্য়ুত্তৰ:"</string>
+ <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
+ <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"নেভিগেশ্বন নিশ্চিত কৰক"</string>
+ <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"এই পৃষ্ঠাটোৰ পৰা আঁতৰি যাওক"</string>
+ <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"এই পৃষ্ঠাটোতে থাকক"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nআপুনি এই পৃষ্ঠাটো এৰি বেলেগলৈ যাব বিচাৰে নেকি?"</string>
+ <string name="save_password_label" msgid="6860261758665825069">"নিশ্চিত কৰক"</string>
+ <string name="double_tap_toast" msgid="4595046515400268881">"পৰামৰ্শ: জুম ইন আৰু আউট কৰিবলৈ দুবাৰ টিপক৷"</string>
+ <string name="autofill_this_form" msgid="4616758841157816676">"স্বয়ংপূৰ্তি"</string>
+ <string name="setup_autofill" msgid="7103495070180590814">"স্বয়ংপূৰ্তি ছেট আপ কৰক"</string>
+ <!-- no translation found for autofill_window_title (921006636895825007) -->
+ <skip />
+ <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+ <string name="autofill_province" msgid="2231806553863422300">"প্ৰদেশ"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"পিন ক\'ড"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"ৰাজ্য"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"পিন ক\'ড"</string>
+ <string name="autofill_county" msgid="237073771020362891">"জিলা"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"দ্বীপ"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"জিলা"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"বিভাগ"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"জিলাৰ মুৰব্বী"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"গাঁও"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"ক্ষেত্ৰ"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"এমিৰেট"</string>
+ <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"আপোনাৰ ৱেব বুকমার্কবোৰ আৰু ইতিহাস পঢ়ক"</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰে ব্যৱহাৰ কৰা সকলো URLৰ ইতিহাস পঢ়িবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
+ <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"আপোনাৰ ৱেব বুকমার্কবোৰ আৰু ইতিহাস লিখক"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"আপোনাৰ টেবলেটত সঞ্চয় কৰি ৰখা ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰৰ ইতিহাস সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"আপোনাৰ টিভিত সঞ্চয় কৰি ৰখা ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰৰ ইতিহাস সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিংৰ ক্ষমতা থকা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"আপোনাৰ ফ\'নত সঞ্চয় কৰি ৰখা ব্ৰাউজাৰৰ বুকমার্ক আৰু ব্ৰাউজাৰৰ ইতিহাস সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। টোকা: এই অনুমতি তৃতীয় পক্ষৰ ব্ৰাউজাৰবোৰ বা ৱেব ব্ৰাউজিং কৰিব পৰা অন্য এপ্লিকেশ্বনবোৰৰ দ্বাৰা বলৱৎ নহ\'বও পাৰে।"</string>
+ <string name="permlab_setAlarm" msgid="1379294556362091814">"এলাৰ্ম ছেট কৰক"</string>
+ <string name="permdesc_setAlarm" msgid="316392039157473848">"এপটোক ইনষ্টল হৈ থকা এলাৰ্ম ক্লক এপত এলাৰ্ম ছেট কৰিবলৈ অনুমতি দিয়ে। কিছুমান এলাৰ্ম ক্লক এপত এই সুবিধাটো প্ৰযোজ্য নহ\'ব পাৰে।"</string>
+ <string name="permlab_addVoicemail" msgid="5525660026090959044">"ভইচমেইল যোগ কৰক"</string>
+ <string name="permdesc_addVoicemail" msgid="6604508651428252437">"আপোনাৰ ভইচমেইল ইনবক্সত বাৰ্তাবোৰ যোগ কৰিবলৈ এপটোক অনুমতি দিয়ক।"</string>
+ <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ব্ৰাউজাৰৰ জিঅ\'লোকেশ্বনৰ অনুমতিসমূহ সংশোধন কৰক"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ব্ৰাউজাৰৰ জিঅ\'লোকেশ্বন বিষয়ক অনুমতিসমূহ সংশোধন কৰিবলৈ এপটোক অনুমতি দিয়ে৷ ক্ষতিকাৰক এপবোৰে একপক্ষীয় ৱেবছাইটসমূহলৈ অৱস্থান সেৱাৰ তথ্য পঠিয়াবলৈ ইয়াক ব্যৱহাৰ কৰিব পাৰে৷"</string>
+ <string name="save_password_message" msgid="767344687139195790">"ব্ৰাউজাৰে এই পাছৱর্ডটো মনত ৰখাটো বিচাৰেনে?"</string>
+ <string name="save_password_notnow" msgid="6389675316706699758">"এতিয়াই নহয়"</string>
+ <string name="save_password_remember" msgid="6491879678996749466">"মনত ৰাখিব"</string>
+ <string name="save_password_never" msgid="8274330296785855105">"কেতিয়াও মনত নাৰাখিব"</string>
+ <string name="open_permission_deny" msgid="7374036708316629800">"এই পৃষ্ঠাটো খুলিবলৈ আপোনাৰ অনুমতি নাই।"</string>
+ <string name="text_copied" msgid="4985729524670131385">"ক্লিপব\'র্ডলৈ বাৰ্তা প্ৰতিলিপি কৰা হ\'ল।"</string>
+ <string name="more_item_label" msgid="4650918923083320495">"অধিক"</string>
+ <string name="prepend_shortcut_label" msgid="2572214461676015642">"মেনু+"</string>
+ <string name="menu_space_shortcut_label" msgid="2410328639272162537">"স্পেচ"</string>
+ <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"লিখক"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"মচক"</string>
+ <string name="search_go" msgid="8298016669822141719">"অনুসন্ধান কৰক"</string>
+ <string name="search_hint" msgid="1733947260773056054">"অনুসন্ধান কৰক…"</string>
+ <string name="searchview_description_search" msgid="6749826639098512120">"অনুসন্ধান কৰক"</string>
+ <string name="searchview_description_query" msgid="5911778593125355124">"প্ৰশ্নৰ সন্ধান কৰক"</string>
+ <string name="searchview_description_clear" msgid="1330281990951833033">"প্ৰশ্ন মচক"</string>
+ <string name="searchview_description_submit" msgid="2688450133297983542">"প্ৰশ্ন দাখিল কৰক"</string>
+ <string name="searchview_description_voice" msgid="2453203695674994440">"কণ্ঠধ্বনিৰ যোগেৰে সন্ধান কৰক"</string>
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"স্পৰ্শৰে অন্বেষণ কৰা সুবিধা সক্ষম কৰিবনে?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>এ স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰিব বিচাৰে। যেতিয়া স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰা সুবিধা অন কৰা থাকে তেতিয়া আপোনাৰ আঙুলিৰ তলত থকা বিৱৰণবোৰ শুনিব বা চাব পাৰে বা আঙুলিৰ সংকেতৰ জৰিয়তে টেবলেট ব্যৱহাৰ কৰিব পাৰে।"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>এ স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰিব বিচাৰে। যেতিয়া স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰা সুবিধা অন কৰা থাকে তেতিয়া আপোনাৰ আঙুলিৰ তলত থকা বিৱৰণবোৰ শুনিব বা চাব পাৰে বা আঙুলিৰ ইংগিতৰ জৰিয়তে ফ\'ন ব্যৱহাৰ কৰিব পাৰে।"</string>
+ <string name="oneMonthDurationPast" msgid="7396384508953779925">"১ মাহ আগত"</string>
+ <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"১ মাহতকৈও আগত"</string>
+ <!-- no translation found for last_num_days (5104533550723932025) -->
+ <string name="last_month" msgid="3959346739979055432">"যোৱা মাহ"</string>
+ <string name="older" msgid="5211975022815554840">"পুৰণি"</string>
+ <string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> তাৰিখে"</string>
+ <string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> বজাত"</string>
+ <string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> চনত"</string>
+ <string name="day" msgid="8144195776058119424">"দিন"</string>
+ <string name="days" msgid="4774547661021344602">"দিনবোৰ"</string>
+ <string name="hour" msgid="2126771916426189481">"ঘণ্টা"</string>
+ <string name="hours" msgid="894424005266852993">"ঘণ্টা"</string>
+ <string name="minute" msgid="9148878657703769868">"মিনিট"</string>
+ <string name="minutes" msgid="5646001005827034509">"কেইমিনিটমান"</string>
+ <string name="second" msgid="3184235808021478">"ছেকেণ্ড"</string>
+ <string name="seconds" msgid="3161515347216589235">"কেইছেকেণ্ডমান"</string>
+ <string name="week" msgid="5617961537173061583">"সপ্তাহ"</string>
+ <string name="weeks" msgid="6509623834583944518">"কেইসপ্তাহমান"</string>
+ <string name="year" msgid="4001118221013892076">"বছৰ"</string>
+ <string name="years" msgid="6881577717993213522">"কেইবছৰমান"</string>
+ <string name="now_string_shortest" msgid="8912796667087856402">"এতিয়া"</string>
+ <plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> মিনিট</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> মিনিট</item>
+ </plurals>
+ <plurals name="duration_hours_shortest" formatted="false" msgid="3552182110578602356">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টা</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টা</item>
+ </plurals>
+ <plurals name="duration_days_shortest" formatted="false" msgid="5213655532597081640">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+ </plurals>
+ <plurals name="duration_years_shortest" formatted="false" msgid="7848711145196397042">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> বছৰ</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> বছৰ</item>
+ </plurals>
+ <plurals name="duration_minutes_shortest_future" formatted="false" msgid="3277614521231489951">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটত</item>
+ </plurals>
+ <plurals name="duration_hours_shortest_future" formatted="false" msgid="2152452368397489370">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাত</item>
+ </plurals>
+ <plurals name="duration_days_shortest_future" formatted="false" msgid="8088331502820295701">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> দিনত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> দিনত</item>
+ </plurals>
+ <plurals name="duration_years_shortest_future" formatted="false" msgid="2317006667145250301">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> বছৰত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> বছৰত</item>
+ </plurals>
+ <plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটৰ আগত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটৰ আগত</item>
+ </plurals>
+ <plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাৰ আগত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাৰ আগত</item>
+ </plurals>
+ <plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> দিন আগত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> দিন আগত</item>
+ </plurals>
+ <plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> বছৰৰ আগতে</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> বছৰৰ আগতে</item>
+ </plurals>
+ <plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> মিনিটত</item>
+ </plurals>
+ <plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টাত</item>
+ </plurals>
+ <plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> দিনত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> দিনত</item>
+ </plurals>
+ <plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> বছৰত</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> বছৰত</item>
+ </plurals>
+ <string name="VideoView_error_title" msgid="3534509135438353077">"ভিডিঅ\'ত সমস্যা আছে"</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"এই ভিডিঅ\'টোক এই ডিভাইচটোত ষ্ট্ৰীমিং কৰিবৰ বাবে মান্য নহয়।"</string>
+ <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"এই ভিডিঅ\' প্লে কৰিব পৰা নাযায়।"</string>
+ <string name="VideoView_error_button" msgid="2822238215100679592">"ঠিক আছে"</string>
+ <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="noon" msgid="7245353528818587908">"দুপৰীয়া"</string>
+ <string name="Noon" msgid="3342127745230013127">"দুপৰীয়া"</string>
+ <string name="midnight" msgid="7166259508850457595">"মাজনিশা"</string>
+ <string name="Midnight" msgid="5630806906897892201">"মাজনিশা"</string>
+ <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
+ <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
+ <string name="selectAll" msgid="6876518925844129331">"সকলো বাছনি কৰক"</string>
+ <string name="cut" msgid="3092569408438626261">"কাটক"</string>
+ <string name="copy" msgid="2681946229533511987">"প্ৰতিলিপি কৰক"</string>
+ <string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"ক্লিপব\'ৰ্ডত প্ৰতিলিপি কৰিব পৰা নগ\'ল"</string>
+ <string name="paste" msgid="5629880836805036433">"পেইষ্ট কৰক"</string>
+ <string name="paste_as_plain_text" msgid="5427792741908010675">"নিকা পাঠ হিচাপে পেইষ্ট কৰক"</string>
+ <string name="replace" msgid="5781686059063148930">"সলনি কৰক…"</string>
+ <string name="delete" msgid="6098684844021697789">"মচক"</string>
+ <string name="copyUrl" msgid="2538211579596067402">"URL প্ৰতিলিপি কৰক"</string>
+ <string name="selectTextMode" msgid="1018691815143165326">"পাঠ বাছনি কৰক"</string>
+ <string name="undo" msgid="7905788502491742328">"আনডু কৰক"</string>
+ <string name="redo" msgid="7759464876566803888">"ৰিডু"</string>
+ <string name="autofill" msgid="3035779615680565188">"স্বয়ংপূৰ্তি"</string>
+ <string name="textSelectionCABTitle" msgid="5236850394370820357">"বাৰ্তা বাছনি"</string>
+ <string name="addToDictionary" msgid="4352161534510057874">"অভিধানত যোগ কৰক"</string>
+ <string name="deleteText" msgid="6979668428458199034">"মচক"</string>
+ <string name="inputMethod" msgid="1653630062304567879">"ইনপুট পদ্ধতি"</string>
+ <string name="editTextMenuTitle" msgid="4909135564941815494">"পাঠ বিষয়ক কাৰ্য"</string>
+ <string name="email" msgid="4560673117055050403">"ইমেইল"</string>
+ <string name="dial" msgid="1253998302767701559">"কল কৰক"</string>
+ <string name="map" msgid="6521159124535543457">"অৱস্থান নিৰূপণ কৰক"</string>
+ <string name="browse" msgid="1245903488306147205">"খোলক"</string>
+ <string name="sms" msgid="4560537514610063430">"বাৰ্তা"</string>
+ <string name="add_contact" msgid="7867066569670597203">"যোগ দিয়ক"</string>
+ <!-- no translation found for view_calendar (979609872939597838) -->
+ <skip />
+ <!-- no translation found for add_calendar_event (1953664627192056206) -->
+ <skip />
+ <!-- no translation found for view_flight (7691640491425680214) -->
+ <skip />
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"সঞ্চয়াগাৰৰ খালী ঠাই শেষ হৈ আছে"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ছিষ্টেমৰ কিছুমান কাৰ্যকলাপে কাম নকৰিবও পাৰে"</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ছিষ্টেমৰ বাবে পৰ্যাপ্ত খালী ঠাই নাই। আপোনাৰ ২৫০এম. বি. খালী ঠাই থকাটো নিশ্চিত কৰক আৰু ৰিষ্টাৰ্ট কৰক।"</string>
+ <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> চলি আছে"</string>
+ <string name="app_running_notification_text" msgid="1197581823314971177">"অধিক তথ্য জানিবলৈ বা এপ বন্ধ কৰিবলৈ টিপক।"</string>
+ <string name="ok" msgid="5970060430562524910">"ঠিক আছে"</string>
+ <string name="cancel" msgid="6442560571259935130">"বাতিল কৰক"</string>
+ <string name="yes" msgid="5362982303337969312">"ঠিক আছে"</string>
+ <string name="no" msgid="5141531044935541497">"বাতিল কৰক"</string>
+ <string name="dialog_alert_title" msgid="2049658708609043103">"মনোযোগ দিব"</string>
+ <string name="loading" msgid="7933681260296021180">"ল\'ড কৰি থকা হৈছে…"</string>
+ <string name="capital_on" msgid="1544682755514494298">"অন কৰক"</string>
+ <string name="capital_off" msgid="6815870386972805832">"অফ কৰক"</string>
+ <string name="whichApplication" msgid="4533185947064773386">"এয়া ব্যৱহাৰ কৰি কার্য সম্পূর্ণ কৰক"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ব্যৱহাৰ কৰি কাৰ্যটো সম্পূৰ্ণ কৰক"</string>
+ <string name="whichApplicationLabel" msgid="7425855495383818784">"কাৰ্য সম্পূৰ্ণ কৰক"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"ইয়াৰ জৰিয়তে খোলক"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$sৰ জৰিয়তে খোলক"</string>
+ <string name="whichViewApplicationLabel" msgid="2666774233008808473">"খোলক"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"ইয়াৰ দ্বাৰা সম্পাদনা কৰক"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sৰদ্বাৰা সম্পাদনা কৰক"</string>
+ <string name="whichEditApplicationLabel" msgid="7183524181625290300">"সম্পাদনা কৰক"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"ইয়াৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$sৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
+ <string name="whichSendApplicationLabel" msgid="4579076294675975354">"শ্বেয়াৰ কৰক"</string>
+ <string name="whichSendToApplication" msgid="8272422260066642057">"ইয়াৰ মাধ্য়মেৰে প্ৰেৰণ কৰক"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ব্য়ৱহাৰ কৰি প্ৰেৰণ কৰক"</string>
+ <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"প্রেৰণ কৰক"</string>
+ <string name="whichHomeApplication" msgid="4307587691506919691">"এটা হ\'ম এপ্ বাছনি কৰক"</string>
+ <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"হ\'ম ৰূপে %1$s ব্যৱহাৰ কৰক"</string>
+ <string name="whichHomeApplicationLabel" msgid="809529747002918649">"প্ৰতিচ্ছবি তোলক"</string>
+ <string name="whichImageCaptureApplication" msgid="3680261417470652882">"ইয়াৰ সৈতে প্ৰতিচ্ছবি তোলক"</string>
+ <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s ৰ সৈতে প্ৰতিচ্ছবি তোলক"</string>
+ <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"প্ৰতিচ্ছবি তোলক"</string>
+ <string name="alwaysUse" msgid="4583018368000610438">"এই কার্যৰ বাবে পূর্বনির্ধাৰিত ধৰণে ব্যৱহাৰ কৰক।"</string>
+ <string name="use_a_different_app" msgid="8134926230585710243">"এটা পৃথক এপ্ ব্যৱহাৰ কৰক"</string>
+ <string name="clearDefaultHintMsg" msgid="3252584689512077257">"ছিষ্টেমৰ ছেটিংসমূহ > এপসমূহ > ডাউনল\'ড কৰা সমল-লৈ গৈ ডিফ\'ল্ট মচক৷"</string>
+ <string name="chooseActivity" msgid="7486876147751803333">"কোনো কার্য বাছনি কৰক"</string>
+ <string name="chooseUsbActivity" msgid="6894748416073583509">"ইউএছবি ডিভাইচৰ বাবে এটা এপ্ বাছনি কৰক"</string>
+ <string name="noApplications" msgid="2991814273936504689">"কোনো এপে এই কাৰ্য কৰিব নোৱাৰে।"</string>
+ <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> বন্ধ হ\'ল"</string>
+ <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> বন্ধ হ\'ল"</string>
+ <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> বাৰে বাৰে বন্ধ হৈ গৈছে"</string>
+ <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> বাৰে বাৰে বন্ধ হৈ গৈছে"</string>
+ <string name="aerr_restart" msgid="7581308074153624475">"আকৌ এপটো খোলক"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"আপোনাৰ প্ৰতিক্ৰিয়া পঠিয়াওক"</string>
+ <string name="aerr_close" msgid="2991640326563991340">"বন্ধ কৰক"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ডিভাইচ ৰিষ্টাৰ্ট নোহোৱালৈ মিউট কৰক"</string>
+ <string name="aerr_wait" msgid="3199956902437040261">"অপেক্ষা কৰক"</string>
+ <string name="aerr_close_app" msgid="3269334853724920302">"এপটো বন্ধ কৰক"</string>
+ <string name="anr_title" msgid="4351948481459135709"></string>
+ <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g>য়ে সঁহাৰি দিয়া নাই"</string>
+ <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g>য়ে সঁহাৰি দিয়া নাই"</string>
+ <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g>য়ে সঁহাৰি দিয়া নাই"</string>
+ <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> প্ৰক্ৰিয়াই সঁহাৰি দিয়া নাই"</string>
+ <string name="force_close" msgid="8346072094521265605">"ঠিক আছে"</string>
+ <string name="report" msgid="4060218260984795706">"অভিযোগ কৰক"</string>
+ <string name="wait" msgid="7147118217226317732">"অপেক্ষা কৰক"</string>
+ <string name="webpage_unresponsive" msgid="3272758351138122503">"এই পৃষ্ঠাই কোনো সহাঁৰি জনোৱা নাই।\n\nআপুনি ইয়াক বন্ধ কৰিব বিচাৰেনে?"</string>
+ <string name="launch_warning_title" msgid="1547997780506713581">"আন এটা এপৰ ওপৰত"</string>
+ <string name="launch_warning_replace" msgid="6202498949970281412">"এতিয়া <xliff:g id="APP_NAME">%1$s</xliff:g> চলি আছে।"</string>
+ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক পূৰ্বতে লঞ্চ কৰা হৈছিল৷"</string>
+ <string name="screen_compat_mode_scale" msgid="3202955667675944499">"স্কেল"</string>
+ <string name="screen_compat_mode_show" msgid="4013878876486655892">"সদায় দেখুৱাওক"</string>
+ <string name="screen_compat_mode_hint" msgid="1064524084543304459">"ছিষ্টেমৰ ছেটিংসমূহ > এপসমূহ > ডাউনল\'ড কৰা সমল-লৈ গৈ ইয়াক আকৌ সক্ষম কৰক।"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বর্তমানৰ ডিছপ্লেৰ আকাৰ ছেটিং ব্যৱহাৰ কৰিব নোৱাৰে আৰু ই সঠিকভাৱে নচলিবও পাৰে।"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"সদায় দেখুৱাওক"</string>
+ <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক এটা খাপ নোখোৱা Android OS সংস্কৰণৰ বাবে তৈয়াৰ কৰা হৈছিল, যাৰ ফলত ই অস্বাভাৱিকধৰণে আচৰণ কৰিব পাৰে। এপটোৰ শেহতীয়া সংস্কৰণ উপলব্ধ হ\'ব পাৰে।"</string>
+ <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"সদায় দেখুৱাওক"</string>
+ <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"আপডেট আছে নেকি চাওক"</string>
+ <string name="smv_application" msgid="3307209192155442829">"এপটোৱে <xliff:g id="APPLICATION">%1$s</xliff:g> (প্ৰক্ৰিয়াটোৱে <xliff:g id="PROCESS">%2$s</xliff:g>) নিজে বলবৎ কৰা StrictMode নীতি ভংগ কৰিলে।"</string>
+ <string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> প্ৰক্ৰিয়াটোৱে নিজে বলৱৎ কৰা StrictMode নীতি ভংগ কৰিলে।"</string>
+ <!-- no translation found for android_upgrading_title (7513829952443484438) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (4503169817302593560) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (7009520271220804517) -->
+ <skip />
+ <!-- no translation found for android_start_title (4536778526365907780) -->
+ <skip />
+ <!-- no translation found for android_start_title (4929837533850340472) -->
+ <skip />
+ <!-- no translation found for android_start_title (7467484093260449437) -->
+ <skip />
+ <string name="android_upgrading_fstrim" msgid="8036718871534640010">"সঞ্চয়াগাৰ অপ্টিমাইজ কৰি থকা হৈছে।"</string>
+ <!-- no translation found for android_upgrading_notification_title (1511552415039349062) -->
+ <skip />
+ <string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক আপগ্ৰেড কৰি থকা হৈছে…"</string>
+ <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ৰ ভিতৰত <xliff:g id="NUMBER_0">%1$d</xliff:g> এপ্ অপ্টিমাইজ কৰি থকা হৈছে৷"</string>
+ <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+ <skip />
+ <string name="android_upgrading_starting_apps" msgid="451464516346926713">"আৰম্ভ হৈ থকা এপসমূহ।"</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"বুট কাৰ্য সমাপ্ত কৰিছে।"</string>
+ <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string>
+ <!-- no translation found for heavy_weight_notification_detail (2304833848484424985) -->
+ <skip />
+ <!-- no translation found for heavy_weight_switcher_title (387882830435195342) -->
+ <skip />
+ <!-- no translation found for heavy_weight_switcher_text (4176781660362912010) -->
+ <skip />
+ <!-- no translation found for old_app_action (3044685170829526403) -->
+ <skip />
+ <!-- no translation found for new_app_action (6694851182870774403) -->
+ <skip />
+ <!-- no translation found for new_app_description (5894852887817332322) -->
+ <skip />
+ <!-- no translation found for dump_heap_notification (2618183274836056542) -->
+ <skip />
+ <string name="dump_heap_notification_detail" msgid="6901391084243999274">"হীপ ডাম্প সংগ্ৰহ কৰা হ\'ল। শ্বেয়াৰ কৰিবলৈ টিপক"</string>
+ <!-- no translation found for dump_heap_title (5864292264307651673) -->
+ <skip />
+ <!-- no translation found for dump_heap_text (4809417337240334941) -->
+ <skip />
+ <string name="sendText" msgid="5209874571959469142">"বার্তাৰ বাবে কাৰ্য বাছনি কৰক"</string>
+ <string name="volume_ringtone" msgid="6885421406845734650">"ৰিংগাৰৰ ধ্বনি"</string>
+ <string name="volume_music" msgid="5421651157138628171">"মিডিয়াৰ ধ্বনি"</string>
+ <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"ব্লুটুথৰ জৰিয়তে প্লে কৰি থকা হৈছে"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"ৰিংট\'ন নিৰৱ ম\'ডত ছেট কৰা আছে"</string>
+ <string name="volume_call" msgid="3941680041282788711">"কলৰ সময়ত ধ্বনিৰ মাত্ৰা"</string>
+ <string name="volume_bluetooth_call" msgid="2002891926351151534">"ব্লুটুথৰ যোগেৰে কৰা কলৰ সময়ত ধ্বনিৰ মাত্ৰা"</string>
+ <string name="volume_alarm" msgid="1985191616042689100">"এলার্মৰ ধ্বনি"</string>
+ <string name="volume_notification" msgid="2422265656744276715">"জাননীৰ ধ্বনি"</string>
+ <string name="volume_unknown" msgid="1400219669770445902">"ধ্বনি"</string>
+ <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ব্লুটুথৰ ভলিউম"</string>
+ <string name="volume_icon_description_ringer" msgid="3326003847006162496">"ৰিংট\'নৰ ধ্বনি"</string>
+ <string name="volume_icon_description_incall" msgid="8890073218154543397">"কলৰ ভলিউম"</string>
+ <string name="volume_icon_description_media" msgid="4217311719665194215">"মিডিয়াৰ ভলিউম"</string>
+ <string name="volume_icon_description_notification" msgid="7044986546477282274">"জাননীৰ ধ্বনি"</string>
+ <string name="ringtone_default" msgid="3789758980357696936">"পূর্বনিধার্ৰিত ৰিংট\'ন"</string>
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ডিফ\'ল্ট (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_silent" msgid="7937634392408977062">"একো নাই"</string>
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"ৰিংট\'নসমূহ"</string>
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"এলার্মৰ ধ্বনিসমূহ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"জাননীৰ ধ্বনিসমূহ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"অজ্ঞাত"</string>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">ৱাই-ফাই নেটৱর্ক উপলব্ধ</item>
+ <item quantity="other">ৱাই-ফাই নেটৱর্ক উপলব্ধ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">পাছৱৰ্ড অবিহনে সংযোগ কৰিব পৰা ৱাই-ফাই নেটৱর্ক উপলব্ধ</item>
+ <item quantity="other">পাছৱৰ্ড অবিহনে সংযোগ কৰিব পৰা ৱাই-ফাই নেটৱর্ক উপলব্ধ</item>
+ </plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"পাছৱৰ্ড অবিহনে সংযোগ কৰিবপৰা ৱাই-ফাই নেটৱর্কৰ সৈতে সংযোগ কৰক"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"পাছৱৰ্ড অবিহনে সংযোগ কৰিবপৰা ৱাই-ফাই নেটৱর্কৰ সৈতে সংযোগ কৰি থকা হৈছে"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"ৱাই-ফাই নেটৱৰ্কৰ সৈতে সংযোগ কৰা হ\'ল"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ৱাই-ফাই নেটৱৰ্কৰ সৈতে সংযোগ কৰিবপৰা নগ\'ল"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"সকলো নেটৱৰ্ক চাবলৈ টিপক"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"সংযোগ কৰক"</string>
+ <!-- no translation found for wifi_available_action_all_networks (4368435796357931006) -->
+ <skip />
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ৱাই-ফাই স্বয়ংক্ৰিয়ভাৱে অন হ\'ব"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"যেতিয়া আপুনি ছেভ কৰি থোৱা উচ্চ মানৰ নেটৱৰ্কৰ কাষত থাকে"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"পুনৰাই অন নকৰিব"</string>
+ <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+ <skip />
+ <string name="wifi_available_sign_in" msgid="9157196203958866662">"ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক"</string>
+ <!-- no translation found for network_available_sign_in (1848877297365446605) -->
+ <skip />
+ <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
+ <skip />
+ <string name="wifi_no_internet" msgid="8938267198124654938">"ৱাই-ফাইত ইন্টাৰনেট নাই"</string>
+ <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"অধিক বিকল্পৰ বাবে টিপক"</string>
+ <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>লৈ সলনি কৰা হ\'ল"</string>
+ <string name="network_switch_metered_detail" msgid="775163331794506615">"যেতিয়া <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>ত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।"</string>
+ <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>ৰ পৰা <xliff:g id="NEW_NETWORK">%2$s</xliff:g> লৈ সলনি কৰা হ\'ল"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="3979506840912951943">"ম\'বাইল ডেটা"</item>
+ <item msgid="75483255295529161">"ৱাই-ফাই"</item>
+ <item msgid="6862614801537202646">"ব্লুটুথ"</item>
+ <item msgid="5447331121797802871">"ইথাৰনেট"</item>
+ <item msgid="8257233890381651999">"ভিপিএন"</item>
+ </string-array>
+ <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক"</string>
+ <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ৱাই-ফাইৰ লগত সংযোগ কৰিব পৰা নগ\'ল"</string>
+ <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ইণ্টাৰনেট সংযোগ যথেষ্ট দুর্বল।"</string>
+ <string name="wifi_connect_alert_title" msgid="8455846016001810172">"সংযোগ কৰাৰ অনুমতি দিবনে?"</string>
+ <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+ <skip />
+ <string name="wifi_connect_default_application" msgid="7143109390475484319">"এপ্লিকেশ্বন"</string>
+ <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"ৱাই-ফাই ডাইৰেক্ট"</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ৱাই-ফাই ডাইৰেক্ট আৰম্ভ কৰক। এই কার্যই ৱাই-ফাই ক্লাইণ্ট/হ\'টস্প\'ট অফ কৰিব।"</string>
+ <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"ৱাই-ফাই ডাইৰেক্ট আৰম্ভ কৰিব পৰা নগ\'ল।"</string>
+ <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"ৱাই-ফাই ডাইৰেক্ট অন হৈ আছে"</string>
+ <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"ছেটিংসমূহৰ বাবে টিপক"</string>
+ <string name="accept" msgid="1645267259272829559">"স্বীকাৰ কৰক"</string>
+ <string name="decline" msgid="2112225451706137894">"প্ৰত্যাখ্যান কৰক"</string>
+ <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"আমন্ত্ৰণ পঠোৱা হ\'ল"</string>
+ <string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"সংযোগ হ\'বলৈ আমন্ত্ৰণ"</string>
+ <string name="wifi_p2p_from_message" msgid="570389174731951769">"প্ৰেৰক:"</string>
+ <string name="wifi_p2p_to_message" msgid="248968974522044099">"প্ৰতি:"</string>
+ <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"প্ৰয়োজনীয় পিন নম্বৰটো লিখক:"</string>
+ <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"পিন:"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"টি.ভি.টো <xliff:g id="DEVICE_NAME">%1$s</xliff:g> লৈ সংযোগ হৈ থকাৰ অৱস্থাত অস্থায়ীভাৱে ৱাই-ফাইৰ পৰা সংযোগ বিচ্ছিন্ন হ\'ব"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"টিভিটো <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ লগত সংযোগ হ\'লে সাময়িকভাৱে ৱাই-ফাইৰ পৰা সংযোগ বিচ্ছিন্ন হ\'ব"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ফ\'নটো <xliff:g id="DEVICE_NAME">%1$s</xliff:g> লৈ সংযোগ হ\'লে ৱাই-ফাইৰ পৰা কিছু সময়ৰ বাবে সংযোগ স্বীকাৰ বিচ্ছিন্ন হ\'ব"</string>
+ <string name="select_character" msgid="3365550120617701745">"বর্ণ লিখক"</string>
+ <string name="sms_control_title" msgid="7296612781128917719">"এছএমএছ বার্তাবোৰ পঠিয়াই থকা হৈছে"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> এ বহু সংখ্যক এছএমএছ বার্তাবোৰ প্ৰেৰণ কৰি আছে। আপুনি এই এপে বার্তা প্ৰেৰণ কৰি থকাটো বিচাৰেনে?"</string>
+ <string name="sms_control_yes" msgid="3663725993855816807">"অনুমতি দিয়ক"</string>
+ <string name="sms_control_no" msgid="625438561395534982">"অস্বীকাৰ কৰক"</string>
+ <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<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="5873295990846059400">"ইয়াৰ বাবে "<b>" মাছুল ভৰিবলগীয়া হ\'ব পাৰে"</b>"।"</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"ইয়াৰ বাবে মাছুল ভৰিবলগীয়া হ\'ব পাৰে।"</b></string>
+ <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"পঠিয়াওক"</string>
+ <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"বাতিল কৰক"</string>
+ <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"মোৰ পচন্দ মনত ৰাখিব"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"আপুনি ইয়াক পিছত ছেটিং > এপ্-ত সলনি কৰিব পাৰে"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"যিকোনো সময়ত অনুমতি দিয়ক"</string>
+ <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"কেতিয়াও অনুমতি নিদিব"</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"ছিম কাৰ্ড আঁতৰোৱা হ\'ল"</string>
+ <string name="sim_removed_message" msgid="2333164559970958645">"এখন মান্য ছিম কার্ড ব্যৱহাৰ কৰি ৰিষ্টার্ট নকৰা পর্যন্ত ম\'বাইলৰ নেটৱর্ক উপলব্ধ নহয়।"</string>
+ <string name="sim_done_button" msgid="827949989369963775">"সম্পন্ন হ\'ল"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"ছিম কাৰ্ড যোগ কৰা হ\'ল"</string>
+ <string name="sim_added_message" msgid="6599945301141050216">"ম\'বাইলৰ নেটৱর্ক ব্যৱহাৰ কৰিবলৈ আপোনাৰ ডিভাইচটো ৰিষ্টার্ট কৰক।"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"ৰিষ্টাৰ্ট কৰক"</string>
+ <!-- no translation found for install_carrier_app_notification_title (9056007111024059888) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_text (3346681446158696001) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_text_app_name (1196505084835248137) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_button (3094206295081900849) -->
+ <skip />
+ <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন ছিম ভৰোৱা হৈছে"</string>
+ <string name="carrier_app_notification_text" msgid="1132487343346050225">"ছেট আপ কৰিবলৈ টিপক"</string>
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"সময় ছেট কৰক"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"তাৰিখ ছেট কৰক"</string>
+ <string name="date_time_set" msgid="5777075614321087758">"ছেট কৰক"</string>
+ <string name="date_time_done" msgid="2507683751759308828">"সম্পন্ন হ\'ল"</string>
+ <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"নতুন: "</font></string>
+ <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ প্ৰদান কৰা"</string>
+ <string name="no_permissions" msgid="7283357728219338112">"কোনো অনুমতিৰ প্ৰয়োজন নাই"</string>
+ <string name="perm_costs_money" msgid="4902470324142151116">"ইয়াৰ ফলত আপোনাৰ টকা খৰচ হ\'ব পাৰে"</string>
+ <string name="dlg_ok" msgid="7376953167039865701">"ঠিক আছে"</string>
+ <!-- no translation found for usb_charging_notification_title (1595122345358177163) -->
+ <skip />
+ <!-- no translation found for usb_supplying_notification_title (4631045789893086181) -->
+ <skip />
+ <!-- no translation found for usb_mtp_notification_title (4238227258391151029) -->
+ <skip />
+ <!-- no translation found for usb_ptp_notification_title (5425857879922006878) -->
+ <skip />
+ <!-- no translation found for usb_tether_notification_title (3716143122035802501) -->
+ <skip />
+ <!-- no translation found for usb_midi_notification_title (5356040379749154805) -->
+ <skip />
+ <!-- no translation found for usb_accessory_notification_title (1899977434994900306) -->
+ <skip />
+ <string name="usb_notification_message" msgid="3370903770828407960">"অধিক বিকল্পৰ বাবে টিপক।"</string>
+ <!-- no translation found for usb_power_notification_message (4647527153291917218) -->
+ <skip />
+ <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"এনাল\'গ অডিঅ\' সহায়ক সামগ্ৰী পোৱা গৈছে"</string>
+ <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"সংলগ্ন কৰা ডিভাইচটোৱে এই ফ\'নটোৰ সৈতে কাম কৰিব নোৱাৰে। অধিক জানিবলৈ টিপক।"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"ইউএছবি ডিবাগিং সংযোগ কৰা হ\'ল"</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"ইউএছবি ডিবাগিং অক্ষম কৰিবলৈ টিপক।"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"ইউএছবি ডিবাগিং অক্ষম কৰিবলৈ বাছনি কৰক।"</string>
+ <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"বাগ সম্পর্কীয় অভিযোগ গ্ৰহণ কৰি থকা হৈছে…"</string>
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিবনে?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰি থকা হৈছে…"</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"আপোনাৰ প্ৰশাসকে এই ডিভাইচটোৰ সমস্যা সমাধানৰ বাবে বাগ সম্পৰ্কীয় অভিযোগ বিচাৰিছে। এপ্ আৰু ডেটা শ্বেয়াৰ কৰা হ\'ব পাৰে।"</string>
+ <string name="share_remote_bugreport_action" msgid="6249476773913384948">"শ্বেয়াৰ কৰক"</string>
+ <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"প্ৰত্যাখ্যান কৰক"</string>
+ <string name="select_input_method" msgid="8547250819326693584">"কীব\'ৰ্ড সলনি কৰক"</string>
+ <string name="show_ime" msgid="2506087537466597099">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীণত ৰাখিব"</string>
+ <string name="hardware" msgid="194658061510127999">"ভাৰ্শ্বুৱল কীব\'ৰ্ড দেখুৱাওক"</string>
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"কায়িক কীব’ৰ্ড কনফিগাৰ কৰক"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা আৰু চানেকি বাছনি কৰিবলৈ ইয়াত টিপক"</string>
+ <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"অন্য এপৰ ওপৰত দেখুৱায়"</string>
+ <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> অন্য এপসমূহৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>এ অইন এপবোৰৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string>
+ <string name="alert_windows_notification_message" msgid="8917232109522912560">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g>এ এই সুবিধাটো ব্যৱহাৰ কৰাটো নিবিচাৰে তেন্তে টিপি ছেটিংসমূহ খোলক আৰু ইয়াক অফ কৰক।"</string>
+ <!-- no translation found for alert_windows_notification_turn_off_action (2902891971380544651) -->
+ <skip />
+ <!-- no translation found for ext_media_checking_notification_title (5734005953288045806) -->
+ <skip />
+ <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"আসোঁৱাহ বিচাৰি থকা হৈছে"</string>
+ <!-- no translation found for ext_media_new_notification_message (7589986898808506239) -->
+ <skip />
+ <!-- no translation found for ext_media_ready_notification_message (4083398150380114462) -->
+ <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"<xliff:g id="NAME">%s</xliff:g> ব্যৱহাৰযোগ্য নহয়"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> ব্যৱহাৰযোগ্য নহয়। সমস্যাটো সমাধান কৰিবলৈ টিপক।"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ব্যৱহাৰযোগ্য হৈ থকা নাই। ঠিক কৰিবলৈ বাছনি কৰক।"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰি"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰে। ব্যৱহাৰ কৰিব পৰা ফৰ্মেটত ছেট আপ কৰিবলৈ টিপক।"</string>
+ <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক চলাব নোৱাৰে। চলাব পৰা কোনো ফৰ্মেটত ছেট আপ কৰিবলৈ বাছনি কৰক।"</string>
+ <!-- no translation found for ext_media_badremoval_notification_title (3206248947375505416) -->
+ <skip />
+ <!-- no translation found for ext_media_badremoval_notification_message (380176703346946313) -->
+ <skip />
+ <!-- no translation found for ext_media_nomedia_notification_title (1704840188641749091) -->
+ <skip />
+ <!-- no translation found for ext_media_nomedia_notification_message (6471542972147056586) -->
+ <skip />
+ <!-- no translation found for ext_media_unmounting_notification_title (640674168454809372) -->
+ <skip />
+ <!-- no translation found for ext_media_unmounting_notification_message (4182843895023357756) -->
+ <skip />
+ <string name="ext_media_init_action" msgid="7952885510091978278">"ছেট আপ কৰক"</string>
+ <!-- no translation found for ext_media_unmount_action (1121883233103278199) -->
+ <skip />
+ <!-- no translation found for ext_media_browse_action (8322172381028546087) -->
+ <skip />
+ <!-- no translation found for ext_media_missing_title (620980315821543904) -->
+ <skip />
+ <!-- no translation found for ext_media_missing_message (5761133583368750174) -->
+ <skip />
+ <!-- no translation found for ext_media_move_specific_title (1471100343872375842) -->
+ <skip />
+ <!-- no translation found for ext_media_move_title (1022809140035962662) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_title (8575300932957954671) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_message (4199002148206265426) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_title (7613189040358789908) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_message (1978096440816403360) -->
+ <skip />
+ <string name="ext_media_status_removed" msgid="6576172423185918739">"আঁতৰোৱা হ\'ল"</string>
+ <string name="ext_media_status_unmounted" msgid="2551560878416417752">"বাহিৰলৈ উলিওৱা হ\'ল"</string>
+ <string name="ext_media_status_checking" msgid="6193921557423194949">"পৰীক্ষা কৰি থকা হৈছে…"</string>
+ <string name="ext_media_status_mounted" msgid="7253821726503179202">"সাজু"</string>
+ <string name="ext_media_status_mounted_ro" msgid="8020978752406021015">"ৰীড-অনলি"</string>
+ <string name="ext_media_status_bad_removal" msgid="8395398567890329422">"বিপজ্জনকভাৱে আঁতৰোৱা হ\'ল"</string>
+ <string name="ext_media_status_unmountable" msgid="805594039236667894">"ব্যৱহাৰযোগ্য নহয়"</string>
+ <string name="ext_media_status_unsupported" msgid="4691436711745681828">"সঞ্চয়াগাৰ ব্যৱহাৰ কৰিব নোৱাৰি"</string>
+ <string name="ext_media_status_ejecting" msgid="5463887263101234174">"বাহিৰলৈ উলিয়াই থকা হৈছে…"</string>
+ <string name="ext_media_status_formatting" msgid="1085079556538644861">"ফৰ্মেট কৰি থকা হৈছে…"</string>
+ <string name="ext_media_status_missing" msgid="5638633895221670766">"ভৰোৱা নাই"</string>
+ <string name="activity_list_empty" msgid="1675388330786841066">"কোনো মিলা কাৰ্যকলাপ পোৱা নগ\'ল।"</string>
+ <string name="permlab_route_media_output" msgid="6243022988998972085">"মিডিয়াৰ আউটপুট ৰাউট কৰিব পাৰে"</string>
+ <string name="permdesc_route_media_output" msgid="4932818749547244346">"অন্য় বাহ্যিক ডিভাইচবোৰলৈ মিডিয়া আউটপুট প্ৰেৰণ কৰিবলৈ এপ্লিকেশ্বনক অনুমতি দিয়ে।"</string>
+ <string name="permlab_readInstallSessions" msgid="3713753067455750349">"ইনষ্টল কৰা ছেশ্বনসমূহ পঢ়িব পাৰে"</string>
+ <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"এটা এপ্লিকেশ্বনক ইনষ্টল কৰা ছেশ্বনসমূহ পঢ়িবলৈ অনুমতি দিয়ে। এই কাৰ্যই সক্ৰিয় পেকেজ ইনষ্টলেশ্বনৰ বিষয়ে চাবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"পেকেজ ইনষ্টলৰ বাবে অনুৰোধ কৰিব পাৰে"</string>
+ <!-- no translation found for permdesc_requestInstallPackages (5740101072486783082) -->
+ <skip />
+ <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"পেকেজ মচাৰ অনুৰোধ কৰিব পাৰে"</string>
+ <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"এপটোক পেকেজবোৰ মচাৰ অনুৰোধ কৰিবলৈ দিয়ে।"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ বিচাৰক"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"কোনো এপক সেই এপটোৰ বাবে বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ অনুমতি বিচাৰিবলৈ দিয়ে।"</string>
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্ৰণ কৰিবলৈ দুবাৰ টিপক"</string>
+ <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ৱিজেট যোগ কৰিব পৰা নগ\'ল।"</string>
+ <string name="ime_action_go" msgid="8320845651737369027">"যাওক"</string>
+ <string name="ime_action_search" msgid="658110271822807811">"অনুসন্ধান কৰক"</string>
+ <string name="ime_action_send" msgid="2316166556349314424">"পঠিয়াওক"</string>
+ <string name="ime_action_next" msgid="3138843904009813834">"পৰৱৰ্তী"</string>
+ <string name="ime_action_done" msgid="8971516117910934605">"সম্পন্ন হ\'ল"</string>
+ <string name="ime_action_previous" msgid="1443550039250105948">"আগৰ"</string>
+ <string name="ime_action_default" msgid="2840921885558045721">"কার্য কৰক"</string>
+ <string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g> ব্যৱহাৰ কৰি \n নম্বৰটো ডায়েল কৰক"</string>
+ <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g> ব্যৱহাৰ কৰি সম্পৰ্ক \n সৃষ্টি কৰক"</string>
+ <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"বৰ্তমান আৰু ভৱিষ্যতে আপোনাৰ একাউণ্টত প্ৰৱেশ কৰিবলৈ তলৰ এটা বা অধিক এপে অনুমতি লাভৰ বাবে অনুৰোধ কৰিছে৷"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"আপুনি এই অনুৰোধক সন্মতি দিব বিচাৰেনে?"</string>
+ <string name="grant_permissions_header_text" msgid="6874497408201826708">"ব্য়ৱহাৰ কৰাৰ অনুমতি বিচাৰি কৰা অনুৰোধ"</string>
+ <string name="allow" msgid="7225948811296386551">"অনুমতি দিয়ক"</string>
+ <string name="deny" msgid="2081879885755434506">"প্ৰত্যাখ্যান কৰক"</string>
+ <string name="permission_request_notification_title" msgid="6486759795926237907">"অনুমতি বিচাৰি অনুৰোধ কৰা হৈছে"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"<xliff:g id="ACCOUNT">%s</xliff:g> একাউণ্টৰ বাবে\nঅনুমতি বিচাৰি অনুৰোধ কৰা হৈছে।"</string>
+ <string name="forward_intent_to_owner" msgid="1207197447013960896">"আপুনি আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলৰ বাহিৰত এই এপটো ব্যৱহাৰ কৰি আছে"</string>
+ <string name="forward_intent_to_work" msgid="621480743856004612">"আপুনি আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলৰ ভিতৰত এই এপটো ব্যৱহাৰ কৰি আছে"</string>
+ <string name="input_method_binding_label" msgid="1283557179944992649">"ইনপুট পদ্ধতি"</string>
+ <string name="sync_binding_label" msgid="3687969138375092423">"ছিংক"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"দিব্যাংগসকলৰ বাবে থকা সুবিধাসমূহ"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"ৱালপেপাৰ"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"ৱালপেপাৰ সলনি কৰক"</string>
+ <string name="notification_listener_binding_label" msgid="2014162835481906429">"জাননী নিৰীক্ষক"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR শ্ৰোতা"</string>
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"অৱস্থা প্ৰদানকাৰী"</string>
+ <string name="notification_ranker_binding_label" msgid="774540592299064747">"জাননীৰ স্তৰ নিৰ্দ্ধাৰক সেৱা"</string>
+ <string name="vpn_title" msgid="19615213552042827">"ভিপিএন সক্ৰিয় কৰা হৈছে"</string>
+ <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>এ ভিপিএন সক্ৰিয় কৰিলে"</string>
+ <string name="vpn_text" msgid="1610714069627824309">"নেটৱর্ক পৰিচালনা কৰিবলৈ টিপক।"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>ৰ সৈতে সংযোগ হৈছে। নেটৱর্ক পৰিচালনা কৰিবলৈ টিপক।"</string>
+ <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"সদা-সক্ৰিয় ভিপিএন সংযোগ কৰি থকা হৈছে…"</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"সদা-সক্ৰিয় ভিপিএন সংযোগ কৰা হ\'ল"</string>
+ <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"সদা-সক্ৰিয় ভিপিএনৰ লগত সংযোগ বিচ্ছিন্ন কৰা হৈছে"</string>
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"সদা-সক্ৰিয় ভিপিএনত আসোঁৱাহ"</string>
+ <string name="vpn_lockdown_config" msgid="8151951501116759194">"নেটৱৰ্ক বা ভিপিএন ছেটিংসমূহ সলনি কৰক"</string>
+ <string name="upload_file" msgid="2897957172366730416">"ফাইল বাছনি কৰক"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"কোনো ফাইল বাছনি কৰা হোৱা নাই"</string>
+ <string name="reset" msgid="2448168080964209908">"ৰিছেট কৰক"</string>
+ <string name="submit" msgid="1602335572089911941">"দাখিল কৰক"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"গাড়ীৰ ম’ড সক্ষম কৰা হ\'ল"</string>
+ <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"গাড়ীৰ ম\'ডৰ পৰা বাহিৰ হ\'বলৈ টিপক।"</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"টেডাৰিং বা হটস্প\'ট সক্ৰিয় অৱস্থাত আছে"</string>
+ <string name="tethered_notification_message" msgid="2113628520792055377">"ছেট আপ কৰিবলৈ টিপক।"</string>
+ <string name="disable_tether_notification_title" msgid="7526977944111313195">"টেডাৰিং অক্ষম কৰি থোৱা হৈছে"</string>
+ <string name="disable_tether_notification_message" msgid="2913366428516852495">"সবিশেষ জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক"</string>
+ <string name="back_button_label" msgid="2300470004503343439">"উভতি যাওক"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"পৰৱৰ্তী"</string>
+ <string name="skip_button_label" msgid="1275362299471631819">"এৰি যাওক"</string>
+ <string name="no_matches" msgid="8129421908915840737">"কোনো মিল নাই"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"পৃষ্ঠাত বিচাৰক"</string>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g>ৰ <xliff:g id="INDEX">%d</xliff:g>টা</item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>ৰ <xliff:g id="INDEX">%d</xliff:g>টা</item>
+ </plurals>
+ <string name="action_mode_done" msgid="7217581640461922289">"সম্পন্ন হ\'ল"</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"ইউএছবি সঞ্চয়াগাৰৰ ডেটা মচি থকা হৈছে…"</string>
+ <string name="progress_erasing" product="default" msgid="6596988875507043042">"এছডি কাৰ্ডৰ ডেটা মচি থকা হৈছে…"</string>
+ <string name="share" msgid="1778686618230011964">"শ্বেয়াৰ কৰক"</string>
+ <string name="find" msgid="4808270900322985960">"বিচাৰক"</string>
+ <string name="websearch" msgid="4337157977400211589">"ৱেবত সন্ধান কৰক"</string>
+ <string name="find_next" msgid="5742124618942193978">"পৰৱৰ্তী বস্তু বিচাৰক"</string>
+ <string name="find_previous" msgid="2196723669388360506">"আগৰটো বিচাৰক"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>ৰ পৰা অৱস্থানৰ অনুৰোধ কৰা হৈছে"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"অৱস্থানৰ অনুৰোধ"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)এ অনুৰোধ কৰিছে"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"হয়"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"নহয়"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"মচি পেলোৱাৰ সীমা পাৰ হ\'ল"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"এই <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> ৰ মচি থোৱা <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> টা <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> বস্তু আছে। আপুনি কি কৰিব বিচাৰে?"</string>
+ <string name="sync_really_delete" msgid="2572600103122596243">"বস্তুবোৰ মচক"</string>
+ <string name="sync_undo_deletes" msgid="2941317360600338602">"মচা কাৰ্যক আনডু কৰক"</string>
+ <string name="sync_do_nothing" msgid="3743764740430821845">"এতিয়া একো নকৰিব"</string>
+ <string name="choose_account_label" msgid="5655203089746423927">"একাউণ্ট বাছনি কৰক"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"একাউণ্ট যোগ কৰক"</string>
+ <string name="add_account_button_label" msgid="3611982894853435874">"একাউণ্ট যোগ কৰক"</string>
+ <string name="number_picker_increment_button" msgid="2412072272832284313">"বৃদ্ধি কৰক"</string>
+ <string name="number_picker_decrement_button" msgid="476050778386779067">"হ্ৰাস কৰক"</string>
+ <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> স্পর্শ কৰক আৰু হেঁচি ধৰক।"</string>
+ <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"বৃদ্ধি কৰিবলৈ ওপৰলৈ আৰু হ্ৰাস কৰিবলৈ তললৈ শ্লাইড কৰক।"</string>
+ <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"মিনিট বৃদ্ধি কৰক"</string>
+ <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"মিনিট হ্ৰাস কৰক"</string>
+ <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"ঘণ্টা বৃদ্ধি কৰক"</string>
+ <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ঘণ্টা হ্ৰাস কৰক"</string>
+ <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"অপৰাহ্ন ছেট কৰক"</string>
+ <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"পূৰ্বাহ্ন ছেট কৰক"</string>
+ <string name="date_picker_increment_month_button" msgid="5369998479067934110">"মাহ বৃদ্ধি কৰক"</string>
+ <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"মাহ হ্ৰাস কৰক"</string>
+ <string name="date_picker_increment_day_button" msgid="7130465412308173903">"দিন বৃদ্ধি কৰক"</string>
+ <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"দিন হ্ৰাস কৰক"</string>
+ <string name="date_picker_increment_year_button" msgid="6318697384310808899">"বছৰ বৃদ্ধি কৰক"</string>
+ <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"বছৰ হ্ৰাস কৰক"</string>
+ <!-- no translation found for date_picker_prev_month_button (2858244643992056505) -->
+ <skip />
+ <!-- no translation found for date_picker_next_month_button (5559507736887605055) -->
+ <skip />
+ <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
+ <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"বাতিল কৰক"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"মচক"</string>
+ <string name="keyboardview_keycode_done" msgid="1992571118466679775">"সম্পন্ন হ\'ল"</string>
+ <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ম\'ড সলনি"</string>
+ <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"শ্বিফ্ট"</string>
+ <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"এণ্টাৰ"</string>
+ <string name="activitychooserview_choose_application" msgid="2125168057199941199">"এটা এপ্ বাছনি কৰক"</string>
+ <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> লঞ্চ কৰিব পৰা নগ\'ল"</string>
+ <string name="shareactionprovider_share_with" msgid="806688056141131819">"ইয়াৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
+ <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>ৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
+ <string name="content_description_sliding_handle" msgid="415975056159262248">"শ্লাইড কৰা হেণ্ডেল৷ স্পৰ্শ কৰক আৰু ধৰি ৰাখক৷"</string>
+ <string name="description_target_unlock_tablet" msgid="3833195335629795055">"স্ক্ৰীণ আনলক কৰিবলৈ ছোৱাইপ কৰক৷"</string>
+ <string name="action_bar_home_description" msgid="5293600496601490216">"গৃহ পৃষ্ঠালৈ যাওক"</string>
+ <string name="action_bar_up_description" msgid="2237496562952152589">"ওপৰলৈ যাওক"</string>
+ <string name="action_menu_overflow_description" msgid="2295659037509008453">"অধিক বিকল্প"</string>
+ <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s: %2$s"</string>
+ <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"শ্বেয়াৰ কৰা আভ্যন্তৰীণ সঞ্চয়াগাৰ"</string>
+ <string name="storage_sd_card" msgid="3282948861378286745">"এছডি কাৰ্ড"</string>
+ <!-- no translation found for storage_sd_card_label (6347111320774379257) -->
+ <skip />
+ <!-- no translation found for storage_usb_drive (6261899683292244209) -->
+ <skip />
+ <!-- no translation found for storage_usb_drive_label (4501418548927759953) -->
+ <skip />
+ <string name="storage_usb" msgid="3017954059538517278">"ইউএছবি সঞ্চয়াগাৰ"</string>
+ <string name="extract_edit_menu_button" msgid="8940478730496610137">"সম্পাদনা কৰক"</string>
+ <!-- no translation found for data_usage_warning_title (6499834033204801605) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (7340198905103751676) -->
+ <skip />
+ <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"ম\'বাইল ডেটা ব্যৱাহৰৰ সীমা শেষ হৈছে"</string>
+ <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"ৱাই-ফাই ডেটাৰ সীমাত উপনীত হৈছে"</string>
+ <!-- no translation found for data_usage_limit_body (2908179506560812973) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_snoozed_title (3171402244827034372) -->
+ <skip />
+ <!-- no translation found for data_usage_wifi_limit_snoozed_title (3547771791046344188) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_snoozed_body (1671222777207603301) -->
+ <skip />
+ <string name="data_usage_restricted_title" msgid="5965157361036321914">"নেপথ্য ডেটা সীমিত কৰি ৰখা হৈছে৷"</string>
+ <string name="data_usage_restricted_body" msgid="469866376337242726">"সীমাবদ্ধতা আঁতৰাবলৈ টিপক।"</string>
+ <!-- no translation found for data_usage_rapid_title (1809795402975261331) -->
+ <skip />
+ <!-- no translation found for data_usage_rapid_body (6897825788682442715) -->
+ <skip />
+ <!-- no translation found for data_usage_rapid_app_body (5396680996784142544) -->
+ <skip />
+ <string name="ssl_certificate" msgid="6510040486049237639">"নিৰাপত্তা সম্পৰ্কীয় প্ৰমাণপত্ৰ"</string>
+ <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"এই প্ৰমাণপত্ৰখন মান্য৷"</string>
+ <string name="issued_to" msgid="454239480274921032">"প্ৰদান কৰা হৈছে:"</string>
+ <string name="common_name" msgid="2233209299434172646">"সাধাৰণ নাম:"</string>
+ <string name="org_name" msgid="6973561190762085236">"সংস্থা:"</string>
+ <string name="org_unit" msgid="7265981890422070383">"সংস্থাৰ গোট:"</string>
+ <string name="issued_by" msgid="2647584988057481566">"এয়া প্ৰদান কৰে:"</string>
+ <string name="validity_period" msgid="8818886137545983110">"মান্যতা:"</string>
+ <string name="issued_on" msgid="5895017404361397232">"প্ৰদান কৰা সময়:"</string>
+ <string name="expires_on" msgid="3676242949915959821">"ম্যাদ উকলিব:"</string>
+ <string name="serial_number" msgid="758814067660862493">"ক্ৰমিক নম্বৰ:"</string>
+ <string name="fingerprints" msgid="4516019619850763049">"ফিংগাৰপ্ৰিণ্ট:"</string>
+ <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ফিংগাৰপ্ৰিণ্ট:"</string>
+ <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ফিংগাৰপ্ৰিণ্ট:"</string>
+ <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"সকলো চাওক"</string>
+ <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"কাৰ্যকলাপ বাছনি কৰক"</string>
+ <string name="share_action_provider_share_with" msgid="5247684435979149216">"ইয়াৰ জৰিয়তে শ্বেয়াৰ কৰক"</string>
+ <string name="sending" msgid="3245653681008218030">"পঠিয়াই থকা হৈছে…"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"ব্ৰাউজাৰ লঞ্চ কৰিবনে?"</string>
+ <string name="SetupCallDefault" msgid="5834948469253758575">"কল স্বীকাৰ কৰিবনে?"</string>
+ <string name="activity_resolver_use_always" msgid="8017770747801494933">"সদায়"</string>
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"মাত্ৰ এবাৰ"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$sএ কৰ্মস্থানৰ প্ৰ\'ফাইল সমৰ্থন নকৰে।"</string>
+ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"টেবলেট"</string>
+ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"টিভি"</string>
+ <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ফ\'ন"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ড\'ক স্পীকাৰসমূহ"</string>
+ <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string>
+ <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"হেডফ\'নবোৰ"</string>
+ <string name="default_audio_route_name_usb" msgid="1234984851352637769">"ইউএছবি"</string>
+ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ছিষ্টেম"</string>
+ <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ব্লুটুথ অডিঅ\'"</string>
+ <string name="wireless_display_route_description" msgid="9070346425023979651">"ৱায়াৰলেচ ডিছপ্লে\'"</string>
+ <string name="media_route_button_content_description" msgid="591703006349356016">"কাষ্ট"</string>
+ <string name="media_route_chooser_title" msgid="1751618554539087622">"ডিভাইচৰ লগত সংযোগ কৰক"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ডিভাইচত স্ক্ৰীণ কাষ্ট কৰক"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"ডিভাইচৰ সন্ধান কৰক…"</string>
+ <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ছেটিংসমূহ"</string>
+ <string name="media_route_controller_disconnect" msgid="8966120286374158649">"বিচ্ছিন্ন কৰক"</string>
+ <string name="media_route_status_scanning" msgid="7279908761758293783">"স্কেন কৰি থকা হৈছে…"</string>
+ <string name="media_route_status_connecting" msgid="6422571716007825440">"সংযোগ কৰি থকা হৈছে..."</string>
+ <string name="media_route_status_available" msgid="6983258067194649391">"উপলব্ধ"</string>
+ <string name="media_route_status_not_available" msgid="6739899962681886401">"উপলব্ধ নহয়"</string>
+ <string name="media_route_status_in_use" msgid="4533786031090198063">"ব্যৱহাৰ হৈ আছে"</string>
+ <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"অন্তৰ্নিমিত স্ক্ৰীণ"</string>
+ <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI স্ক্ৰীণ"</string>
+ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"অ\'ভাৰলে\' #<xliff:g id="ID">%1$d</xliff:g>"</string>
+ <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<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="6022119702628572080">", সুৰক্ষিত"</string>
+ <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"আৰ্হি পাহৰিলেনে"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"ভুল আৰ্হি"</string>
+ <string name="kg_wrong_password" msgid="2333281762128113157">"ভুল পাছৱৰ্ড"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"ভুল পিন"</string>
+ <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="8790651267324125694">
+ <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক।</item>
+ <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক।</item>
+ </plurals>
+ <string name="kg_pattern_instructions" msgid="398978611683075868">"নিজৰ আৰ্হি আঁকক"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"ছিমৰ পিন দিয়ক"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"পিন দিয়ক"</string>
+ <string name="kg_password_instructions" msgid="5753646556186936819">"পাছৱৰ্ড দিয়ক"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"ছিমখন বর্তমান অক্ষম অৱস্থাত আছে। অব্যাহত ৰাখিবলৈ PUK ক\'ড লিখক। সবিশেষ জানিবলৈ বাহকৰ সৈতে যোগাযোগ কৰক।"</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"ইচ্ছা কৰা পিন ক\'ড লিখক"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"ইচ্ছা কৰা পিন ক\'ড নিশ্চিত কৰক"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"ছিম কার্ড আনলক কৰি থকা হৈছে…"</string>
+ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"ভুল পিন ক\'ড।"</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"৪ ৰ পৰা ৮ টা লৈকে সংখ্য়া সন্নিবিষ্ট হোৱা পিন লিখক।"</string>
+ <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK ক\'ড ৮টা সংখ্যাৰ হ\'ব লাগিব।"</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"শুদ্ধ PUK ক\'ডটো পুনৰ দিয়ক। বাৰে বাৰে ভুল ক\'ড দিলে ছিমখন স্থায়ীভাৱে অক্ষম হ\'ব।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"পিন ক\'ড মিলা নাই"</string>
+ <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"বহুতবাৰ ভুলকৈ আর্হি অঁকাৰ প্ৰয়াস কৰা হৈছে"</string>
+ <string name="kg_login_instructions" msgid="1100551261265506448">"আনলক কৰিবলৈ নিজৰ Google একাউণ্টৰ জৰিয়তে ছাইন ইন কৰক।"</string>
+ <string name="kg_login_username_hint" msgid="5718534272070920364">"ব্যৱহাৰকাৰী (ইমেইল)"</string>
+ <string name="kg_login_password_hint" msgid="9057289103827298549">"পাছৱৰ্ড"</string>
+ <string name="kg_login_submit_button" msgid="5355904582674054702">"ছাইন ইন কৰক"</string>
+ <string name="kg_login_invalid_input" msgid="5754664119319872197">"ব্যৱহাৰকাৰীৰ অমান্য নাম বা পাছৱর্ড।"</string>
+ <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"নিজৰ ব্যৱহাৰকাৰী নাম আৰু পাছৱর্ড পাহৰিলেনে?\n"<b>"google.com/accounts/recovery"</b>" লৈ যাওক।"</string>
+ <string name="kg_login_checking_password" msgid="1052685197710252395">"একাউণ্ট পৰীক্ষা কৰি থকা হৈছে…"</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"আপুনি আপোনাৰ পিন <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="7813713389422226531">"আপুনি আপোনাৰ পাছৱৰ্ড <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="74089475965050805">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হি <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="1575557200627128949">"আপুনি <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="5621231220154419413">"আপুনি টিভিটো আনলক কৰিবলৈ <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="default" msgid="4051015943038199910">"আপুনি <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="2072996269148483637">"আপুনি <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ টেবলেটৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। টেবলেটটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"আপুনি টিভিটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। টিভিটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"আপুনি <xliff:g id="NUMBER">%d</xliff:g>বাৰ ভুলকৈ ফ\'নৰ ল\'ক খোলাৰ প্ৰয়াস কৰিছে। ফ\'নটো এতিয়া ফেক্টৰী ডিফ\'ল্টলৈ ৰিছেট কৰা হ\'ব।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হিটো <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="4224651132862313471">"আপুনি টিভিটো আনলক কৰিবলৈ <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="1437638152015574839">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হিটো <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="4160700433287233771">" — "</string>
+ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"আঁতৰাওক"</string>
+ <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string>
+ <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"শ্বৰ্টকাট অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটামত ৩ ছেকেণ্ডৰ বাবে ছাপ দি থাকিলে দিব্যাংগসকলৰ বাবে থকা সুবিধা এটা আৰম্ভ হ\'ব। \n\n চলিত দিব্যাংগসকলৰ সুবিধা:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপুনি এই সুবিধাটো ছেটিংসমূহ > দিব্যাংগসকলৰ বাবে সুবিধা-লৈ গৈ সলনি কৰিব পাৰে।"</string>
+ <string name="disable_accessibility_shortcut" msgid="627625354248453445">"শ্বৰ্টকাট অফ কৰক"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string>
+ <string name="color_inversion_feature_name" msgid="4231186527799958644">"ৰং বিপৰীতকৰণ"</string>
+ <string name="color_correction_feature_name" msgid="6779391426096954933">"ৰং শুধৰণী"</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাটটোৱে <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ক অন কৰিছে"</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাটটোৱে <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ক অফ কৰিছে"</string>
+ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"আপুনি দিব্যাংগসকলৰ সুবিধাৰ বুটামটো টিপিলে ব্যৱহাৰ কৰিবলগীয়া কোনো সুবিধা বাছক:"</string>
+ <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"সুবিধাসমূহ সলনি কৰিবলৈ দিব্যাংগসকলৰ সুবিধাৰ বুটামটো স্পৰ্শ কৰি থাকক।"</string>
+ <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"বিবৰ্ধন"</string>
+ <string name="user_switched" msgid="3768006783166984410">"বৰ্তমানৰ ব্যৱহাৰকাৰী <xliff:g id="NAME">%1$s</xliff:g>।"</string>
+ <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g>লৈ সলনি কৰি থকা হৈছে…"</string>
+ <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g>ৰ পৰা লগ আউট কৰি থকা হৈছে…"</string>
+ <string name="owner_name" msgid="2716755460376028154">"গৰাকী"</string>
+ <string name="error_message_title" msgid="4510373083082500195">"আসোঁৱাহ"</string>
+ <string name="error_message_change_not_allowed" msgid="1238035947357923497">"আপোনাৰ প্ৰশাসকে এই অৱস্থাটো সলনি কৰিবলৈ অনুমতি নিদিয়ে"</string>
+ <string name="app_not_found" msgid="3429141853498927379">"এই কাৰ্যটো পৰিচালনা কৰিবলৈ কোনো এপ্লিকেশ্বন পোৱা নগ\'ল"</string>
+ <string name="revoke" msgid="5404479185228271586">"প্ৰত্যাহাৰ কৰক"</string>
+ <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
+ <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string>
+ <string name="mediasize_iso_a2" msgid="3097535991925798280">"ISO A2"</string>
+ <string name="mediasize_iso_a3" msgid="3023213259314236123">"ISO A3"</string>
+ <string name="mediasize_iso_a4" msgid="231745325296873764">"ISO A4"</string>
+ <string name="mediasize_iso_a5" msgid="3484327407340865411">"ISO A5"</string>
+ <string name="mediasize_iso_a6" msgid="4861908487129577530">"ISO A6"</string>
+ <string name="mediasize_iso_a7" msgid="5890208588072936130">"ISO A7"</string>
+ <string name="mediasize_iso_a8" msgid="4319425041085816612">"ISO A8"</string>
+ <string name="mediasize_iso_a9" msgid="4882220529506432008">"ISO A9"</string>
+ <string name="mediasize_iso_a10" msgid="2382866026365359391">"ISO A10"</string>
+ <string name="mediasize_iso_b0" msgid="3651827147402009675">"ISO B0"</string>
+ <string name="mediasize_iso_b1" msgid="6072859628278739957">"ISO B1"</string>
+ <string name="mediasize_iso_b2" msgid="1348731852150380378">"ISO B2"</string>
+ <string name="mediasize_iso_b3" msgid="2612510181259261379">"ISO B3"</string>
+ <string name="mediasize_iso_b4" msgid="695151378838115434">"ISO B4"</string>
+ <string name="mediasize_iso_b5" msgid="4863754285582212487">"ISO B5"</string>
+ <string name="mediasize_iso_b6" msgid="5305816292139647241">"ISO B6"</string>
+ <string name="mediasize_iso_b7" msgid="531673542602786624">"ISO B7"</string>
+ <string name="mediasize_iso_b8" msgid="9164474595708850034">"ISO B8"</string>
+ <string name="mediasize_iso_b9" msgid="282102976764774160">"ISO B9"</string>
+ <string name="mediasize_iso_b10" msgid="4517141714407898976">"ISO B10"</string>
+ <string name="mediasize_iso_c0" msgid="3103521357901591100">"ISO C0"</string>
+ <string name="mediasize_iso_c1" msgid="1231954105985048595">"ISO C1"</string>
+ <string name="mediasize_iso_c2" msgid="927702816980087462">"ISO C2"</string>
+ <string name="mediasize_iso_c3" msgid="835154173518304159">"ISO C3"</string>
+ <string name="mediasize_iso_c4" msgid="5095951985108194011">"ISO C4"</string>
+ <string name="mediasize_iso_c5" msgid="1985397450332305739">"ISO C5"</string>
+ <string name="mediasize_iso_c6" msgid="8147421924174693013">"ISO C6"</string>
+ <string name="mediasize_iso_c7" msgid="8993994925276122950">"ISO C7"</string>
+ <string name="mediasize_iso_c8" msgid="6871178104139598957">"ISO C8"</string>
+ <string name="mediasize_iso_c9" msgid="7983532635227561362">"ISO C9"</string>
+ <string name="mediasize_iso_c10" msgid="5040764293406765584">"ISO C10"</string>
+ <string name="mediasize_na_letter" msgid="2841414839888344296">"লেটাৰ"</string>
+ <string name="mediasize_na_gvrnmt_letter" msgid="5295836838862962809">"চৰকাৰী পত্ৰ"</string>
+ <string name="mediasize_na_legal" msgid="8621364037680465666">"লিগেল"</string>
+ <string name="mediasize_na_junior_legal" msgid="3309324162155085904">"জুনিয়ৰ লিগেল"</string>
+ <string name="mediasize_na_ledger" msgid="5567030340509075333">"লেজাৰ"</string>
+ <string name="mediasize_na_tabloid" msgid="4571735038501661757">"টে\'বলইড"</string>
+ <string name="mediasize_na_index_3x5" msgid="5182901917818625126">"ইনডেক্স কাৰ্ড ৩x৫"</string>
+ <string name="mediasize_na_index_4x6" msgid="7687620625422312396">"ইনডেক্স কাৰ্ড ৪x৬"</string>
+ <string name="mediasize_na_index_5x8" msgid="8834215284646872800">"ইনডেক্স কাৰ্ড ৫x৮"</string>
+ <string name="mediasize_na_monarch" msgid="213639906956550754">"ম\'নাৰ্ক"</string>
+ <string name="mediasize_na_quarto" msgid="835778493593023223">"কুৱাট্ৰো"</string>
+ <string name="mediasize_na_foolscap" msgid="1573911237983677138">"ফুলস্কেপ"</string>
+ <string name="mediasize_chinese_roc_8k" msgid="3626855847189438896">"ROC 8K"</string>
+ <string name="mediasize_chinese_roc_16k" msgid="9182191577022943355">"ROC 16K"</string>
+ <string name="mediasize_chinese_prc_1" msgid="4793232644980170500">"PRC 1"</string>
+ <string name="mediasize_chinese_prc_2" msgid="5404109730975720670">"PRC 2"</string>
+ <string name="mediasize_chinese_prc_3" msgid="1335092253339363526">"PRC 3"</string>
+ <string name="mediasize_chinese_prc_4" msgid="9167997800486569834">"PRC 4"</string>
+ <string name="mediasize_chinese_prc_5" msgid="845875168823541497">"PRC 5"</string>
+ <string name="mediasize_chinese_prc_6" msgid="3220325667692648789">"PRC 6"</string>
+ <string name="mediasize_chinese_prc_7" msgid="1776792138507038527">"PRC 7"</string>
+ <string name="mediasize_chinese_prc_8" msgid="1417176642687456692">"PRC 8"</string>
+ <string name="mediasize_chinese_prc_9" msgid="4785983473123798365">"PRC 9"</string>
+ <string name="mediasize_chinese_prc_10" msgid="7847982299391851899">"PRC 10"</string>
+ <string name="mediasize_chinese_prc_16k" msgid="262793383539980677">"PRC 16K"</string>
+ <string name="mediasize_chinese_om_pa_kai" msgid="5256815579447959814">"Pa Kai"</string>
+ <string name="mediasize_chinese_om_dai_pa_kai" msgid="7336412963441354407">"Dai Pa Kai"</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai" msgid="6324465444100490742">"Jurro Ku Kai"</string>
+ <string name="mediasize_japanese_jis_b10" msgid="1787262845627694376">"JIS B10"</string>
+ <string name="mediasize_japanese_jis_b9" msgid="3336035783663287470">"JIS B9"</string>
+ <string name="mediasize_japanese_jis_b8" msgid="6195398299104345731">"JIS B8"</string>
+ <string name="mediasize_japanese_jis_b7" msgid="1674621886902828884">"JIS B7"</string>
+ <string name="mediasize_japanese_jis_b6" msgid="4170576286062657435">"JIS B6"</string>
+ <string name="mediasize_japanese_jis_b5" msgid="4899297958100032533">"JIS B5"</string>
+ <string name="mediasize_japanese_jis_b4" msgid="4213158129126666847">"JIS B4"</string>
+ <string name="mediasize_japanese_jis_b3" msgid="8513715307410310696">"JIS B3"</string>
+ <string name="mediasize_japanese_jis_b2" msgid="4777690211897131190">"JIS B2"</string>
+ <string name="mediasize_japanese_jis_b1" msgid="4608142385457034603">"JIS B1"</string>
+ <string name="mediasize_japanese_jis_b0" msgid="7587108366572243991">"JIS B0"</string>
+ <string name="mediasize_japanese_jis_exec" msgid="5244075432263649068">"JIS Exec"</string>
+ <string name="mediasize_japanese_chou4" msgid="4941652015032631361">"Chou4"</string>
+ <string name="mediasize_japanese_chou3" msgid="6387319169263957010">"Chou3"</string>
+ <string name="mediasize_japanese_chou2" msgid="1299112025415343982">"Chou2"</string>
+ <string name="mediasize_japanese_hagaki" msgid="8070115620644254565">"Hagaki"</string>
+ <string name="mediasize_japanese_oufuku" msgid="6049065587307896564">"Oufuku"</string>
+ <string name="mediasize_japanese_kahu" msgid="6872696027560065173">"Kahu"</string>
+ <string name="mediasize_japanese_kaku2" msgid="2359077233775455405">"Kaku2"</string>
+ <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string>
+ <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"অজ্ঞাত প\'ৰ্ট্ৰেইট"</string>
+ <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"অজ্ঞাত লেণ্ডস্কেইপ"</string>
+ <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"বাতিল কৰা হ\'ল"</string>
+ <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"সমল লিখাত আসোঁৱাহ"</string>
+ <string name="reason_unknown" msgid="6048913880184628119">"অজ্ঞাত"</string>
+ <string name="reason_service_unavailable" msgid="7824008732243903268">"প্ৰিণ্টিং সেৱা সক্ষম নহয়"</string>
+ <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> সেৱা ইনষ্টল কৰা হ\'ল"</string>
+ <string name="print_service_installed_message" msgid="5897362931070459152">"সক্ষম কৰিবলৈ টিপক"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"প্ৰশাসকৰ পিন দিয়ক"</string>
+ <string name="restr_pin_enter_pin" msgid="3395953421368476103">"পিন দিয়ক"</string>
+ <string name="restr_pin_incorrect" msgid="8571512003955077924">"অশুদ্ধ"</string>
+ <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"বৰ্তমানৰ পিন"</string>
+ <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"নতুন পিন"</string>
+ <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"নতুন পিন নিশ্চিত কৰক"</string>
+ <string name="restr_pin_create_pin" msgid="8017600000263450337">"সীমাবদ্ধতা সংশোধন কৰিবলৈ এটা পিন সৃষ্টি কৰক"</string>
+ <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"পিনবোৰ মিলা নাই। আকৌ চেষ্টা কৰক।"</string>
+ <string name="restr_pin_error_too_short" msgid="8173982756265777792">"পিনটো অতি চুটি। কমেও ৪টা সংখ্যাৰ হ\'ব লাগিব।"</string>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"> <xliff:g id="COUNT">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক</item>
+ <item quantity="other"> <xliff:g id="COUNT">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক</item>
+ </plurals>
+ <string name="restr_pin_try_later" msgid="973144472490532377">"পিছত আকৌ চেষ্টা কৰক"</string>
+ <!-- no translation found for immersive_cling_title (8394201622932303336) -->
+ <skip />
+ <!-- no translation found for immersive_cling_description (3482371193207536040) -->
+ <skip />
+ <!-- no translation found for immersive_cling_positive (5016839404568297683) -->
+ <skip />
+ <string name="done_label" msgid="2093726099505892398">"সম্পন্ন কৰা হ\'ল"</string>
+ <string name="hour_picker_description" msgid="6698199186859736512">"ঘড়ীৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
+ <string name="minute_picker_description" msgid="8606010966873791190">"মিনিটৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
+ <string name="select_hours" msgid="6043079511766008245">"ঘণ্টা বাছনি কৰক"</string>
+ <string name="select_minutes" msgid="3974345615920336087">"মিনিট বাছনি কৰক"</string>
+ <string name="select_day" msgid="7774759604701773332">"মাহ আৰু দিন বাছনি কৰক"</string>
+ <string name="select_year" msgid="7952052866994196170">"বছৰ বাছনি কৰক"</string>
+ <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> মচা হ\'ল"</string>
+ <string name="managed_profile_label_badge" msgid="2355652472854327647">"কৰ্মস্থান <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"২য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"৩য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"আনপিন কৰাৰ পূৰ্বে পিন দিবলৈ কওক"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"আনপিন কৰাৰ পূৰ্বে আনলক আৰ্হি দিবলৈ কওক"</string>
+ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন কৰাৰ পূৰ্বে পাছৱৰ্ড দিবলৈ কওক"</string>
+ <string name="package_installed_device_owner" msgid="6875717669960212648">"আপোনাৰ প্ৰশাসকে ইনষ্টল কৰিছে"</string>
+ <string name="package_updated_device_owner" msgid="1847154566357862089">"আপোনাৰ প্ৰশাসকে আপেডট কৰিছে"</string>
+ <string name="package_deleted_device_owner" msgid="2307122077550236438">"আপোনাৰ প্ৰশাসকে মচিছে"</string>
+ <string name="battery_saver_description" msgid="5394663545060026162">"বেটাৰিৰ অৱস্থা উন্নত কৰাত সহায় কৰিবলৈ বেটাৰি সঞ্চয়কাৰী সুবিধাই আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা হ্ৰাস কৰে আৰু কম্পন, অৱস্থান সেৱা আৰু অধিকাংশ নেপথ্য ডেটা সীমিত কৰে। ছিংকৰ ওপৰত নির্ভৰশীল ইমেইল, মেছেজিং আৰু অন্য এপসমূহ আপুনি নোখোলা পৰ্যন্ত আপডেট নহ\'বও পাৰে।\n\nআপোনাৰ ডিভাইচ চ্চার্জ কৰি থকাৰ সময়ত বেটাৰি সঞ্চয়কাৰী সুবিধা স্বয়ংক্ৰিয়ভাৱে অফ হ\'ব।"</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"ডেটা ব্য়ৱহাৰ মাত্ৰা কম কৰিবৰ বাবে ডেটা সঞ্চয়কাৰীয়ে কিছুমান এপক নেপথ্য়ত ডেটা প্ৰেৰণ বা সংগ্ৰহ কৰাত বাধা প্ৰদান কৰে। আপুনি বৰ্তমান ব্য়ৱহাৰ কৰি থকা এটা এপে ডেটা ব্য়ৱহাৰ কৰিব পাৰে, কিন্তু সঘনাই এই কার্য কৰিব নোৱাৰিব পাৰে। ইয়াৰ অৰ্থ এইয়ে হ\'ব পাৰে যে, উদাহৰণস্বৰূপে, আপুনি নিটিপা পর্যন্ত প্ৰতিচ্ছবিসমূহ দেখুওৱা নহ\'ব।"</string>
+ <string name="data_saver_enable_title" msgid="4674073932722787417">"ডেটা সঞ্চয়কাৰী অন কৰিবনে?"</string>
+ <string name="data_saver_enable_button" msgid="7147735965247211818">"অন কৰক"</string>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one"> %1$d মিনিটৰ বাবে (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পৰ্যন্ত)</item>
+ <item quantity="other"> %1$d মিনিটৰ বাবে (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পৰ্যন্ত)</item>
+ </plurals>
+ <!-- no translation found for zen_mode_duration_minutes_summary_short (6830154222366042597) -->
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d ঘণ্টাৰ বাবে (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পৰ্যন্ত)</item>
+ <item quantity="other">%1$d ঘণ্টাৰ বাবে (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পৰ্যন্ত)</item>
+ </plurals>
+ <!-- no translation found for zen_mode_duration_hours_summary_short (4787552595253082371) -->
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d মিনিটৰ বাবে</item>
+ <item quantity="other">%d মিনিটৰ বাবে</item>
+ </plurals>
+ <!-- no translation found for zen_mode_duration_minutes_short (2199350154433426128) -->
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d ঘণ্টাৰ বাবে</item>
+ <item quantity="other">%d ঘণ্টাৰ বাবে</item>
+ </plurals>
+ <!-- no translation found for zen_mode_duration_hours_short (6748277774662434217) -->
+ <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পৰ্যন্ত"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (পৰৱৰ্তী এলার্ম) পর্যন্ত"</string>
+ <!-- no translation found for zen_mode_forever (931849471004038757) -->
+ <skip />
+ <!-- no translation found for zen_mode_forever_dnd (3792132696572189081) -->
+ <skip />
+ <!-- no translation found for zen_mode_rule_name_combination (191109939968076477) -->
+ <skip />
+ <string name="toolbar_collapse_description" msgid="2821479483960330739">"সংকুচিত কৰক"</string>
+ <!-- no translation found for zen_mode_feature_name (5254089399895895004) -->
+ <skip />
+ <!-- no translation found for zen_mode_downtime_feature_name (2626974636779860146) -->
+ <skip />
+ <!-- no translation found for zen_mode_default_weeknights_name (3081318299464998143) -->
+ <skip />
+ <!-- no translation found for zen_mode_default_weekends_name (2786495801019345244) -->
+ <skip />
+ <!-- no translation found for zen_mode_default_events_name (8158334939013085363) -->
+ <skip />
+ <string name="zen_mode_default_every_night_name" msgid="3012363838882944175">"নিদ্ৰাৰত"</string>
+ <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>ৰ দ্বাৰা মিউট কৰা হৈছে"</string>
+ <string name="system_error_wipe_data" msgid="6608165524785354962">"আপোনাৰ ডিভাইচত এটা আভ্যন্তৰীণ সমস্যা আছে আৰু আপুনি ফেক্টৰী ডেটা ৰিছেট নকৰালৈকে ই সুস্থিৰভাৱে কাম নকৰিব পাৰে।"</string>
+ <string name="system_error_manufacturer" msgid="8086872414744210668">"আপোনাৰ ডিভাইচত এটা আভ্যন্তৰীণ সমস্যা আছে। সবিশেষ জানিবৰ বাবে আপোনাৰ ডিভাইচ নির্মাতাৰ সৈতে যোগাযোগ কৰক।"</string>
+ <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD অনুৰোধক DIAL অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD অনুৰোধক SS অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD অনুৰোধক নতুন USSD অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ussd_to_dial_video" msgid="585340552561515305">"USSD অনুৰোধক ভিডিঅ\' DIAL অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS অনুৰোধক DIAL অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ss_to_dial_video" msgid="4306210904450719045">"SS অনুৰোধক ভিডিঅ\' DIAL অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS অনুৰোধক USSD অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS অনুৰোধক নতুন SS অনুৰোধলৈ সংশোধিত কৰা হৈছে।"</string>
+ <string name="notification_work_profile_content_description" msgid="4600554564103770764">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
+ <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"বিস্তাৰ কৰক"</string>
+ <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"সংকুচিত কৰক"</string>
+ <string name="expand_action_accessibility" msgid="5307730695723718254">"সম্প্ৰসাৰণ ট’গল কৰক"</string>
+ <!-- no translation found for usb_midi_peripheral_name (7221113987741003817) -->
+ <skip />
+ <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+ <skip />
+ <!-- no translation found for usb_midi_peripheral_product_name (4971827859165280403) -->
+ <skip />
+ <!-- no translation found for floating_toolbar_open_overflow_description (4797287862999444631) -->
+ <skip />
+ <!-- no translation found for floating_toolbar_close_overflow_description (559796923090723804) -->
+ <skip />
+ <string name="maximize_button_text" msgid="7543285286182446254">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string>
+ <string name="close_button_text" msgid="3937902162644062866">"বন্ধ কৰক"</string>
+ <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+ <plurals name="selected_count" formatted="false" msgid="7187339492915744615">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টা বাছনি কৰা হ\'ল</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টা বাছনি কৰা হ\'ল</item>
+ </plurals>
+ <string name="default_notification_channel_label" msgid="5929663562028088222">"শ্ৰেণীবদ্ধ নকৰা"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"এই জাননীবোৰৰ গুৰুত্ব আপুনি ছেট কৰব লাগিব।"</string>
+ <string name="importance_from_person" msgid="9160133597262938296">"এই কার্যৰ সৈতে জড়িত থকা লোকসকলক ভিত্তি কৰি এইয়া গুৰুত্বপূর্ণ বুলি বিবেচনা কৰা হৈছ।"</string>
+ <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ক <xliff:g id="ACCOUNT">%2$s</xliff:g>ৰ জৰিয়তে নতুন ব্য়ৱহাৰকাৰী সৃষ্টি কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>ক <xliff:g id="ACCOUNT">%2$s</xliff:g>ৰ (এই একাউন্টৰ এজন ব্য়ৱহাৰকাৰী ইতিমধ্য়ে আছে) জৰিয়তে নতুন ব্য়ৱহাৰকাৰী সৃষ্টি কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ভাষা এটা যোগ কৰক"</string>
+ <string name="country_selection_title" msgid="2954859441620215513">"অঞ্চলৰ অগ্ৰাধিকাৰ"</string>
+ <string name="search_language_hint" msgid="7042102592055108574">"ভাষাৰ নাম লিখক"</string>
+ <string name="language_picker_section_suggested" msgid="8414489646861640885">"প্ৰস্তাৱিত"</string>
+ <string name="language_picker_section_all" msgid="3097279199511617537">"সকলো ভাষা"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"সকলো অঞ্চল"</string>
+ <string name="locale_search_menu" msgid="2560710726687249178">"অনুসন্ধান কৰক"</string>
+ <!-- no translation found for work_mode_off_title (1118691887588435530) -->
+ <skip />
+ <!-- no translation found for work_mode_off_message (5130856710614337649) -->
+ <skip />
+ <string name="work_mode_turn_on" msgid="2062544985670564875">"অন কৰক"</string>
+ <!-- no translation found for deprecated_target_sdk_message (1449696506742572767) -->
+ <skip />
+ <!-- no translation found for deprecated_target_sdk_app_store (5032340500368495077) -->
+ <skip />
+ <string name="new_sms_notification_title" msgid="8442817549127555977">"আপুনি নতুন বার্তা লাভ কৰিছে"</string>
+ <string name="new_sms_notification_content" msgid="7002938807812083463">"চাবলৈ এছএমএছ এপ্ খোলক"</string>
+ <string name="user_encrypted_title" msgid="9054897468831672082">"কিছুমান কৰ্মক্ষমতা সীমিত হ\'ব পাৰে"</string>
+ <string name="user_encrypted_message" msgid="4923292604515744267">"আনলক কৰিবলৈ টিপক"</string>
+ <string name="user_encrypted_detail" msgid="5708447464349420392">"ব্য়ৱহাৰকাৰীৰ ডেটা লক হৈ আছে"</string>
+ <string name="profile_encrypted_detail" msgid="3700965619978314974">"কৰ্মস্থানৰ প্ৰ’ফাইল লক হৈ আছে"</string>
+ <string name="profile_encrypted_message" msgid="6964994232310195874">"কৰ্মস্থানৰ প্ৰ’ফাইল আনলক কৰিবলৈ টিপক"</string>
+ <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>ৰ সৈতে সংযুক্ত হৈ আছে"</string>
+ <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ফাইলসমূহ চাবৰ বাবে টিপক"</string>
+ <string name="pin_target" msgid="3052256031352291362">"পিন"</string>
+ <string name="unpin_target" msgid="3556545602439143442">"আনপিন"</string>
+ <string name="app_info" msgid="6856026610594615344">"এপ্ সম্পৰ্কীয় তথ্য"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"ডেম\' আৰম্ভ কৰি থকা হৈছে…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"ডিভাইচটো আকৌ ছেটিং কৰি থকা হৈছে…"</string>
+ <string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>ক অক্ষম কৰা হ\'ল"</string>
+ <string name="conference_call" msgid="3751093130790472426">"কনফাৰেঞ্চ কল"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"টুলটিপ"</string>
+ <string name="app_category_game" msgid="5431836943981492993">"গেম"</string>
+ <string name="app_category_audio" msgid="1659853108734301647">"সংগীত আৰু ধ্বনি"</string>
+ <string name="app_category_video" msgid="2728726078629384196">"চলচ্চিত্ৰ আৰু ভিডিঅ\'"</string>
+ <string name="app_category_image" msgid="4867854544519846048">"ফট\' আৰু প্ৰতিচ্ছবি"</string>
+ <string name="app_category_social" msgid="5842783057834965912">"সামাজিক আৰু যোগাযোগ"</string>
+ <string name="app_category_news" msgid="7496506240743986873">"বাতৰি আৰু আলোচনী"</string>
+ <string name="app_category_maps" msgid="5878491404538024367">"মেপ আৰু দিক্-নিৰ্দেশনা"</string>
+ <string name="app_category_productivity" msgid="3742083261781538852">"উৎপাদনশীলতা"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ডিভাইচৰ সঞ্চয়াগাৰ"</string>
+ <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"ইউএছবি ডিবাগিং"</string>
+ <string name="time_picker_hour_label" msgid="2979075098868106450">"ঘণ্টা"</string>
+ <string name="time_picker_minute_label" msgid="5168864173796598399">"মিনিট"</string>
+ <string name="time_picker_header_text" msgid="143536825321922567">"সময় ছেট কৰক"</string>
+ <string name="time_picker_input_error" msgid="7574999942502513765">"এটা মান্য সময় দিয়ক"</string>
+ <string name="time_picker_prompt_label" msgid="7588093983899966783">"সময় টাইপ কৰক"</string>
+ <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"সময়ৰ ইনপুটৰ বাবে পাঠৰ ইনপুট ম\'ডলৈ যাওক।"</string>
+ <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"সময়ৰ ইনপুটৰ বাবে ঘড়ী ম\'ডলৈ যাওক।"</string>
+ <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"স্বয়ংপূৰ্তিৰ বিকল্পসমূহ"</string>
+ <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"পিছত স্বয়ংপূৰ্তি কৰিবলৈ ছেভ কৰক"</string>
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"সমলসমূহ স্বয়ংপূৰ্তি কৰিব নোৱাৰি"</string>
+ <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"কোনো স্বয়ংপূৰ্তি পৰামৰ্শ নাই"</string>
+ <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
+ <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g>টা স্বয়ংপূৰ্তি পৰামৰ্শ</item>
+ <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g>টা স্বয়ংপূৰ্তি পৰামৰ্শ</item>
+ </plurals>
+ <string name="autofill_save_title" msgid="3345527308992082601">"<b><xliff:g id="LABEL">%1$s</xliff:g></b>ত ছেভ কৰিবনে?"</string>
+ <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ক <b><xliff:g id="LABEL">%2$s</xliff:g></b>ত ছেভ কৰিবনে?"</string>
+ <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক <b><xliff:g id="LABEL">%3$s</xliff:g></b>ত ছেভ কৰিবনে?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<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>ক <b><xliff:g id="LABEL">%4$s</xliff:g></b>ত ছেভ কৰিবনে?"</string>
+ <string name="autofill_save_yes" msgid="6398026094049005921">"ছেভ কৰক"</string>
+ <string name="autofill_save_no" msgid="2625132258725581787">"নালাগে, ধন্যবাদ"</string>
+ <string name="autofill_save_type_password" msgid="5288448918465971568">"পাছৱৰ্ড"</string>
+ <string name="autofill_save_type_address" msgid="4936707762193009542">"ঠিকনা"</string>
+ <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ক্ৰেডিট কাৰ্ড"</string>
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ব্যৱহাৰকাৰীৰ নাম"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ইমেইল ঠিকনা"</string>
+ <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"শান্ত হৈ থাকক আৰু ওচৰৰ ক\'ৰবাত আশ্ৰয় বিচাৰক।"</string>
+ <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"উপকূলীয় আৰু নদী-কাযৰীয়া অঞ্চলৰ পৰা তৎক্ষণাৎ আঁতৰ হওক আৰু ওখ অঞ্চলৰ নিচিনা নিৰাপদ ঠাইত আশ্ৰয় লওক।"</string>
+ <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"শান্ত হৈ থাকক আৰু ওচৰৰ ক\'ৰবাত আশ্ৰয় বিচাৰক।"</string>
+ <string name="etws_primary_default_message_test" msgid="2709597093560037455">"জৰুৰীকালীন বাৰ্তা সম্পৰ্কীয় পৰীক্ষণ"</string>
+ <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"উত্তৰ দিয়ক"</string>
+ <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
+ <string name="mmcc_authentication_reject" msgid="5767701075994754356">"ভইচৰ বাবে ছিম ব্যৱহাৰৰ অনুমতি নাই"</string>
+ <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"ভইচৰ বাবে ছিমৰ প্ৰ\'ভিজন কৰা হোৱা নাই"</string>
+ <string name="mmcc_illegal_ms" msgid="807334478177362062">"ভইচৰ বাবে ছিম ব্যৱহাৰৰ অনুমতি নাই"</string>
+ <string name="mmcc_illegal_me" msgid="1950705155760872972">"ভইচৰ বাবে ফ\'ন ব্যৱহাৰৰ অনুমতি নাই"</string>
+ <string name="popup_window_default_title" msgid="4874318849712115433">"পপআপ ৱিণ্ড\'"</string>
+ <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
+ <!-- no translation found for shortcut_restored_on_lower_version (4860853725206702336) -->
+ <skip />
+ <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"এপটোত বেকআপ আৰু পুনঃস্থাপন সুবিধা নথকাৰ বাবে শ্বৰ্টকাট পুনঃস্থাপন কৰিবপৰা নগ\'ল"</string>
+ <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"এপৰ স্বাক্ষৰৰ অমিল হোৱাৰ বাবে শ্বৰ্টকাট পুনঃস্থাপন কৰিবপৰা নগ\'ল"</string>
+ <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"শ্বৰ্টকাট পুনঃস্থাপন কৰিবপৰা নগ\'ল"</string>
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"শ্বৰ্টকাট অক্ষম কৰি থোৱা হৈছে"</string>
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
+ <skip />
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
+ <skip />
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
+ <skip />
+ <!-- no translation found for slices_permission_request (8484943441501672932) -->
+ <skip />
+ <!-- no translation found for screenshot_edit (7867478911006447565) -->
+ <skip />
+ <!-- no translation found for notification_channel_system_changes (5072715579030948646) -->
+ <skip />
+ <!-- no translation found for zen_upgrade_notification_title (3799603322910377294) -->
+ <skip />
+ <!-- no translation found for zen_upgrade_notification_content (6603123479476554768) -->
+ <skip />
+</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 082a7a6..bd3de48 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -185,7 +185,7 @@
<string name="network_logging_notification_title" msgid="6399790108123704477">"Прылада знаходзіцца пад кіраваннем"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ваша арганізацыя кіруе гэтай прыладай і можа сачыць за сеткавым трафікам. Дакраніцеся для атрымання дадатковай інфармацыі."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Даныя вашай прылады будуць сцерты"</string>
- <string name="factory_reset_message" msgid="7972496262232832457">"Немагчыма выкарыстоўваць праграму адміністратара. Зараз звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара вашай арганізацыі."</string>
+ <string name="factory_reset_message" msgid="9024647691106150160">"Немагчыма выкарыстоўваць праграму адміністравання. Звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара арганізацыі."</string>
<string name="printing_disabled_by" msgid="8936832919072486965">"Друк адключаны ўладальнікам праграмы <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Я"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Параметры планшэта"</string>
@@ -242,6 +242,9 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Рэжым палёту"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Уключаны рэжым \"У самалёце\""</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Рэжым \"У самалёце\" адключаны"</string>
+ <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Эканомія зараду"</string>
+ <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Рэжым эканоміі зараду выключаны"</string>
+ <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Рэжым эканоміі зараду ўключаны"</string>
<string name="global_action_settings" msgid="1756531602592545966">"Налады"</string>
<string name="global_action_assist" msgid="3892832961594295030">"Дапамога"</string>
<string name="global_action_voice_assist" msgid="7751191495200504480">"Галас. дапамога"</string>
@@ -311,7 +314,7 @@
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты адбіткаў пальцаў"</string>
- <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"адключаць ці змяняць радок стану"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"быць панэллю стану"</string>
@@ -362,6 +365,8 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дазваляе прыкладанню захоўваць некаторыя пастаянныя часткi ў памяцi. Гэта можа абмежаваць аб\'ём памяці, даступнай для іншых прыкладанняў, i запаволiць працу планшэта."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дазваляе праграме пастаянна захоўваць некаторыя свае часткi ў памяцi. Гэта можа абмежаваць аб\'ём памяці, даступнай для іншых праграм, i запаволiць працу тэлевізара."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Дазваляе прыкладанню захоўваць некаторыя пастаянныя часткi ў памяцi. Гэта можа абмежаваць аб\'ём памяці, даступнай для іншых прыкладанняў, i запаволiць працу тэлефона."</string>
+ <string name="permlab_foregroundService" msgid="3310786367649133115">"запусціць асноўныя сэрвісы"</string>
+ <string name="permdesc_foregroundService" msgid="6471634326171344622">"Дазваляе праграме выкарыстоўваць асноўныя сэрвісы."</string>
<string name="permlab_getPackageSize" msgid="7472921768357981986">"вымерыць прастору для захоўвання прыкладання"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Дазваляе прыкладанням атрымліваць яго код, дадзеныя і аб\'ём кэш-памяці"</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"змена сістэмных налад"</string>
@@ -808,6 +813,8 @@
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Узор разблакiроўкі."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Фэйскантроль"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код разблакiроўкі."</string>
+ <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Разблакіроўка SIM-карты з дапамогай PIN-кода."</string>
+ <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Разблакіроўка SIM-карты з дапамогай PUK-кода."</string>
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль разблакiроўкі."</string>
<string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Вобласць узора."</string>
<string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Вобласць слайда."</string>
@@ -1114,29 +1121,33 @@
<string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Праверыць на наяўнасць абнаўленняў"</string>
<string name="smv_application" msgid="3307209192155442829">"Прыкладанне <xliff:g id="APPLICATION">%1$s</xliff:g> (працэс <xliff:g id="PROCESS">%2$s</xliff:g>) парушыла ўласную палітыку StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Працэс <xliff:g id="PROCESS">%1$s</xliff:g> парушыў уласную палітыку StrictMode."</string>
- <string name="android_upgrading_title" msgid="1584192285441405746">"Абнаўленне Android..."</string>
- <string name="android_start_title" msgid="8418054686415318207">"Android запускаецца..."</string>
+ <!-- no translation found for android_upgrading_title (7513829952443484438) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (4503169817302593560) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (7009520271220804517) -->
+ <skip />
+ <!-- no translation found for android_start_title (4536778526365907780) -->
+ <skip />
+ <!-- no translation found for android_start_title (4929837533850340472) -->
+ <skip />
+ <!-- no translation found for android_start_title (7467484093260449437) -->
+ <skip />
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Аптымізацыя сховішча."</string>
- <string name="android_upgrading_notification_title" msgid="8428357096969413169">"Абнаўленне Android завяршаецца…"</string>
- <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Пэўныя праграмы могуць не працаваць належным чынам, пакуль не скончыцца абнаўленне"</string>
+ <!-- no translation found for android_upgrading_notification_title (1511552415039349062) -->
+ <skip />
<string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> абнаўляецца…"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"Аптымізацыя прыкладання <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Падрыхтоўка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Запуск прыкладанняў."</string>
<string name="android_upgrading_complete" msgid="1405954754112999229">"Завяршэнне загрузкі."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"Прыкладанне \"<xliff:g id="APP">%1$s</xliff:g>\" запушчанае"</string>
- <!-- no translation found for heavy_weight_notification_detail (2304833848484424985) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_title (387882830435195342) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_text (4176781660362912010) -->
- <skip />
- <!-- no translation found for old_app_action (3044685170829526403) -->
- <skip />
- <!-- no translation found for new_app_action (6694851182870774403) -->
- <skip />
- <!-- no translation found for new_app_description (5894852887817332322) -->
- <skip />
+ <string name="heavy_weight_notification_detail" msgid="2304833848484424985">"Націсніце, каб вярнуцца да гульні"</string>
+ <string name="heavy_weight_switcher_title" msgid="387882830435195342">"Выберыце гульню"</string>
+ <string name="heavy_weight_switcher_text" msgid="4176781660362912010">"Для больш прадукцыйнай працы прылады адначасова дазваляецца адкрыць толькі адну з гэтых гульняў."</string>
+ <string name="old_app_action" msgid="3044685170829526403">"Вярнуцца да праграмы \"<xliff:g id="OLD_APP">%1$s</xliff:g>\""</string>
+ <string name="new_app_action" msgid="6694851182870774403">"Адкрыць праграму \"<xliff:g id="NEW_APP">%1$s</xliff:g>\""</string>
+ <string name="new_app_description" msgid="5894852887817332322">"Праграма \"<xliff:g id="OLD_APP">%1$s</xliff:g>\" будзе закрыта. Даныя не будуць захаваны"</string>
<string name="dump_heap_notification" msgid="2618183274836056542">"Працэс <xliff:g id="PROC">%1$s</xliff:g> перавысіў ліміт памяці"</string>
<string name="dump_heap_notification_detail" msgid="6901391084243999274">"Быў сабраны дамп кучы; дакраніцеся, каб абагуліць"</string>
<string name="dump_heap_title" msgid="5864292264307651673">"Абагуліць дамп дынамічнай вобласці?"</string>
@@ -1182,7 +1193,8 @@
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не атрымалася падключыцца да адкрытай сеткі Wi‑Fi"</string>
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Дакраніцеся, каб убачыць усе сеткі"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Падключыцца"</string>
- <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Усе сеткі"</string>
+ <!-- no translation found for wifi_available_action_all_networks (4368435796357931006) -->
+ <skip />
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi уключыцца аўтаматычна"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Побач з захаванай сеткай з высакаякасным сігналам"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не ўключаць зноў"</string>
@@ -1248,6 +1260,7 @@
<string name="sim_restart_button" msgid="4722407842815232347">"Перазапусціць"</string>
<string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Уключыць мабільную сувязь"</string>
<string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Спампаваць праграму аператара для актывацыі новай SIM-карты"</string>
+ <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Для актывацыі новай SIM-карты спампуйце праграму <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="install_carrier_app_notification_button" msgid="3094206295081900849">"Спампаваць праграму"</string>
<string name="carrier_app_notification_title" msgid="8921767385872554621">"Устаўлена новая SIM-карта"</string>
<string name="carrier_app_notification_text" msgid="1132487343346050225">"Краніце, каб наладзіць"</string>
@@ -1291,7 +1304,7 @@
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> паказваецца паверх іншых праграм"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> паказв. паверх іншых праграм"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць гэта."</string>
- <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"АДКЛЮЧЫЦЬ"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Выключыць"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Падрыхтоўка <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Праверка на наяўнасць памылак"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Выяўлены новы носьбіт <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1464,22 +1477,19 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"USB-дыск <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-назапашвальнік"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Рэдагаваць"</string>
- <string name="data_usage_warning_title" msgid="3620440638180218181">"Абвестка аб выкарыстанні трафіка"</string>
- <string name="data_usage_warning_body" msgid="6660692274311972007">"Прагляд выкарыстання і налад."</string>
- <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Дасягнуты ліміт трафіку 2G-3G"</string>
- <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Дасягнуты ліміт трафіку 4G"</string>
+ <string name="data_usage_warning_title" msgid="6499834033204801605">"Папярэджанне аб перавышэнні ліміту трафіка"</string>
+ <string name="data_usage_warning_body" msgid="7340198905103751676">"Вы выкарысталі <xliff:g id="APP">%s</xliff:g> даных"</string>
<string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Дасягн. ліміт маб. перад. даных"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Дасягн. ліміт перад. даных Wi-Fi"</string>
- <string name="data_usage_limit_body" msgid="291731708279614081">"Перад.даных спын. да канца цыкла"</string>
- <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Перавышаны ліміт 2G-3G"</string>
- <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Перавышаны ліміт дадзеных 4G"</string>
- <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Перавышаны ліміт мабільных дадзеных"</string>
- <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Перав. ліміт па дадзеным Wi-Fi"</string>
- <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Аб\'ём <xliff:g id="SIZE">%s</xliff:g> перавышае устаноўл. мяжу."</string>
+ <string name="data_usage_limit_body" msgid="2908179506560812973">"Выкарыстанне даных прыпынена да канца цыкла"</string>
+ <string name="data_usage_mobile_limit_snoozed_title" msgid="3171402244827034372">"Перавышаны ліміт мабільных даных"</string>
+ <string name="data_usage_wifi_limit_snoozed_title" msgid="3547771791046344188">"Перавышаны ліміт трафіка Wi-Fi"</string>
+ <string name="data_usage_limit_snoozed_body" msgid="1671222777207603301">"Вы перавысілі ліміт на <xliff:g id="SIZE">%s</xliff:g>"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Зыходныя дадзеныя абмежаваныя"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Дакраніцеся, каб зняць абмежав."</string>
- <string name="data_usage_rapid_title" msgid="4579994056245665351">"Значнае выкарыстанне трафіка"</string>
- <string name="data_usage_rapid_body" msgid="4899922842674185567">"У апошнія некалькі дзён вы выкарысталі больш трафіку, чым звычайна. Націсніце для прагляду выкарыстання і налад."</string>
+ <string name="data_usage_rapid_title" msgid="1809795402975261331">"Інтэнсіўнае выкарыстанне трафіка"</string>
+ <string name="data_usage_rapid_body" msgid="6897825788682442715">"Праграмы выкарысталі больш даных, чым звычайна"</string>
+ <string name="data_usage_rapid_app_body" msgid="5396680996784142544">"У праграме <xliff:g id="APP">%s</xliff:g> было выкарыстана больш даных, чым звычайна"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Сертыфікат бяспекі"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Гэты сертыфікат сапраўдны."</string>
<string name="issued_to" msgid="454239480274921032">"Каму выдадзена:"</string>
diff --git a/core/res/res/values-mcc001-mnc01-as/strings.xml b/core/res/res/values-mcc001-mnc01-as/strings.xml
new file mode 100644
index 0000000..93b8fc7
--- /dev/null
+++ b/core/res/res/values-mcc001-mnc01-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_illegal_me" msgid="2238090225563073546">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-as/strings.xml b/core/res/res/values-mcc302-mnc370-as/strings.xml
new file mode 100644
index 0000000..c0ad316
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s ৱাই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-as/strings.xml b/core/res/res/values-mcc302-mnc720-as/strings.xml
new file mode 100644
index 0000000..0ab4dac
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s ৱাই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc030-as/strings.xml b/core/res/res/values-mcc310-mnc030-as/strings.xml
new file mode 100644
index 0000000..27953b8
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc030-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="2995576894416087107">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc150-as/strings.xml b/core/res/res/values-mcc310-mnc150-as/strings.xml
new file mode 100644
index 0000000..174cfe3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc150-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_illegal_me" msgid="5207603948149789531">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc170-as/strings.xml b/core/res/res/values-mcc310-mnc170-as/strings.xml
new file mode 100644
index 0000000..37b727b
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc170-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="3173546391131606065">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc280-as/strings.xml b/core/res/res/values-mcc310-mnc280-as/strings.xml
new file mode 100644
index 0000000..3bc3c1f
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc280-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="822496463303720579">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc380-as/strings.xml b/core/res/res/values-mcc310-mnc380-as/strings.xml
new file mode 100644
index 0000000..4c4a705
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc380-as/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ছিমৰ অনুমতি নাই MM#3"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc410-as/strings.xml b/core/res/res/values-mcc310-mnc410-as/strings.xml
new file mode 100644
index 0000000..94b9726
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc410-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="4477688981805467729">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc560-as/strings.xml b/core/res/res/values-mcc310-mnc560-as/strings.xml
new file mode 100644
index 0000000..6365190
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc560-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="7030488670186895244">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc950-as/strings.xml b/core/res/res/values-mcc310-mnc950-as/strings.xml
new file mode 100644
index 0000000..7a3af72
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc950-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="8920048244573695129">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc180-as/strings.xml b/core/res/res/values-mcc311-mnc180-as/strings.xml
new file mode 100644
index 0000000..868c39b
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc180-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="97745044956236881">"ছিমৰ অনুমতি নাই MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="5766888847785331904">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc312-mnc670-as/strings.xml b/core/res/res/values-mcc312-mnc670-as/strings.xml
new file mode 100644
index 0000000..534d4e1
--- /dev/null
+++ b/core/res/res/values-mcc312-mnc670-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_illegal_me" msgid="3649306773478362802">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mcc313-mnc100-as/strings.xml b/core/res/res/values-mcc313-mnc100-as/strings.xml
new file mode 100644
index 0000000..350757c
--- /dev/null
+++ b/core/res/res/values-mcc313-mnc100-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="mmcc_illegal_me" msgid="7320955531336937252">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-or-watch/strings.xml b/core/res/res/values-or-watch/strings.xml
new file mode 100644
index 0000000..4498c95
--- /dev/null
+++ b/core/res/res/values-or-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଆପ୍ରୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଟି।"</string>
+ <string name="permgrouplab_sensors" msgid="202675452368612754">"ସେନ୍ସର୍"</string>
+</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
new file mode 100644
index 0000000..ccfc523
--- /dev/null
+++ b/core/res/res/values-or/strings.xml
@@ -0,0 +1,2133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
+ <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
+ <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+ <string name="untitled" msgid="4638956954852782576">"<ନାମହୀନ>"</string>
+ <string name="emptyPhoneNumber" msgid="7694063042079676517">"(କୌଣସି ଫୋନ୍ ନମ୍ବର ନାହିଁ)"</string>
+ <string name="unknownName" msgid="6867811765370350269">"ଅଜଣା"</string>
+ <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ଭଏସ୍ ମେଲ୍"</string>
+ <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
+ <string name="mmiError" msgid="5154499457739052907">"ସଂଯୋଗରେ ସମସ୍ୟା ଅଛି କିମ୍ବା ଅମାନ୍ୟ MMI କୋଡ୍।"</string>
+ <string name="mmiFdnError" msgid="5224398216385316471">"କେବଳ ସ୍ଥାୟୀ ଡାୟଲିଙ୍ଗ ନମ୍ବର୍ ପାଇଁ କାର୍ଯ୍ୟ ସୀମିତ ଅଟେ।"</string>
+ <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"ଆପଣ ରୋମିଙ୍ଗରେ ଥିବାବେଳେ କଲ୍ ଫର୍ୱର୍ଡିଙ୍ଗ ସେଟିଙ୍ଗ ବଦଳାଇପାରିବେ ନାହିଁ।"</string>
+ <string name="serviceEnabled" msgid="8147278346414714315">"ସେବା ସକ୍ଷମ କରାଯାଇଥିଲା।"</string>
+ <string name="serviceEnabledFor" msgid="6856228140453471041">"ଏଥିପାଇଁ ସେବା ସକ୍ଷମ କରାଯାଇଥିଲା:"</string>
+ <string name="serviceDisabled" msgid="1937553226592516411">"ସେବାକୁ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।"</string>
+ <string name="serviceRegistered" msgid="6275019082598102493">"ପଞ୍ଜିକରଣ ସଫଳ ହେଲା।"</string>
+ <string name="serviceErased" msgid="1288584695297200972">"ଲିଭାଇବା ସଫଳ ହେଲା।"</string>
+ <string name="passwordIncorrect" msgid="7612208839450128715">"ଭୁଲ ପାସୱର୍ଡ।"</string>
+ <string name="mmiComplete" msgid="8232527495411698359">"MMI ସମ୍ପୂର୍ଣ୍ଣ।"</string>
+ <string name="badPin" msgid="9015277645546710014">"ଆପଣ ଟାଇପ୍ କରିଥିବା ପୁରୁଣା PIN ଭୁଲ ଅଟେ।"</string>
+ <string name="badPuk" msgid="5487257647081132201">"ଆପଣ ଟାଇପ୍ କରିଥିବା PUK ଭୁଲ ଅଟେ।"</string>
+ <string name="mismatchPin" msgid="609379054496863419">"ଆପଣ ଟାଇପ୍ କରିଥିବା PINଗୁଡ଼ିକ ମେଳ ହେଉନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="invalidPin" msgid="3850018445187475377">"4 ରୁ 8ଟି ସଂଖ୍ୟା ବିଶିଷ୍ଟ ଏକ PIN ଟାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"ଏକ PUK ଟାଇପ୍ କରନ୍ତୁ, ଯାହାକି 8 ସଂଖ୍ୟା ବିଶିଷ୍ଟ କିମ୍ୱା ତା’ଠାରୁ ଅଧିକ ହୋଇଥିବ।"</string>
+ <string name="needPuk" msgid="919668385956251611">"ଆପଣଙ୍କ SIM କାର୍ଡ PUK ଲକ୍ ଅଛି। ଏହାକୁ ଅନଲକ୍ କରିବାକୁ PUK କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="needPuk2" msgid="4526033371987193070">"SIM କାର୍ଡରୁ ଅବରୋଧ ହଟାଇବା ପାଇଁ PUK2 ଟାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="enablePin" msgid="209412020907207950">"ସଫଳ ହେଲାନାହିଁ, SIM/RUIM ଲକ୍ କରନ୍ତୁ।"</string>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">ଆଉ <xliff:g id="NUMBER_1">%d</xliff:g>ଟି ପ୍ରୟାସ ପରେ SIM ଲକ୍ ହୋଇଯିବ।</item>
+ <item quantity="one">ଆଉ <xliff:g id="NUMBER_0">%d</xliff:g>ଟି ପ୍ରୟାସ ପରେ SIM ଲକ୍ ହୋଇଯିବ।</item>
+ </plurals>
+ <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+ <string name="meid" msgid="4841221237681254195">"MEID"</string>
+ <string name="ClipMmi" msgid="6952821216480289285">"ଇନକମିଙ୍ଗ କଲର୍ ଆଇଡି"</string>
+ <string name="ClirMmi" msgid="7784673673446833091">"ଆଉଟଗୋଇଙ୍ଗ୍ କଲର୍ ଆଇଡି"</string>
+ <string name="ColpMmi" msgid="3065121483740183974">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID"</string>
+ <string name="ColrMmi" msgid="4996540314421889589">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID କଟକଣା"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"କଲ୍ ଫରୱାର୍ଡିଙ୍ଗ"</string>
+ <string name="CwMmi" msgid="9129678056795016867">"କଲ୍ ଅପେକ୍ଷାରତ"</string>
+ <string name="BaMmi" msgid="455193067926770581">"କଲ୍ ବ୍ୟାରିଙ୍ଗ୍"</string>
+ <string name="PwdMmi" msgid="7043715687905254199">"ପାସ୍ୱର୍ଡ ପରିବର୍ତ୍ତନ"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"PIN ପରିବର୍ତ୍ତନ"</string>
+ <string name="CnipMmi" msgid="3110534680557857162">"କଲିଙ୍ଗ ନମ୍ୱର୍ ଉପସ୍ଥିତ"</string>
+ <string name="CnirMmi" msgid="3062102121430548731">"କଲିଙ୍ଗ ନମ୍ବର୍ ପ୍ରତିବନ୍ଧିତ"</string>
+ <string name="ThreeWCMmi" msgid="9051047170321190368">"ତିନି ପ୍ରକାରରେ କଲିଙ୍ଗ"</string>
+ <string name="RuacMmi" msgid="7827887459138308886">"ଅବାଞ୍ଛିତ ଅଜଣା କଲ୍ଗୁଡ଼ିକର ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
+ <string name="CndMmi" msgid="3116446237081575808">"କଲିଙ୍ଗ ନମ୍ବର୍ ଡେଲିଭରୀ"</string>
+ <string name="DndMmi" msgid="1265478932418334331">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ ନୁହେଁ"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ ନୁହେଁ"</string>
+ <string name="serviceNotProvisioned" msgid="8614830180508686666">"ସେବାର ସୁବିଧା ନାହିଁ।"</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"ଆପଣ କଲର୍ ID ସେଟିଙ୍ଗ ବଦଳାଇପାରିବେ ନାହିଁ।"</string>
+ <!-- no translation found for RestrictedOnDataTitle (1322504692764166532) -->
+ <skip />
+ <!-- no translation found for RestrictedOnEmergencyTitle (3646729271176394091) -->
+ <skip />
+ <!-- no translation found for RestrictedOnNormalTitle (3179574012752700984) -->
+ <skip />
+ <!-- no translation found for RestrictedOnAllVoiceTitle (158800171499150681) -->
+ <skip />
+ <!-- no translation found for RestrictedStateContent (4278821484643362350) -->
+ <skip />
+ <string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"ନେଟ୍ୱର୍କ ପର୍ଯ୍ୟନ୍ତ ପହଞ୍ଚିପାରୁ ନାହିଁ"</string>
+ <!-- no translation found for NetworkPreferenceSwitchSummary (7056776609127756440) -->
+ <skip />
+ <!-- no translation found for EmergencyCallWarningTitle (4790413876281901612) -->
+ <skip />
+ <!-- no translation found for EmergencyCallWarningSummary (8973232888021643293) -->
+ <skip />
+ <!-- no translation found for notification_channel_network_alert (4427736684338074967) -->
+ <skip />
+ <!-- no translation found for notification_channel_call_forward (2419697808481833249) -->
+ <skip />
+ <!-- no translation found for notification_channel_emergency_callback (6686166232265733921) -->
+ <skip />
+ <!-- no translation found for notification_channel_mobile_data_status (4575131690860945836) -->
+ <skip />
+ <!-- no translation found for notification_channel_sms (3441746047346135073) -->
+ <skip />
+ <!-- no translation found for notification_channel_voice_mail (3954099424160511919) -->
+ <skip />
+ <!-- no translation found for notification_channel_wfc (2130802501654254801) -->
+ <skip />
+ <!-- no translation found for notification_channel_sim (4052095493875188564) -->
+ <skip />
+ <string name="peerTtyModeFull" msgid="6165351790010341421">"ପୀଆର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ FULL ଅଟେ"</string>
+ <string name="peerTtyModeHco" msgid="5728602160669216784">"ପୀଅର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ HCO ଅଟେ"</string>
+ <string name="peerTtyModeVco" msgid="1742404978686538049">"ପୀଅର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ VCO ଅଟେ"</string>
+ <string name="peerTtyModeOff" msgid="3280819717850602205">"ପୀଅର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ OFF ଅଛି"</string>
+ <string name="serviceClassVoice" msgid="1258393812335258019">"ଭଏସ୍"</string>
+ <string name="serviceClassData" msgid="872456782077937893">"ଡାଟା"</string>
+ <string name="serviceClassFAX" msgid="5566624998840486475">"ଫାକ୍ସ"</string>
+ <string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
+ <string name="serviceClassDataAsync" msgid="4523454783498551468">"ଏସିଙ୍କ୍"</string>
+ <string name="serviceClassDataSync" msgid="7530000519646054776">"ସିଙ୍କ୍"</string>
+ <string name="serviceClassPacket" msgid="6991006557993423453">"ପ୍ୟାକେଟ୍"</string>
+ <string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
+ <string name="roamingText0" msgid="7170335472198694945">"ରୋମିଙ୍ଗ ସୂଚକ ଅନ୍ ଅଛି"</string>
+ <string name="roamingText1" msgid="5314861519752538922">"ରୋମିଙ୍ଗ ସୂଚକ ଅଫ୍ ଅଛି"</string>
+ <string name="roamingText2" msgid="8969929049081268115">"ରୋମିଙ୍ଗ ସୂଚକ ଧପ୍ ଧପ୍ ହେଉଛି"</string>
+ <string name="roamingText3" msgid="5148255027043943317">"ନିକଟସ୍ଥ ଅଞ୍ଚଳ ବାହାରେ"</string>
+ <string name="roamingText4" msgid="8808456682550796530">"ବିଲଡିଙ୍ଗ ବାହାରେ"</string>
+ <string name="roamingText5" msgid="7604063252850354350">"ରୋମିଙ୍ଗ - ପସନ୍ଦର ସିଷ୍ଟମ୍"</string>
+ <string name="roamingText6" msgid="2059440825782871513">"ରୋମିଙ୍ଗ - ଉପଲବ୍ଧ ସେବା"</string>
+ <string name="roamingText7" msgid="7112078724097233605">"ରୋମିଙ୍ଗ - ଆଲାୟାନ୍ସ ପାର୍ଟନର୍"</string>
+ <string name="roamingText8" msgid="5989569778604089291">"ରୋମିଙ୍ଗ - ପ୍ରିମିୟମ୍ ପାର୍ଟନର୍"</string>
+ <string name="roamingText9" msgid="7969296811355152491">"ରୋମିଙ୍ଗ - ସମ୍ପୂର୍ଣ୍ଣ ସେବା କାର୍ଯ୍ୟକ୍ଷମତା"</string>
+ <string name="roamingText10" msgid="3992906999815316417">"ରୋମିଙ୍ଗ - ଆଂଶିକ ସେବା କାର୍ଯ୍ୟକ୍ଷମତା"</string>
+ <string name="roamingText11" msgid="4154476854426920970">"ରୋମିଙ୍ଗ ବ୍ୟାନର୍ ଅନ୍ ଅଛି"</string>
+ <string name="roamingText12" msgid="1189071119992726320">"ରୋମିଙ୍ଗ ବ୍ୟାନର୍ ଅଫ୍ ଅଛି"</string>
+ <string name="roamingTextSearching" msgid="8360141885972279963">"ସେବା ଖୋଜାଯାଉଛି"</string>
+ <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ୱାଇ-ଫାଇ କଲିଙ୍ଗ"</string>
+ <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
+ <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (7472393097168811593) -->
+ <!-- no translation found for wfcSpnFormats:0 (6830082633573257149) -->
+ <!-- no translation found for wfcSpnFormats:1 (4397097370387921767) -->
+ <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ଅଫ୍"</string>
+ <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ପସନ୍ଦ କରାଯାଇଥିବା ୱାଇ-ଫାଇ"</string>
+ <!-- no translation found for wfc_mode_cellular_preferred_summary (1988279625335345908) -->
+ <skip />
+ <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"କେବଳ ୱାଇ-ଫାଇ"</string>
+ <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
+ <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
+ <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ସେକେଣ୍ଡ ପରେ"</string>
+ <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
+ <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫର୍ୱର୍ଡ କରାଗଲା ନାହିଁ"</string>
+ <string name="fcComplete" msgid="3118848230966886575">"ଫିଚର୍ କୋଡ୍ ସମ୍ପୂର୍ଣ୍ଣ।"</string>
+ <string name="fcError" msgid="3327560126588500777">"ସଂଯୋଗରେ ସମସ୍ୟା କିମ୍ୱା ଅମାନ୍ୟ ଫିଚର୍ କୋଡ୍।"</string>
+ <string name="httpErrorOk" msgid="1191919378083472204">"ଠିକ୍ ଅଛି"</string>
+ <string name="httpError" msgid="7956392511146698522">"ନେଟ୍ୱର୍କରେ ଏକ ତ୍ରୁଟି ଥିଲା।"</string>
+ <string name="httpErrorLookup" msgid="4711687456111963163">"URL ମିଳିଲା ନାହିଁ।"</string>
+ <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"ସାଇଟ୍ ପ୍ରମାଣୀକରଣ ସ୍କିମ୍ ସପୋର୍ଟ କରୁନାହିଁ।"</string>
+ <string name="httpErrorAuth" msgid="1435065629438044534">"ସ୍ୱୀକୃତି ଦେଇପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorProxyAuth" msgid="1788207010559081331">"ପ୍ରୋକ୍ସୀ ସର୍ଭର୍ ଦ୍ୱାରା ସ୍ୱୀକୃତି ଦିଆଯାଇପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorConnect" msgid="8714273236364640549">"ସର୍ଭର୍ ସହ ସଂଯୋଗ କରିପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorIO" msgid="2340558197489302188">"ସର୍ଭର୍ ସହ ଯୋଗାଯୋଗ କରିପାରିଲା ନାହିଁ। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="httpErrorTimeout" msgid="4743403703762883954">"ସର୍ଭରକୁ ସଂଯୋଗର ସମୟ ସୀମା ସମାପ୍ତ ହୋଇଯାଇଛି।"</string>
+ <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"ଏହି ପୃଷ୍ଠାରେ ବହୁତ ସର୍ଭର୍ ରିଡାଇରେକ୍ଟ ରହିଛି।"</string>
+ <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"ପ୍ରୋଟୋକଲ୍ ସପୋର୍ଟ କରୁନାହିଁ।"</string>
+ <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"ଏକ ନିରାପଦ ସଂଯୋଗ ସ୍ଥାପନ କରିପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorBadUrl" msgid="3636929722728881972">"URL ବୈଧ ନଥିବାରୁ ପୃଷ୍ଠାଟି ଖୋଲିପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorFile" msgid="2170788515052558676">"ଫାଇଲ୍ ଆକ୍ସେସ୍ କରିପାରିଲା ନାହିଁ।"</string>
+ <string name="httpErrorFileNotFound" msgid="6203856612042655084">"ଅନୁରୋଧ କରାଯାଇଥିବା ଫାଇଲ୍ ପାଇଲା ନାହିଁ।"</string>
+ <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"ଅନେକ ଅନୁରୋଧ ଉପରେ କାମ ଚାଲୁଛି। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g>ରେ ସାଇନ୍-ଇନ୍ ତ୍ରୁଟି"</string>
+ <string name="contentServiceSync" msgid="8353523060269335667">"ସିଙ୍କ୍"</string>
+ <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ସିଙ୍କ୍"</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"ଅତ୍ୟଧିକ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ଡିଲିଟ୍ କରିଦିଏ।"</string>
+ <string name="low_memory" product="tablet" msgid="6494019234102154896">"ଟାବଲେଟ୍ ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବା ପାଇଁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ୱାଚ୍ ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବାକୁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"ଟିଭିର ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ପେସ୍ ଖାଲି କରିବାକୁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="low_memory" product="default" msgid="3475999286680000541">"ଫୋନ୍ ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବା ପାଇଁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for ssl_ca_cert_warning (5106721205300213569) -->
+ <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ଅଜଣା ତୃତୀୟ ପକ୍ଷ ଅନୁଯାୟୀ"</string>
+ <!-- no translation found for ssl_ca_cert_noti_by_administrator (3541729986326153557) -->
+ <skip />
+ <string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> ଅନୁଯାୟୀ"</string>
+ <string name="work_profile_deleted" msgid="5005572078641980632">"ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଡିଲିଟ୍ ହେଲା"</string>
+ <!-- no translation found for work_profile_deleted_description (1100529432509639864) -->
+ <skip />
+ <!-- no translation found for work_profile_deleted_details (6307630639269092360) -->
+ <skip />
+ <!-- no translation found for work_profile_deleted_description_dpm_wipe (8823792115612348820) -->
+ <skip />
+ <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
+ <skip />
+ <!-- no translation found for network_logging_notification_title (6399790108123704477) -->
+ <skip />
+ <!-- no translation found for network_logging_notification_text (7930089249949354026) -->
+ <skip />
+ <string name="factory_reset_warning" msgid="5423253125642394387">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string>
+ <!-- no translation found for factory_reset_message (9024647691106150160) -->
+ <skip />
+ <!-- no translation found for printing_disabled_by (8936832919072486965) -->
+ <skip />
+ <string name="me" msgid="6545696007631404292">"ମୁଁ"</string>
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"ଟାବଲେଟ୍ର ବିକଳ୍ପ"</string>
+ <string name="power_dialog" product="tv" msgid="6153888706430556356">"ଟିଭି ବିକଳ୍ପଗୁଡ଼ିକ"</string>
+ <string name="power_dialog" product="default" msgid="1319919075463988638">"ଫୋନ୍ ବିକଳ୍ପ"</string>
+ <string name="silent_mode" msgid="7167703389802618663">"ସାଇଲେଣ୍ଟ ମୋଡ୍"</string>
+ <string name="turn_on_radio" msgid="3912793092339962371">"ୱେୟାରଲେସ୍କୁ ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="turn_off_radio" msgid="8198784949987062346">"ୱେୟାରଲେସ୍କୁ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="screen_lock" msgid="799094655496098153">"ସ୍କ୍ରୀନ୍ ଲକ୍"</string>
+ <string name="power_off" msgid="4266614107412865048">"ପାୱାର୍ ଅଫ୍"</string>
+ <string name="silent_mode_silent" msgid="319298163018473078">"ରିଙ୍ଗର୍ ଅଫ୍ ଅଛି"</string>
+ <string name="silent_mode_vibrate" msgid="7072043388581551395">"ରିଙ୍ଗର୍ କମ୍ପନ"</string>
+ <string name="silent_mode_ring" msgid="8592241816194074353">"ରିଙ୍ଗର୍ ଅନ୍ ଅଛି"</string>
+ <string name="reboot_to_update_title" msgid="6212636802536823850">"Android ସିଷ୍ଟମ୍ ଅପଡେଟ୍"</string>
+ <string name="reboot_to_update_prepare" msgid="6305853831955310890">"ଅପଡେଟ୍ କରିବାକୁ ପ୍ରସ୍ତୁତ କରାଯାଉଛି…"</string>
+ <string name="reboot_to_update_package" msgid="3871302324500927291">"ଅପଡେଟ୍ ପ୍ୟାକେଜ୍ ପ୍ରୋସେସ୍ କରାଯାଉଛି…"</string>
+ <string name="reboot_to_update_reboot" msgid="6428441000951565185">"ରିଷ୍ଟାର୍ଟ କରାଯାଉଛି…"</string>
+ <string name="reboot_to_reset_title" msgid="4142355915340627490">"ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍"</string>
+ <string name="reboot_to_reset_message" msgid="2432077491101416345">"ରିଷ୍ଟାର୍ଟ କରାଯାଉଛି…"</string>
+ <string name="shutdown_progress" msgid="2281079257329981203">"ବନ୍ଦ କରାଯାଉଛି…"</string>
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ଆପଣଙ୍କ ଟାବଲେଟ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
+ <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"ଆପଣଙ୍କ ଟିଭି ବନ୍ଦ ହେବ।"</string>
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ଆପଣଙ୍କ ଘଣ୍ଟା ବନ୍ଦ ହୋଇଯିବ।"</string>
+ <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ଆପଣଙ୍କ ଫୋନ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"ଆପଣ ବନ୍ଦ କରିବାକୁ ଚାହାନ୍ତି?"</string>
+ <string name="reboot_safemode_title" msgid="7054509914500140361">"ନିରାପଦ ମୋଡ୍ରେ ରିବୁଟ୍ କରନ୍ତୁ"</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"ଆପଣ ନିରାପଦ ମୋଡ୍ରେ ରିବୁଟ୍ କରିବେ କି? ଆପଣ ଇନଷ୍ଟଲ୍ କରିଥିବା ସମସ୍ତ ତୃତୀୟ ପକ୍ଷ ଆପ୍ଲିକେଶନ୍, ଏହାଦ୍ୱାରା ଅକ୍ଷମ ହୋଇଯିବ। ଆପଣ ପୁଣି ରିବୁଟ୍ କରିବା ପରେ ସେଗୁଡ଼ିକ ରିଷ୍ଟୋର୍ ହେବ।"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"କିଛି ସମୟ ପୂର୍ବରୁ"</string>
+ <string name="no_recent_tasks" msgid="8794906658732193473">"କୌଣସି ସମ୍ପ୍ରତି ଆପ୍ ନାହିଁ।"</string>
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"ଟାବଲେଟ ବିକଳ୍ପ"</string>
+ <string name="global_actions" product="tv" msgid="7240386462508182976">"ଟିଭିର ବିକଳ୍ପ"</string>
+ <string name="global_actions" product="default" msgid="2406416831541615258">"ଫୋନ ବିକଳ୍ପ"</string>
+ <string name="global_action_lock" msgid="2844945191792119712">"ସ୍କ୍ରୀନ୍ ଲକ୍"</string>
+ <string name="global_action_power_off" msgid="4471879440839879722">"ପାୱାର୍ ଅଫ୍"</string>
+ <string name="global_action_emergency" msgid="7112311161137421166">"ଜରୁରୀକାଳୀନ"</string>
+ <string name="global_action_bug_report" msgid="7934010578922304799">"ବଗ୍ ରିପୋର୍ଟ"</string>
+ <!-- no translation found for global_action_logout (935179188218826050) -->
+ <skip />
+ <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+ <skip />
+ <string name="bugreport_title" msgid="2667494803742548533">"ବଗ୍ ରିପୋର୍ଟ ନିଅନ୍ତୁ"</string>
+ <string name="bugreport_message" msgid="398447048750350456">"ଇ-ମେଲ୍ ମେସେଜ୍ ଭାବରେ ପଠାଇବାକୁ, ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ଡିଭାଇସ୍ ବିଷୟରେ ଏହା ସୂଚନା ସଂଗ୍ରହ କରିବ। ବଗ୍ ରିପୋର୍ଟ ଆରମ୍ଭ ହେବାପରଠାରୁ ଏହାକୁ ପଠାଇବା ପାଇଁ କିଛି ସମୟ ଲାଗିବ, ଦୟାକରି ଧୈର୍ଯ୍ୟ ରଖନ୍ତୁ।"</string>
+ <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ଇଣ୍ଟରାକ୍ଟିଭ୍ ରିପୋର୍ଟ"</string>
+ <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"ଅଧିକାଂଶ କ୍ଷେତ୍ରରେ ଏହା ବ୍ୟବହାର କରନ୍ତୁ। ଏହାଦ୍ୱାରା ଆପଣ ରିପୋର୍ଟର ପ୍ରଗତିକୁ ଟ୍ରାକ୍ କରିପାରିବେ, ସମସ୍ୟା ଉପରେ ଅଧିକ ବିବରଣୀ ଲେଖିପାରିବେ ଏବଂ ସ୍କ୍ରୀନଶଟ୍ ନେଇପାରିବେ। ଏହା କିଛି କମ୍-ବ୍ୟବହାର କରାଯାଇଥିବା ବିଭାଗକୁ ଛାଡ଼ିଦେଇପାରେ, ଯାହା ରିପୋର୍ଟ କରିବାକୁ ଅଧିକ ସମୟ ନିଏ।"</string>
+ <string name="bugreport_option_full_title" msgid="6354382025840076439">"ପୂର୍ଣ୍ଣ ରିପୋର୍ଟ"</string>
+ <string name="bugreport_option_full_summary" msgid="7210859858969115745">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ପ୍ରତିକ୍ରିୟା ଦେଉନଥିବାବେଳେ କିମ୍ବା ବହୁତ ଧୀରେ ଚାଲୁଥିବାବେଳେ କିମ୍ବା ଆପଣ ସମସ୍ତ ରିପୋର୍ଟ ବିଭାଗ ଆବଶ୍ୟକ କରିବାବେଳେ ସିଷ୍ଟମର କମ୍ ହସ୍ତକ୍ଷେପ ପାଇଁ ଏହି ବିକଳ୍ପ ବ୍ୟବହାର କରନ୍ତୁ। ଅଧିକ ବିବରଣୀ ଲେଖିବାକୁ କିମ୍ବା ଅତିରିକ୍ତ ସ୍କ୍ରୀନଶଟ୍ ନେବାକୁ ଅନୁମତି ଦିଏନାହିଁ।"</string>
+ <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
+ <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> ସେକେଣ୍ଡରେ ବଗ୍ ରିପୋର୍ଟ ପାଇଁ ସ୍କ୍ରୀନଶଟ୍ ନେଉଛି।</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> ସେକେଣ୍ଡରେ ବଗ୍ ରିପୋର୍ଟ ପାଇଁ ସ୍କ୍ରୀନଶଟ୍ ନେଉଛି।</item>
+ </plurals>
+ <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"ସାଇଲେଣ୍ଟ ମୋଡ୍"</string>
+ <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ସାଉଣ୍ଡ ଅଫ୍ ଅଛି"</string>
+ <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"ସାଉଣ୍ଡ ଅନ୍ ଅଛି"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍"</string>
+ <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍ ଅନ୍ ଅଛି"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍ ଅଫ୍ ଅଛି"</string>
+ <!-- no translation found for global_action_toggle_battery_saver (708515500418994208) -->
+ <skip />
+ <!-- no translation found for global_action_battery_saver_on_status (484059130698197787) -->
+ <skip />
+ <!-- no translation found for global_action_battery_saver_off_status (75550964969478405) -->
+ <skip />
+ <string name="global_action_settings" msgid="1756531602592545966">"ସେଟିଙ୍ଗ"</string>
+ <string name="global_action_assist" msgid="3892832961594295030">"ସହାୟକ"</string>
+ <string name="global_action_voice_assist" msgid="7751191495200504480">"ଭଏସ୍ ସହାୟକ"</string>
+ <!-- no translation found for global_action_lockdown (1099326950891078929) -->
+ <skip />
+ <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+ <!-- no translation found for notification_hidden_text (6351207030447943784) -->
+ <skip />
+ <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+ <skip />
+ <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+ <skip />
+ <!-- no translation found for notification_channel_security (7345516133431326347) -->
+ <skip />
+ <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+ <skip />
+ <!-- no translation found for notification_channel_account (7577959168463122027) -->
+ <skip />
+ <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+ <skip />
+ <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+ <skip />
+ <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+ <skip />
+ <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+ <skip />
+ <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
+ <skip />
+ <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+ <skip />
+ <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+ <skip />
+ <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
+ <skip />
+ <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+ <skip />
+ <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+ <skip />
+ <!-- no translation found for notification_channel_heavy_weight_app (6218742927792852607) -->
+ <skip />
+ <!-- no translation found for notification_channel_foreground_service (3931987440602669158) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (1060198778219731292) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7175032677643332242) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
+ <string name="safeMode" msgid="2788228061547930246">"ସୁରକ୍ଷିତ ମୋଡ୍"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android ସିଷ୍ଟମ୍"</string>
+ <!-- no translation found for user_owner_label (8836124313744349203) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (8947929265267690522) -->
+ <skip />
+ <string name="permgrouplab_contacts" msgid="3657758145679177612">"ଯୋଗାଯୋଗ"</string>
+ <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ଆକ୍ସେସ୍ କରେ"</string>
+ <!-- no translation found for permgrouprequest_contacts (1601591667800538208) -->
+ <skip />
+ <string name="permgrouplab_location" msgid="7275582855722310164">"ଲୋକେଶନ୍"</string>
+ <string name="permgroupdesc_location" msgid="1346617465127855033">"ଏହି ଡିଭାଇସ୍ର ଲୋକେଶନ୍ ଆକ୍ସେସ୍ କରେ"</string>
+ <!-- no translation found for permgrouprequest_location (8903573681261610809) -->
+ <skip />
+ <string name="permgrouplab_calendar" msgid="5863508437783683902">"କ୍ୟାଲେଣ୍ଡର୍"</string>
+ <string name="permgroupdesc_calendar" msgid="3889615280211184106">"ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର୍ ଆକ୍ସେସ୍ କରେ"</string>
+ <!-- no translation found for permgrouprequest_calendar (6704529828699071445) -->
+ <skip />
+ <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
+ <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS ମେସେଜ୍ ପଠାନ୍ତୁ ଓ ଦେଖନ୍ତୁ"</string>
+ <!-- no translation found for permgrouprequest_sms (605618939583628306) -->
+ <skip />
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"ଷ୍ଟୋରେଜ୍"</string>
+ <string name="permgroupdesc_storage" msgid="637758554581589203">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଥିବା ଫଟୋ, ମିଡିଆ ଓ ଫାଇଲ୍ ଆକ୍ସେସ୍ କରେ"</string>
+ <!-- no translation found for permgrouprequest_storage (7429669910547860218) -->
+ <skip />
+ <string name="permgrouplab_microphone" msgid="171539900250043464">"ମାଇକ୍ରୋଫୋନ୍"</string>
+ <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ଅଡିଓ ରେକର୍ଡ କରେ"</string>
+ <!-- no translation found for permgrouprequest_microphone (8065941268709600606) -->
+ <skip />
+ <string name="permgrouplab_camera" msgid="4820372495894586615">"କ୍ୟାମେରା"</string>
+ <string name="permgroupdesc_camera" msgid="3250611594678347720">"ଫଟୋ ନିଏ ଓ ଭିଡିଓ ରେକର୍ଡ କରେ"</string>
+ <!-- no translation found for permgrouprequest_camera (810824326507258410) -->
+ <skip />
+ <string name="permgrouplab_phone" msgid="5229115638567440675">"ଫୋନ୍"</string>
+ <string name="permgroupdesc_phone" msgid="6234224354060641055">"ଫୋନ୍ କଲ୍ କରେ ଏବଂ ପରିଚାଳନା କରେ"</string>
+ <!-- no translation found for permgrouprequest_phone (7084161459732093690) -->
+ <skip />
+ <string name="permgrouplab_sensors" msgid="416037179223226722">"ବଡୀ ସେନ୍ସର୍"</string>
+ <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ଆପଣଙ୍କ ଗୁରୁତପୂର୍ଣ୍ଣ ସଂକେତଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍ ଡାଟା ଆକ୍ସେସ୍ କରେ"</string>
+ <!-- no translation found for permgrouprequest_sensors (8631146669524259656) -->
+ <skip />
+ <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ୱିଣ୍ଡୋ କଣ୍ଟେଣ୍ଟ ହାସଲ କରନ୍ତୁ"</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ଆପଣ କାମ କରୁଥିବା ୱିଣ୍ଡୋର କଣ୍ଟେଣ୍ଟକୁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ସ୍ପର୍ଶ ଦ୍ୱାରା ଏକ୍ସପ୍ଲୋର୍ ଅନ୍ କରନ୍ତୁ"</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"ଟାପ୍ କରାଯାଇଥିବା ଆଇଟମ୍ଗୁଡ଼ିକୁ ବଡ଼ ପାଟିରେ କୁହାଯିବ ଏବଂ ଜେଶ୍ଚର୍ ବ୍ୟବହାର କରି ସ୍କ୍ରୀନ୍ ଏକ୍ସପ୍ଲୋର୍ କରାଯିବ।"</string>
+ <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"ଆପଣ ଟାଇପ୍ କରିବା ଟେକ୍ସଟ୍କୁ ଧ୍ୟାନଦେଇ ଦେଖନ୍ତୁ"</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ବ୍ୟକ୍ତିଗତ ଡାଟା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି, କ୍ରେଡିଟ୍ କାର୍ଡ ନମ୍ବର ଓ ପାସ୍ୱର୍ଡ।"</string>
+ <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ଡିସପ୍ଲେ ମେଗ୍ନିଫିକେଶନ୍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
+ <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ଡିସପ୍ଲେର ଜୁମ୍ ସ୍ତର ଓ ପୋଜିସନିଙ୍ଗ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ଜେଶ୍ଚର୍ କରନ୍ତୁ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ଟାପ୍, ସ୍ୱାଇପ୍, ପିଞ୍ଚ ଓ ଅନ୍ୟାନ୍ୟ ଜେଶ୍ଚର୍ ସମ୍ପାଦନ କରିପାରିବ।"</string>
+ <!-- no translation found for capability_title_canCaptureFingerprintGestures (6309568287512278670) -->
+ <skip />
+ <!-- no translation found for capability_desc_canCaptureFingerprintGestures (4386487962402228670) -->
+ <skip />
+ <string name="permlab_statusBar" msgid="7417192629601890791">"ଷ୍ଟାଟସ୍ ବାର୍କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
+ <string name="permdesc_statusBar" msgid="8434669549504290975">"ଆପ୍କୁ, ସ୍ଥିତି ବାର୍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍ ଆଇକନ୍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_statusBarService" msgid="4826835508226139688">"ଷ୍ଟାଟସ୍ ବାର୍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
+ <string name="permdesc_statusBarService" msgid="716113660795976060">"ଆପ୍ଟିକୁ ସ୍ଥିତି ବାର୍ ହେବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ସ୍ଥିତି ବାର୍କୁ ବଡ଼/ଛୋଟ କରନ୍ତୁ"</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ଷ୍ଟାଟସ୍ ବାର୍କୁ ବଡ଼ କିମ୍ବା ଛୋଟ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_install_shortcut" msgid="4279070216371564234">"ଶର୍ଟକଟ୍ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ୟୁଜର୍ଙ୍କ ବିନା ବାଧାରେ ହୋମ୍ସ୍କ୍ରୀନ୍ ସର୍ଟକଟ୍ ଯୋଡ଼ିବାକୁ ଏକ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ଶର୍ଟକଟ୍ ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ୟୁଜର୍ଙ୍କ ବିନା ବାଧାରେ ହୋମ୍ସ୍କ୍ରୀନ୍ର ଶର୍ଟକଟ୍ ବାହାର କରିବା ପାଇଁ ଗୋଟିଏ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍କୁ ଅନ୍ୟ ରୁଟ୍ ଦିଅନ୍ତୁ"</string>
+ <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ଭିନ୍ନ ନମ୍ବରକୁ କଲ୍ ରିଡାଇରେକ୍ଟ କରିବା କିମ୍ବା ଏକାଠି କଲ୍ ଖାରଜ କରିବା ବିକଳ୍ପ ସହ ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍ କରିବାବେଳେ ଡାୟଲ୍ କରାଯାଉଥିବା ନମ୍ବର ଦେଖିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+ <skip />
+ <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+ <skip />
+ <string name="permlab_receiveSms" msgid="8673471768947895082">"ଟେକ୍ସଟ୍ ମେସେଜ୍ (SMS) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ମେସେଜ୍ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ ହେଉଛି, ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍ଟି ମନିଟର୍ କିମ୍ବା ଡିଲିଟ୍ କରିପାରେ।"</string>
+ <string name="permlab_receiveMms" msgid="1821317344668257098">"ଟେକ୍ସଟ୍ ମେସେଜ୍ (MMS) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS ମେସେଜ୍ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍ଟି ମନିଟର୍ କିମ୍ବା ଡିଲିଟ୍ କରିପାରେ।"</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍ରେ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଡିଭାଇସ୍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
+ <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍କୁ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ଆପ୍କୁ, କିଛି ସମୟ ପୂର୍ବରୁ ସିଙ୍କ ହୋଇଥିବା ଫୀଡ୍ ବିଷୟରେ ବିବରଣୀ ପ୍ରାପ୍ତ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_sendSms" msgid="7544599214260982981">"SMS ମେସେଜ୍ ପଠାନ୍ତୁ ଓ ଦେଖନ୍ତୁ"</string>
+ <string name="permdesc_sendSms" msgid="7094729298204937667">"ଆପ୍କୁ SMS ମେସେଜ୍ ପଠେଇବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅପ୍ରତ୍ୟାଶିତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ। ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ବିନା ସ୍ୱୀକୃତିରେ ମେସେଜ୍ ପଠାଇ, ଆପଣଙ୍କ ପଇସା ଖର୍ଚ୍ଚ କରାଇପାରେ।"</string>
+ <string name="permlab_readSms" msgid="8745086572213270480">"ଆପଣଙ୍କ ଟେକ୍ସଟ୍ ମେସେଜ୍ (SMS କିମ୍ବା MMS) ପଢ଼ନ୍ତୁ"</string>
+ <!-- no translation found for permdesc_readSms (4741697454888074891) -->
+ <skip />
+ <!-- no translation found for permdesc_readSms (5796670395641116592) -->
+ <skip />
+ <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ SMS (ଟେକ୍ସଟ୍) ମେସେଜ୍ ଏହି ଆପ୍ ପଢ଼ିପାରେ।"</string>
+ <string name="permlab_receiveWapPush" msgid="5991398711936590410">"ଟେକ୍ସଟ୍ ମେସେଜ୍ (WAP) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ଆପ୍କୁ WAP ମେସେଜିଙ୍ଗକୁ ପ୍ରାପ୍ତ ଓ ବିକାଶ କରିବାକୁ ଦେଇଥାଏ। ଏହି ଅନୁମତିରେ ଆପଣ ସେମାନଙ୍କୁ ଦେଖାଯାଇଥିବା ମେସେଜ୍ ଉପରେ ନଜର ରଖିବା ଏବଂ ଡିଲିଟ୍ କରିବାର କ୍ଷମତା ସାମିଲ୍ ଅଛି।"</string>
+ <string name="permlab_getTasks" msgid="6466095396623933906">"ଚାଲୁଥିବା ଆପ୍ଗୁଡ଼ିକୁ ପୁନଃପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_getTasks" msgid="7454215995847658102">"ବର୍ତ୍ତମାନ ତଥା ନିକଟରେ ଚାଲୁଥିବା କାର୍ଯ୍ୟ ବିଷୟରେ ସୂଚନାକୁ ହାସଲ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଆପଟି ଡିଭାଇସ୍ର କେଉଁ ଆପ୍ଲିକେଶନ୍ରେ ଉପଯୋଗ କରାଯାଇଥିଲା, ତାହାର ସୂଚନାକୁ ଜାଣିପାରେ।"</string>
+ <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"ପ୍ରୋଫାଇଲ୍ ଓ ଡିଭାଇସ୍ ମାଲିକଙ୍କୁ ପରିଚାଳନା କରେ"</string>
+ <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ପ୍ରୋଫାଇଲ୍ ମାଲିକ ଓ ଡିଭାଇସ୍ ମାଲିକଙ୍କ ପ୍ରୋଫାଇଲ୍ ସେଟ୍ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_reorderTasks" msgid="2018575526934422779">"ଚାଲୁଥିବା ଆପ୍ଗୁଡ଼ିକର କ୍ରମକୁ ପୁଣି ସଜାନ୍ତୁ"</string>
+ <string name="permdesc_reorderTasks" msgid="7734217754877439351">"ଆପ୍ଟି, ଆପଣ କରୁଥିବା କାମକୁ ଫୋର୍ଗ୍ରାଉଣ୍ଡ ତଥା ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡକୁ ନେଇପାରିବ। ଆପଣଙ୍କ ବିନା ଅନୁମତିରେ ଆପ୍ଟି ଏହା କରିପାରିବ।"</string>
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"କାର୍ ମୋଡ୍କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="permdesc_enableCarMode" msgid="4853187425751419467">"କାର୍ ମୋଡ୍ ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"ଅନ୍ୟ ଆପ୍ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ଆପ୍କୁ ଅନ୍ୟ ଆପ୍ର ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଟ ପ୍ରକ୍ରିୟାକୁ ସମାପ୍ତ କରିବାକୁ ଦେଇଥାଏ। ଏହି କାରଣରୁ ଅନ୍ୟ ଆପ୍ଗୁଡ଼ିକ ଚାଲିବା ବନ୍ଦ ହୋଇଯାଇପାରେ।"</string>
+ <!-- no translation found for permlab_systemAlertWindow (7238805243128138690) -->
+ <skip />
+ <!-- no translation found for permdesc_systemAlertWindow (2393776099672266188) -->
+ <skip />
+ <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
+ <skip />
+ <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
+ <skip />
+ <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
+ <skip />
+ <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
+ <skip />
+ <string name="permlab_persistentActivity" msgid="8841113627955563938">"ଆପ୍କୁ, ସର୍ବଦା ଚାଲୁଥିବା କରନ୍ତୁ"</string>
+ <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ଆପ୍ଟି ନିଜକୁ ମେମୋରୀରେ ଭାଗ କରିବାକୁ ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅନ୍ୟ ଆପ୍ଗୁଡ଼ିକ ପାଇଁ ମେମୋରୀ ଉପଲବ୍ଧକୁ କମ୍ କରିବା ସହ ଟାବ୍ଲେଟ୍ଟିକୁ ମନ୍ଥର କରିବ।"</string>
+ <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ମେମୋରୀରେ ଆପ୍ଟି ନିଜକୁ ଭାଗ କରିବାକୁ ଦେଇଥାଏ। ଏହା ଟିଭିକୁ ଧୀର କରି ଅନ୍ୟ ଆପ୍ ପାଇଁ ଉପଲବ୍ଧ ମେମୋରୀକୁ ସୀମିତ କରିପାରେ।"</string>
+ <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ଆପ୍ଟି ନିଜକୁ ମେମୋରୀରେ ଭାଗ କରିବାକୁ ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅନ୍ୟ ଆପ୍ଗୁଡ଼ିକ ପାଇଁ ମେମୋରୀ ଉପଲବ୍ଧକୁ କମ୍ କରିବା ସହ ଫୋନ୍ଟିକୁ ମନ୍ଥର କରିବ।"</string>
+ <!-- no translation found for permlab_foregroundService (3310786367649133115) -->
+ <skip />
+ <!-- no translation found for permdesc_foregroundService (6471634326171344622) -->
+ <skip />
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"ଆପ୍ ଷ୍ଟୋରେଜ୍ ସ୍ଥାନର ମାପ କରନ୍ତୁ"</string>
+ <string name="permdesc_getPackageSize" msgid="3921068154420738296">"ଆପ୍ର କୋଡ୍, ଡାଟା ଓ କ୍ୟାଶ୍ ଆକାର ହାସଲ କରିବା ପାଇଁ ଏହାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_writeSettings" msgid="2226195290955224730">"ସିଷ୍ଟମ୍ ସେଟିଙ୍ଗ ବଦଳାନ୍ତୁ"</string>
+ <string name="permdesc_writeSettings" msgid="7775723441558907181">"ଆପ୍କୁ, ସିଷ୍ଟମର ସେଟିଙ୍ଗ ଡାଟା ବଦଳାଇବାକୁ ଦେଇଥାଏ। ହାନୀକାରକ ଆପ୍ ଦ୍ୱାରା ଆପଣଙ୍କ ସିଷ୍ଟମର କନଫିଗରେସନ୍ ଖରାପ ହୋଇପାରେ।"</string>
+ <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"ଆରମ୍ଭ ହେଲେ ଚଲାନ୍ତୁ"</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ସିଷ୍ଟମ୍ ବୁଟ୍ ଶେଷ ହେବା କ୍ଷଣି ଆପ୍ଟିକୁ ସ୍ୱତଃ ଆରମ୍ଭ ହେବାକୁ ଦେଇଥାଏ। ଏହା କାରଣରୁ ଟାବଲେଟଟ୍ଟି ଚାଲୁ ହେବାରେ ଅଧିକ ସମୟ ଲାଗିପାରେ ଏବଂ ଆପ୍ଟି ଲଗାତାର ଚାଲିବା ଦ୍ୱାରା ସମଗ୍ର ଟାବଲେଟଟ୍ ମନ୍ଥର ହୋଇଯାଇପାରେ।"</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"ବୁଟିଙ୍ଗ ସମାପ୍ତ ହେବପରେ ଏହି ଆପ୍କୁ ଆରମ୍ଭ ହେବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା TV ଚଳାଇବାକୁ ଅଧିକ ସମୟ ନେଇପାରେ ଏବଂ ଆପ୍କୁ ସବୁବେଳେ ଚାଲିବାରେ ସମଗ୍ର ଟାବଲେଟ୍ ଧୀର କରିପାରେ।"</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"ସିଷ୍ଟମ୍ ବୁଟ୍ ଶେଷ ହେବା କ୍ଷଣି ଆପ୍ଟିକୁ ସ୍ୱତଃ ଆରମ୍ଭ ହେବାକୁ ଦେଇଥାଏ। ଏହା କାରଣରୁ ଫୋନ୍ଟି ଚାଲୁ ହେବାରେ ଅଧିକ ସମୟ ଲାଗିପାରେ ଏବଂ ଆପ୍ଟି ଲଗାତାର ଚାଲିବା ଦ୍ୱାରା ସମଗ୍ର ଫୋନ୍ ମନ୍ଥର ହୋଇଯାଇପାରେ।"</string>
+ <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ଷ୍ଟିକୀ ବ୍ରୋଡକାଷ୍ଟ ପଠାନ୍ତୁ"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ଆପ୍କୁ ଷ୍ଟିକୀ ବ୍ରଡ୍କାଷ୍ଟ ପଠାଇବାକୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡ୍କାଷ୍ଟ ସମାପ୍ତ ହେବାପରେ ବି ରହିଥାଏ। ଅତ୍ୟଧିକ ଉପଯୋଗ ଦ୍ୱାରା ଟାବଲେଟ୍ ମନ୍ଥର ହୋଇପାରେ କିମ୍ବା ଅଧିକ ମେମୋରୀର ବ୍ୟବହାର କରିବା କାରଣରୁ ଏହା ଅସ୍ଥିର ହୋଇପାରେ।"</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ଷ୍ଟିକୀ ବ୍ରଡ୍କାଷ୍ଟ ପଠାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ, ଯାହା ବ୍ରଡ୍କାଷ୍ଟ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତିରିକ୍ତ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଟିଭିକୁ ଧୀର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ଷ୍ଟିକୀ ବ୍ରଡ୍କାଷ୍ଟ ପଠାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ, ଯାହା ବ୍ରଡ୍କାଷ୍ଟ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତିରିକ୍ତ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଫୋନ୍କୁ ମନ୍ଥର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
+ <string name="permlab_readContacts" msgid="8348481131899886131">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିଙ୍କ ସହ ଆପଣ କେତେଥର କଲ୍, ଇମେଲ୍, ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ତାହାର ନିୟମିତତା ସମେତ ଆପଣଙ୍କ ଟାବଲେଟ୍ରେ ଷ୍ଟୋର୍ ହୋଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହ ଅନୁମତି ଦ୍ୱାରା ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ସେଭ୍ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ ତଥା ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜ୍ଞାତରେ କଲ୍ ଲଗ୍ ଡାଟା ଶେୟାର କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିଙ୍କ ସହ ଆପଣ କେତେଥର କଲ୍, ଇମେଲ୍, ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ତାହାର ନିୟମିତତା ସମେତ ଆପଣଙ୍କ ଟିଭିରେ ଷ୍ଟୋର୍ ହୋଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହାର ଅନୁମତି ଦ୍ୱାରା ଆଙ୍ଙକକ କଲ୍ ଲଗ୍ ସେଭ୍ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ ତଥା ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜ୍ଞାତରେ କଲ୍ ଲଗ୍ ଡାଟା ଶେୟାର କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍ଟି ଆପଣଙ୍କ ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିପାରିବ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ବିନା ଜ୍ଞାତସାରରେ ଯୋଗାଯୋଗ ଡାଟା ଶେୟାର୍ କରିପାରନ୍ତି।"</string>
+ <string name="permlab_writeContacts" msgid="5107492086416793544">"ନିଜ ଯୋଗାଯୋଗ ସଂଶୋଧନ କରନ୍ତୁ"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଟାବଲେଟ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟକ ଡାଟା ବଦଳାଇବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍ଟି ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିପାରେ।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଟିଭିରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍ଟି ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିପାରେ।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍ଟି ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିପାରେ।"</string>
+ <string name="permlab_readCallLog" msgid="3478133184624102739">"କଲ୍ ଲଗ୍ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readCallLog" msgid="3204122446463552146">"ଏହି ଆପ୍ ଆପଣଙ୍କ କଲ୍ ହିଷ୍ଟୋରୀ ପଢ଼ିପାରେ।"</string>
+ <string name="permlab_writeCallLog" msgid="8552045664743499354">"କଲ୍ ଲଗ୍ ଲେଖନ୍ତୁ"</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ଇନ୍କମିଙ୍ଗ ତଥା ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍ ଡାଟା ସହ ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ର କଲ୍ ଲଗ୍ ବଦଳାଇବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ଲିଭାଇବାକୁ କିମ୍ବା ବଦଳାଇବାକୁ ଏହା ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"ଇନ୍କମିଙ୍ଗ ତଥା ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍ ଡାଟା ସହ ଆପଣଙ୍କ ଟିଭିର କଲ୍ ଲଗ୍ ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ଲିଭାଇବାକୁ କିମ୍ବା ବଦଳାଇବାକୁ ଏହାକୁ ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ଇନ୍କମିଙ୍ଗ ତଥା ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍ ଡାଟା ସହ ଆପଣଙ୍କ ଫୋନ୍ର କଲ୍ ଲଗ୍ ବଦଳାଇବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ଲିଭାଇବାକୁ କିମ୍ବା ବଦଳାଇବାକୁ ଏହା ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
+ <string name="permlab_bodySensors" msgid="4683341291818520277">"ବଡୀ ସେନ୍ସର୍ ଆକ୍ସେସ୍ କରେ (ଯେପରିକି ହୃଦ୍ ହାର ମନିଟର୍)"</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ଆପ୍କୁ ସେନ୍ସର୍ ଡେଟା ପର୍ଯ୍ୟନ୍ତ ପହଞ୍ଚିବାକୁ ଦେଇଥାଏ, ଯାହା ଆପଣଙ୍କ ଶାରୀରିକ ସ୍ଥିତିର ନିରୀକ୍ଷଣ କରିଥାଏ, ଯେପରିକି ଆପଣଙ୍କ ହୃଦୟ ସ୍ତର।"</string>
+ <!-- no translation found for permlab_readCalendar (6716116972752441641) -->
+ <skip />
+ <!-- no translation found for permdesc_readCalendar (4993979255403945892) -->
+ <skip />
+ <!-- no translation found for permdesc_readCalendar (8837931557573064315) -->
+ <skip />
+ <!-- no translation found for permdesc_readCalendar (4373978642145196715) -->
+ <skip />
+ <string name="permlab_writeCalendar" msgid="8438874755193825647">"କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟରେ ଯୋଡ଼ନ୍ତୁ କିମ୍ବା ସଂଶୋଧନ କରନ୍ତୁ ଏବଂ ମାଲିକଙ୍କ ଅଜାଣତରେ ଅତିଥିମାନଙ୍କୁ ଇମେଲ୍ ପଠାନ୍ତୁ।"</string>
+ <!-- no translation found for permdesc_writeCalendar (1675270619903625982) -->
+ <skip />
+ <!-- no translation found for permdesc_writeCalendar (9017809326268135866) -->
+ <skip />
+ <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"ଏହି ଆପ୍, ଆପଣଙ୍କ ଫୋନ୍ରେ କ୍ୟାଲେଣ୍ଡର୍ ଇଭେଣ୍ଟଗୁଡ଼ିକୁ ଯୋଡ଼ିପାରେ, ବାହାର କରିପାରେ କିମ୍ବା ବଦଳାଇପାରେ। କ୍ୟାଲେଣ୍ଡର୍ ମାଲିକଙ୍କ ପାଖରୁ ଆସିଥିବା ପରି ଜଣାପଡ଼ିବା ମେସେଜ୍କୁ ଏହି ଆପ୍ ପଠାଇପାରେ କିମ୍ବା ମାଲିକଙ୍କୁ ନଜଣାଇ ଇଭେଣ୍ଟ ବଦଳାଇପାରେ।"</string>
+ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ଅତିରିକ୍ତ ଲୋକେଶନ୍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ଅତିରିକ୍ତ ଲୋକେଶନ୍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। GPS କିମ୍ବା ଅନ୍ୟ ଲୋକେଶନ୍ ସୋର୍ସଗୁଡିକରେ ଆପ୍ଟି ପ୍ରଭାବ ପକାଇପାରେ।"</string>
+ <string name="permlab_accessFineLocation" msgid="251034415460950944">"ନିର୍ଦ୍ଦିଷ୍ଟ ଲୋକେଶନ୍ ଆକ୍ସେସ୍ କରେ (GPS ଏବଂ ନେଟ୍ୱର୍କ-ଆଧାରିତ)"</string>
+ <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ଏହି ଆପ୍, GPS କିମ୍ୱା ନେଟ୍ୱର୍କ ସୋର୍ସ ଉପରେ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେଶନ୍ ପ୍ରାପ୍ତ କରିପାରେ, ଯେପରିକି ସେଲ୍ ଟାୱାର୍ ଓ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ। ଏହି ଲୋକେଶନ୍ ସେବା, ଆପଣଙ୍କ ଫୋନ୍ରେ ଅନ୍ ରହିଥିବା ଓ ଉପଲବ୍ଧ ଥିବା ଦରକାର, ଯେଉଁଥିରୁ ଆପ୍ ସେଗୁଡ଼ିକର ବ୍ୟବହାର କରିପାରିବ। ଏହାଦ୍ୱାରା ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ ବଢ଼ିପାରେ।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ପାଖାପାଖି ଲୋକେଶନ୍ ଆକ୍ସେସ୍ କରେ (ନେଟ୍ୱର୍କ-ଆଧାରିତ)"</string>
+ <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ଆପଣଙ୍କ ଅଡିଓ ସେଟିଙ୍ଗକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ଆପ୍କୁ ଗ୍ଲୋବାଲ୍ ଅଡିଓ ସେଟିଙ୍ଗ, ଯେପରିକି ଭଲ୍ୟୁମ୍କୁ ସଂଶୋଧିତ କରିବାକୁ ଏବଂ ଆଉଟପୁଟ୍ ପାଇଁ ସ୍ପିକର୍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
+ <!-- no translation found for permdesc_recordAudio (4245930455135321433) -->
+ <skip />
+ <string name="permlab_sim_communication" msgid="2935852302216852065">"SIMକୁ କମାଣ୍ଡ ପଠାନ୍ତୁ"</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIMକୁ କମାଣ୍ଡ ପଠାଇବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ବହୁତ ବିପଦପୂର୍ଣ୍ଣ।"</string>
+ <string name="permlab_camera" msgid="3616391919559751192">"ଫଟୋ ଓ ଭିଡିଓଗୁଡ଼ିକୁ ନିଅନ୍ତୁ"</string>
+ <string name="permdesc_camera" msgid="5392231870049240670">"ଏହି ଆପ୍ ଯେକୌଣସି ସମୟରେ କ୍ୟାମେରା ବ୍ୟବହାର କରି ଫଟୋ ଉଠାଇପାରେ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିପାରେ।"</string>
+ <string name="permlab_vibrate" msgid="7696427026057705834">"କମ୍ପନ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
+ <string name="permdesc_vibrate" msgid="6284989245902300945">"ଆପ୍କୁ, ଭାଇବ୍ରେଟର୍ ନିୟନ୍ତ୍ରଣ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_callPhone" msgid="3925836347681847954">"ସିଧାସଳଖ ଫୋନ୍ ନମ୍ବରଗୁଡ଼ିକୁ କଲ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_callPhone" msgid="3740797576113760827">"ଆପଣଙ୍କ ହସ୍ତକ୍ଷେପ ବିନା ଫୋନ୍ ନମ୍ଵରକୁ କଲ୍ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅପ୍ରତ୍ୟାଶିତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ କିମ୍ବା କଲ୍ ହୋଇପାରେ। ଧ୍ୟାନଦିଅନ୍ତୁ ଯେ, ଏହା ଆପ୍କୁ କୌଣସି ଜରୁରୀକାଳୀନ ନମ୍ବରରେ କଲ୍ କରିବାକୁ ଅନୁମତି ଦିଏନାହିଁ। ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ବିନା ସ୍ୱୀକୃତିରେ କଲ୍ କରି ଆପଣଙ୍କ ପଇସା ଖର୍ଚ୍ଚ କରାଇପାରେ।"</string>
+ <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS କଲ୍ ସେବା ଆକ୍ସେସ୍ କରେ"</string>
+ <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ଆପଣଙ୍କ ହସ୍ତକ୍ଷେପ ବିନା କଲ୍ କରିପାରିବା ପାଇଁ ଆପ୍କୁ IMS ସେବା ବ୍ୟବହାର କରିବାକୁ ଦିଏ।"</string>
+ <string name="permlab_readPhoneState" msgid="9178228524507610486">"ଫୋନ୍ ସ୍ଥିତି ଓ ପରିଚୟ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ଆପ୍କୁ ଡିଭାଇସ୍ର ଫୋନ୍ ବୈଶିଷ୍ଟ୍ୟ ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍କୁ ଫୋନ୍ ନମ୍ବର୍ ଓ ଡିଭାଇସ୍ IDଗୁଡ଼ିକୁ ନିର୍ଦ୍ଧାରଣ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ, କଲ୍ ସକ୍ରିୟ ଥିଲେ ବି ଏବଂ କଲ୍ ଦ୍ୱାରା ସଂଯୋଗ ଥିବା ରିମୋଟ୍ ନମ୍ବର୍କୁ ମଧ୍ୟ।"</string>
+ <!-- no translation found for permlab_manageOwnCalls (1503034913274622244) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOwnCalls (6552974537554717418) -->
+ <skip />
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
+ <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
+ <skip />
+ <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
+ <skip />
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ଟାବଲେଟ୍କୁ ସ୍ଲୀପିଙ୍ଗ ମୋଡ୍କୁ ଯିବାକୁ ରୋକନ୍ତୁ"</string>
+ <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ଟିଭିକୁ ସ୍ଲୀପିଙ୍ଗ ମୋଡ୍ରୁ ଯିବାକୁ ରୋକନ୍ତୁ।"</string>
+ <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ଫୋନକୁ ସ୍ଲୀପିଙ୍ଗ ମୋଡ୍କୁ ଯିବାକୁ ରୋକନ୍ତୁ"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"ଆପ୍କୁ, ଟାବଲେଟ୍ଟିକୁ ସ୍ଲୀପ୍ ମୋଡ୍କୁ ଯିବାରେ ପ୍ରତିରୋଧ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"TVକୁ ଶୁଆଇବାକୁ ଯିବାରୁ ରୋକିବାକୁ ଆପ୍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"ଆପ୍କୁ, ଫୋନ୍ଟିକୁ ସ୍ଲୀପ୍ ମୋଡ୍କୁ ଯିବାରେ ପ୍ରତିରୋଧ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_transmitIr" msgid="7545858504238530105">"ଇନଫ୍ରାରେଡ୍ ସଂଚାରିତ କରନ୍ତୁ"</string>
+ <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"ଟାବଲେଟ୍ର ଇନଫ୍ରାରେଡ୍ ଟ୍ରାନ୍ସମିଟର୍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"ଟିଭିର ଇନ୍ଫ୍ରାରେଡ୍ ଟ୍ରାନ୍ସମିଟର୍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ଫୋନ୍ର ଇନଫ୍ରାରେଡ୍ ଟ୍ରାନ୍ସମିଟର୍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_setWallpaper" msgid="6627192333373465143">"ୱାଲପେପର୍ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_setWallpaper" msgid="7373447920977624745">"ଆପ୍କୁ, ସିଷ୍ଟମ୍ ୱାଲପେପର୍ ସେଟ୍ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ଆପଣଙ୍କ ୱାଲ୍ପେପର୍ର ଆକାର ଆଡ୍ଜଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ଆପ୍କୁ, ସିଷ୍ଟମ୍ ୱାଲପେପର୍ ଆକାରର ସୂଚନା ସେଟ୍ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_setTimeZone" msgid="2945079801013077340">"ଟାଇମ୍ ଜୋନ୍ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"ଆପ୍କୁ, ଟାବଲେଟ୍ର ଟାଇମ୍ ଜୋନ୍ ବଦଳାଇବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"ଟିଭିର ସଂଯୋଗ ପ୍ରବନ୍ଧିତ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ଆପ୍କୁ, ଫୋନ୍ର ଟାଇମ୍ ଜୋନ୍ ବଦଳାଇବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_getAccounts" msgid="1086795467760122114">"ଡିଭାଇସ୍ରେ ଆକାଉଣ୍ଟ ଖୋଜନ୍ତୁ"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ଟାବଲେଟ୍ ଦ୍ୱାରା ପରିଚିତ ଆକାଉଣ୍ଟର ତାଲିକା ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ଲିକେଶନ୍ ଦ୍ୱାରା ତିଆରି କରାଯାଇଥିବା କୌଣସି ଆକାଉଣ୍ଟ ବି ଏଥିରେ ସାମିଲ୍ ହୋଇପାରେ।"</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"TV ଦ୍ୱାରା ପରିଚିତ ଆକାଉଣ୍ଟର ତାଲିକା ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଫଳରେ ଆପଣଙ୍କ ଦ୍ୱାରା ଇନଷ୍ଟଲ୍ କରାଯାଇଥିବା ଅନୁପ୍ରୟୋଗରେ ଖୋଲାଯାଇଥିବା କୌଣସି ବି ଆକାଉଣ୍ଟରେ ସାମିଲ୍ ହୋଇପାରିବ।"</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ଫୋନ୍ ଦ୍ୱାରା ପରିଚିତ ଆକାଉଣ୍ଟର ତାଲିକା ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ଲିକେଶନ୍ ଦ୍ୱାରା ତିଆରି କରାଯାଇଥିବା କୌଣସି ଆକାଉଣ୍ଟ ବି ଏଥିରେ ସାମିଲ୍ ହୋଇପାରେ।"</string>
+ <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ନେଟ୍ୱର୍କ ସଂଯୋଗ ଦେଖନ୍ତୁ"</string>
+ <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"କେଉଁ ନେଟ୍ୱର୍କ ଉପସ୍ଥିତ ତଥା ସଂଯୁକ୍ତ ଅଛି, ତାହା ବିଷୟରେ ସୂଚନା ଦେଖିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"ପୂର୍ଣ୍ଣ ନେଟ୍ୱର୍କ ଆକ୍ସେସ୍ ରହିଛି"</string>
+ <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"ଆପ୍କୁ ନେଟ୍ୱର୍କ ସକେଟ୍ ବନେଇବା ଏବଂ କଷ୍ଟମ୍ ନେଟ୍ୱର୍କ ପ୍ରୋଟୋକଲ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ବ୍ରାଉଜର୍ ଏବଂ ଅନ୍ୟ ଆପ୍ଲିକେଶନ୍ ଦ୍ୱାରା ଇଣ୍ଟରନେଟ୍କୁ ଡାଟା ପଠାଯାଇପାରେ, ତେଣୁ ଏହି ଅନୁମତି ଇଣ୍ଟରନେଟ୍କୁ ଡାଟା ପଠେଇବା ପାଇଁ ଆବଶ୍ୟକ ହୁଏନାହିଁ।"</string>
+ <string name="permlab_changeNetworkState" msgid="958884291454327309">"ନେଟୱର୍କ ସଂଯୋଗକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"ନେଟୱର୍କ ସଂଯୋଗର ସ୍ଥିତି ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_changeTetherState" msgid="5952584964373017960">"ଟିଥର୍ ହୋଇଥିବା କନେକ୍ଟିଭିଟୀକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="permdesc_changeTetherState" msgid="1524441344412319780">"ଟିଥର୍ ହୋଇଥିବା ନେଟୱର୍କ ସଂଯୋଗର ସ୍ଥିତି ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"ୱାଇ-ଫାଇ ସଂଯୋଗ ଦେଖନ୍ତୁ"</string>
+ <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ୱାଇ-ଫାଇ ନେଟୱର୍କିଙ୍ଗ ବିଷୟରେ ସୂଚନା ଦେଖିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ, ଯେପରିକି ୱାଇ-ଫାଇ ସକ୍ଷମ ହୋଇଛି କି ନାହିଁ ଏବଂ ସଂଯୁକ୍ତ ହୋଇଥିବା ୱାଇ-ଫାଇ ଡିଭାଇସ୍ର ନାମ।"</string>
+ <string name="permlab_changeWifiState" msgid="6550641188749128035">"ୱାଇ-ଫାଇରୁ ସଂଯୋଗ ଓ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ଆପ୍କୁ ୱାଇ-ଫାଇ ଆକ୍ସେସ୍ ପଏଣ୍ଟ ସହିତ ସଂଯୋଗ ଓ ବିଚ୍ଛିନ୍ନ କରିବାକୁ ତଥା ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ ପାଇଁ ଡିଭାଇସ୍ କନଫିଗରେଶନ୍ରେ ପରିବର୍ତ୍ତନ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ୱାଇ-ଫାଇ ମଲ୍ଟିକାଷ୍ଟ ରିସେପଶନ ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"କେବଳ ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ ନୁହେଁ, ବରଂ ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କରେ ଥିବା ସମସ୍ତ ଡିଭାଇସ୍କୁ ପଠାଯିବା ପ୍ୟାକେଟ୍ଗୁଡ଼ିକ ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍ଟି ଅନୁମତି ଦେଇଥାଏ। ଅଣ-ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍ ତୁଳନାରେ ଏହା ଅଧିକ ପାୱାର୍ ବ୍ୟବହାର କରେ।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"କେବଳ ଆପଣଙ୍କ ଟିଭି ନୁହେଁ, ମଲ୍ଟିକାଷ୍ଟ ଠିକଣା ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କରେ ସମସ୍ତ ଡିଭାଇସ୍କୁ ପଠାଯାଇଥିବା ପ୍ୟାକେଟ୍ ପ୍ରାପ୍ତ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଅଣ-ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍ ତୁଳନାରେ ଏହା ଅଧିକ ପାୱାର୍ ବ୍ୟବହାର କରେ।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"କେବଳ ଆପଣଙ୍କ ଫୋନ୍ ନୁହେଁ, ବରଂ ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କରେ ଥିବା ସମସ୍ତ ଡିଭାଇସ୍କୁ ପଠାଯିବା ପ୍ୟାକେଟ୍ଗୁଡ଼ିକ ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍ଟି ଅନୁମତି ଦେଇଥାଏ। ଅଣ-ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍ ତୁଳନାରେ ଏହା ଅଧିକ ପାୱାର୍ ବ୍ୟବହାର କରେ।"</string>
+ <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ବ୍ଲୁ-ଟୁଥ୍ ସେଟିଙ୍ଗ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"ସ୍ଥାନୀୟ ବ୍ଲୁ-ଟୁଥ, ଟାବଲେଟ୍କୁ କନଫିଗର୍ କରିବାକୁ ଏବଂ ରିମୋର୍ଟ ଡିଭାଇସ୍କୁ ଚିହ୍ନାଇବା ତଥା ସେଗୁଡ଼ିକୁ ପେୟାର୍ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"ଆପ୍କୁ ସ୍ଥାନୀୟ ବ୍ଲୁ-ଟୁଥ୍ TVକୁ କନଫିଗର୍ କରିବାକୁ ଦେଇଥାଏ ଏବଂ ରିମୋର୍ଟ ଡିଭାଇସ୍କୁ ଚିହ୍ନାଇ ସେମାନଙ୍କୁ ଯୋଡ଼ିଥାଏ।"</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ସ୍ଥାନୀୟ ବ୍ଲୁ-ଟୁଥ, ଫୋନ୍କୁ କନଫିଗର୍ କରିବାକୁ ଏବଂ ରିମୋର୍ଟ ଡିଭାଇସ୍କୁ ଚିହ୍ନାଇବା ତଥା ସେଗୁଡ଼ିକୁ ପେୟାର୍ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX ସହିତ ସଂଯୋଗ ଏବଂ ଏଥିରୁ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string>
+ <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"WiMAX ସକ୍ଷମ କି ନାହିଁ ସ୍ଥିର କରିବାକୁ ଏବଂ ସଂଯୁକ୍ତ ଥିବା କୌଣସି WiMAX ନେଟ୍ୱର୍କ ବିଷୟରେ ସୂଚନା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ ।"</string>
+ <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX ସ୍ଥିତିକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"WiMAX ନେଟ୍ୱର୍କରୁ ଟାବଲେଟ୍ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"ଟିଭିକୁ ସଂଯୋଗ କରିବାକୁ ତଥା WiMAX ନେଟ୍ୱର୍କରୁ ଟିଭିକୁ ବିଚ୍ଛିନ୍ନ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"WiMAX ନେଟ୍ୱର୍କରୁ ଫୋନ୍ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"ବ୍ଲୁ-ଟୁଥ୍ ଡିଭାଇସ୍ ଦେଖନ୍ତୁ"</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ଟାବଲେଟ୍ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍ର କନଫିଗରେଶନ୍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"ଟିଭିରେ ବ୍ଲୁ-ଟୁଥ୍ର କନଫିଗରେଶନ୍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍ ହୋଇଥିବା ଡିଭାଇସ୍ ସହ ସଂଯୋଗ ତିଆରି ତଥା ସ୍ୱୀକାର କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ଫୋନ୍ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍ର କନଫିଗରେଶନ୍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_nfc" msgid="4423351274757876953">"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେଶନ୍ ଉପରେ ନିୟନ୍ତ୍ରଣ ରଖନ୍ତୁ"</string>
+ <string name="permdesc_nfc" msgid="7120611819401789907">"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେସନ୍ନ (NFC) ଟାଗ୍, କାର୍ଡ ଓ ରିଡରଗୁଡ଼ିକ ସହ ଯୋଗାଯୋଗ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍ ଲକ୍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ଆପ୍କୁ କୀ\'ଲକ୍ କିମ୍ବା ସେଥିରେ ଥିବା କୌଣସି ପାସ୍ୱର୍ଡ ସୁରକ୍ଷାକୁ ଅକ୍ଷମ କରିବା ପାଇଁ ଅନୁମତି ଦିଏ, ଉଦାହରଣସ୍ୱରୂପ, ଇନ୍କମିଙ୍ଗ ଫୋନ୍ କଲ୍ ପ୍ରାପ୍ତ କରିବା ସମୟରେ ଫୋନ୍ଟି କୀ\'ଲକ୍କୁ ଅକ୍ଷମ କରିଦିଏ, ତା’ପରେ କଲ୍ ସମାପ୍ତ ହେବାପରେ ପୁଣି କୀ\'ଲକ୍କୁ ସକ୍ଷମ କରିଥାଏ।"</string>
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍ ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍ କରିବାକୁ ଆପକୁ ବିଧି ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ସ୍ୱୀକୃତି ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
+ <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଂଶିକ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରୋସେସ୍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନ୍ସର୍ ମଇଳା ହୋଇଯାଇଛି। ଦୟାକରି ସଫା କରନ୍ତୁ ଓ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ଆଙ୍ଗୁଠି ବହୁତ ଜୋର୍ରେ ଚଲାଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ଆଙ୍ଗୁଠି ଖୁବ୍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string-array name="fingerprint_acquired_vendor">
+ </string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ଚିହ୍ନଟ ହେଲା ନାହିଁ"</string>
+ <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
+ <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
+ <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଆଙ୍ଗୁଠି ଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ଆଙ୍ଗୁଠି ଚିହ୍ନ କାର୍ଯ୍ୟ କ୍ୟାନ୍ସଲ୍ କରାଗଲା।"</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
+ <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ବହୁତ ପ୍ରୟାସ କରାଗଲା। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
+ <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for fingerprint_error_no_fingerprints (7654382120628334248) -->
+ <skip />
+ <!-- no translation found for fingerprint_error_hw_not_present (5729436878065119329) -->
+ <skip />
+ <string name="fingerprint_name_template" msgid="5870957565512716938">"ଆଙ୍ଗୁଠି <xliff:g id="FINGERID">%d</xliff:g>"</string>
+ <string-array name="fingerprint_error_vendor">
+ </string-array>
+ <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
+ <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ସିଙ୍କ ସେଟିଙ୍ଗକୁ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ଏକ ଆକାଉଣ୍ଟ ପାଇଁ ସିଙ୍କ ସେଟିଙ୍ଗ ପଢ଼ିବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଉଦାହରଣସ୍ୱରୂପ, ଲୋକଙ୍କ ଆପ୍ ଏକ ଆକାଉଣ୍ଟରେ ସିଙ୍କ ହୋଇଛି କି ନାହିଁ ଏହା ଜାଣିପାରେ।"</string>
+ <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ସିଙ୍କ ଅନ୍ ଓ ଅଫ୍ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"ଆପ୍କୁ ଏକ ଆକାଉଣ୍ଟ ପାଇଁ ସିଙ୍କ ସେଟିଙ୍ଗ ସଂଶୋଧନ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଉଦାହରଣସ୍ୱରୂପ, ଏହାର ବ୍ୟବହାର କୌଣସି ଆକାଉଣ୍ଟରେ ଥିବା ଲୋକଙ୍କ ଆପ୍ ସହିତ ସିଙ୍କ କରିବାକୁ ସକ୍ଷମ ହୋଇଥାଏ।"</string>
+ <string name="permlab_readSyncStats" msgid="7396577451360202448">"ସିଙ୍କ୍ ପରିସଂଖ୍ୟାନକୁ ପଢ଼ନ୍ତୁ।"</string>
+ <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ସିଙ୍କ କାର୍ଯ୍ୟର ହିଷ୍ଟୋରୀ ତଥା କେତେ ଡାଟା ସିଙ୍କ କରାଯାଇଛି, ସେଗୁଡ଼ିକ ଅନ୍ତର୍ଭୁକ୍ତ କରି, ଏକ ଆକାଉଣ୍ଟର ସିଙ୍କ ଅବସ୍ଥା ପଢ଼ିବା ପାଇଁ ଗୋଟିଏ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"ନିଜ USB ଷ୍ଟୋରେଜ୍ର କଣ୍ଟେଣ୍ଟ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"ନିଜ SD କାର୍ଡର କଣ୍ଟେଣ୍ଟ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"USB ଷ୍ଟୋରେଜ୍ରେ ଥିବା କଣ୍ଟେଣ୍ଟ ପଢିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"ଆପଣଙ୍କ SD କାର୍ଡରେ ଥିବା କଣ୍ଟେଣ୍ଟ ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ଆପଣଙ୍କ USB ଷ୍ଟୋରେଜ୍ର କଣ୍ଟେଣ୍ଟ ସଂଶୋଧନ କରନ୍ତୁ କିମ୍ବା ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"ନିଜ SD କାର୍ଡର କଣ୍ଟେଣ୍ଟ ସଂଶୋଧନ କିମ୍ବା ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"ଆପ୍କୁ USB ଷ୍ଟୋରେଜରେ ଲେଖିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"ଆପ୍କୁ SD କାର୍ଡରେ ଲେଖିବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_use_sip" msgid="2052499390128979920">"SIP କଲ୍ କରନ୍ତୁ ଏବଂ ଗ୍ରହଣ କରନ୍ତୁ"</string>
+ <string name="permdesc_use_sip" msgid="2297804849860225257">"ଆପ୍କୁ SIP କଲ୍ କରିବାକୁ ଏବଂ ପାଇବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"ନୂତନ ଦୂରସଂଚାର ସିମ୍ ସଂଯୋଗ ନଥିଭୁକ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"ନୂତନ ଦୂରସଂଚାର ସିମ୍ ସଂଯୋଗକୁ ନଥିଭୁକ୍ତ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+ <string name="permlab_register_call_provider" msgid="108102120289029841">"ନୂତନ ଦୂରସଂଚାର ସଂଯୋଗ ନଥିଭୁକ୍ତ କରନ୍ତୁ"</string>
+ <string name="permdesc_register_call_provider" msgid="7034310263521081388">"ନୂତନ ଦୂରସଂଚାର ସଂଯୋଗକୁ ନଥିଭୁକ୍ତ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"ଟେଲିକମ୍ ସଂଯୋଗ ପରିଚାଳିତ କରନ୍ତୁ"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"ଦୁରସଂଚାର ସଂଯୋଗ ପ୍ରବନ୍ଧିତ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+ <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ଇନ୍ କଲ୍ ସ୍କ୍ରୀନ୍ ସହିତ ସଂଯୋଗ କରନ୍ତୁ"</string>
+ <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ୟୁଜର୍ କଲ୍ ଇନ୍ ସ୍କ୍ରୀନ୍ କେବେ ଓ କିପରି ଦେଖୁଛି, ତାହାକୁ ନିୟନ୍ତ୍ରିତ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ଟେଲିଫୋନୀ ସେବା ସହିତ ସଂଯୋଗ କରନ୍ତୁ"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"ଆପ୍କୁ କଲ୍ କରିବା ଏବଂ ପ୍ରାପ୍ତ କରିବା ପାଇଁ ଟେଲିଫୋନୀ ସେବା ସହିତ ସଂଯୋଗ କରିବା ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+ <string name="permlab_control_incall_experience" msgid="9061024437607777619">"ଏକ କଲ୍ ୟୁଜର୍ ଅନୁଭବ ପ୍ରଦାନ କରିଥାଏ"</string>
+ <string name="permdesc_control_incall_experience" msgid="915159066039828124">"ଆପ୍କୁ ଇନ୍-କ୍ଲଲ୍ ୟୁଜର୍ ଅନୁଭବ ନେବାକୁ ଦେଇଥାଏ।"</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ଐତିହାସିକ ନେଟୱର୍କ ଉପଯୋଗ ବିଷୟରେ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"ନିର୍ଦ୍ଦିଷ୍ଟ ନେଟୱର୍କ ତଥା ଆପ୍ଗୁଡ଼ିକ ପାଇଁ ବିଗତ ଦିନର ନେଟୱର୍କ ବ୍ୟବହାର ପଢ଼ିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ନେଟ୍ୱର୍କ ପଲିସୀକୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ନେଟୱର୍କ ପଲିସୀ ପରିଚାଳନା କରିବାକୁ ଏବଂ ଆପ୍-ନିର୍ଦ୍ଦିଷ୍ଟ ନିୟମ ଧାର୍ଯ୍ୟ କରିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ନେଟ୍ୱର୍କ ବ୍ୟବହାର ଗଣନାକୁ ସଂଶୋଧନ କରନ୍ତୁ"</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ଆପ୍ ପାଇଁ କିପରି ନେଟ୍ୱର୍କ ବ୍ୟବହାର ଗଣନା କରାଯିବ, ସେଥିରେ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ସାମାନ୍ୟ ଆପ୍ ଦ୍ୱାରା ବ୍ୟବହାର କରାଯିବା ପାଇଁ ନୁହେଁ।"</string>
+ <string name="permlab_accessNotifications" msgid="7673416487873432268">"ବିଜ୍ଞପ୍ତି ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"ଅନ୍ୟ ଆପ୍ଲିକେଶନ୍ ଦ୍ୱାରା ପୋଷ୍ଟ କରାଯାଇଥିବାକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ବିଜ୍ଞପ୍ତିକୁ ହାସଲ, ପରୀକ୍ଷା, ତଥା ଖାଲି କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ଏକ ବିଜ୍ଞପ୍ତି ଶ୍ରୋତା ସେବା ସହିତ ଯୋଡ଼ିହୁଅନ୍ତୁ"</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ଶ୍ରୋତା ସେବାର ଶୀର୍ଷ-ସ୍ତର ଇଣ୍ଟରଫେସ୍କୁ ବାନ୍ଧିରଖିବା ପଇଁ ଧାରକକୁ ଅନୁମତି ଦିଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବ ନାହିଁ।"</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ଏକ ସର୍ତ୍ତାବଳୀ ପ୍ରଦାନକାରୀ ସେବା ସହିତ ଯୋଡ଼ିହୁଅନ୍ତୁ"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ଏକ ସ୍ଥିତି ପ୍ରଦାନକାରୀ ସେବାର ଶୀର୍ଷ-ସ୍ତର ଇଣ୍ଟରଫେସ୍ ବାନ୍ଧିରଖିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_bindDreamService" msgid="4153646965978563462">"ଏକ ଡ୍ରୀମ୍ ସେବା ସହିତ ଯୋଡ଼ିହୁଅନ୍ତୁ"</string>
+ <string name="permdesc_bindDreamService" msgid="7325825272223347863">"ଏକ ଡ୍ରୀମ୍ ସେବାର ଶୀର୍ଷ-ସ୍ତର ଇଣ୍ଟରଫେସ୍କୁ ବାନ୍ଧିରଖିବା ପାଇଁ ଧାରକକୁ ଅନୁମତି ଦିଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"କେରିଅରଙ୍କ ଦ୍ୱାରା ଦିଆଯାଇଥିବା କନଫିଗରେଶନ୍ ଆପ୍ ଆରମ୍ଭ କରନ୍ତୁ"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"କେରିଅର୍ ଦ୍ୱାରା ଦିଆଯାଇଥିବା କନଫିଗରେଶନ୍ ଆପ୍ ରଖିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ନେଟ୍ୱର୍କ ସ୍ଥିତିର ନୀରିକ୍ଷଣକୁ ଶୁଣନ୍ତୁ"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ନେଟ୍ୱର୍କ ସ୍ଥିତିରେ ନୀରିକ୍ଷଣ କରିବା ପାଇଁ ଗୋଟିଏ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦିଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବ ନାହିଁ।"</string>
+ <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ଇନପୁଟ୍ ଡିଭାଇସ୍ କାଲିବରେଶନ୍ ବଦଳାନ୍ତୁ"</string>
+ <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ଟଚ୍ ସ୍କ୍ରୀନ୍ର କାଲିବରେଶନ୍ ପାରାମିଟର୍ ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM ସର୍ଟିଫିକେଟ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM ସର୍ଟିଫିକେଟ୍ର ପ୍ରାବଧାନ ତଥା ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_handoverStatus" msgid="7820353257219300883">"Android ବିମ୍ ଟ୍ରାନ୍ସଫର୍ ଷ୍ଟାଟସ୍ ପ୍ରାପ୍ତ କରେ"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"କିଛି ସମୟ ପୂର୍ବରୁ ହୋଇଥିବା Android ବିମ୍ ଟ୍ରାନ୍ସଫର୍ ବିଷୟରେ ସୂଚନା ପ୍ରାପ୍ତ କରିବାକୁ ଏହି ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦେଇଥାଏ"</string>
+ <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM ସର୍ଟିଫିକେଟ୍ ଅପସାରଣ କରନ୍ତୁ"</string>
+ <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM ସାର୍ଟିଫିକେଟ୍ କୁ ହଟାଇବା ପାଇଁ ଏକ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହେବନାହିଁ।"</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ଏକ କେରିଅର୍ ମେସେଜିଙ୍ଗ ସେବା ସହିତ ଯୋଡ଼ିହୁଅନ୍ତୁ"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ଏକ କେରିଅର୍ ମେସେଜିଙ୍ଗ ସେବାର ଶୀର୍ଷ-ସ୍ତରୀୟ ଇଣ୍ଟରଫେସ୍ ବାନ୍ଧିରଖିବାକୁ ହୋଲ୍ଡରଙ୍କୁ ଅନୁମତି ଦିଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ ଆବଶ୍ୟକ କରାଯିବା ଉଚିତ ନୁହେଁ।"</string>
+ <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"କେରିଅର୍ ସେବାଗୁଡ଼ିକ ସହ ଯୋଡ଼ି ହୁଅନ୍ତୁ"</string>
+ <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"କେରିଅର୍ ସେବାଗୁଡ଼ିକ ସହିତ ଧାରକଙ୍କୁ ଯୋଡ଼ିଥାଏ। ସାମାନ୍ୟ ଆପ୍ ପାଇଁ କଦାପି ଆବଶ୍ୟକ ହୁଏନାହିଁ।"</string>
+ <string name="permlab_access_notification_policy" msgid="4247510821662059671">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="policylab_limitPassword" msgid="4497420728857585791">"ପାସ୍ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"ଲକ୍ ସ୍କ୍ରୀନ୍ ପାସ୍ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
+ <!-- no translation found for policylab_watchLogin (5091404125971980158) -->
+ <skip />
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ସ୍କ୍ରିନକୁ ଅନଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସ୍ୱର୍ଡ ସଂଖ୍ୟା ଉପରେ ନୀରିକ୍ଷଣ ରଖନ୍ତୁ ଏବଂ ଟିଭି ଲକ୍ କରନ୍ତୁ ଓ ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଛି, ତେବେ ସମସ୍ତ ଟିଭି ଡାଟାକୁ ହଟାଇଦିଅନ୍ତୁ।"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଫୋନ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟିଭିକୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policylab_resetPassword" msgid="4934707632423915395">"ସ୍କ୍ରୀନ୍ ଲକ୍ ବଦଳାନ୍ତୁ"</string>
+ <string name="policydesc_resetPassword" msgid="1278323891710619128">"ସ୍କ୍ରୀନ୍ ଲକ୍ ବଦଳାନ୍ତୁ।"</string>
+ <string name="policylab_forceLock" msgid="2274085384704248431">"ସ୍କ୍ରୀନ୍କୁ ଲକ୍ କରନ୍ତୁ"</string>
+ <string name="policydesc_forceLock" msgid="1141797588403827138">"ସ୍କ୍ରୀନ୍ କିପରି ଓ କେତେବେଳେ ଲକ୍ କରାଯିବ, ତାହା ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍ଲେଟ୍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+ <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟିଭିର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଫୋନ୍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+ <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"ୟୁଜର୍ ଡାଟା ଲିଭାନ୍ତୁ"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"ବିନା ଚେତାବନୀରେ ଏହି ଟାବଲେଟରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"ବିନା ଚେତାବନୀରେ ଏହି ଟିଭିରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"ବିନା ଚେତାବନୀରେ ଏହି ଫୋନରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
+ <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ଗ୍ଲୋବଲ୍ ପ୍ରକ୍ସୀ ଡିଭାଇସ୍କୁ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"ପଲିସୀ ସକ୍ଷମ କରାଯାଇଥିବାବେଳେ ବ୍ୟବହାର କରିବା ପାଇଁ ଗ୍ଲୋବାଲ୍ ପ୍ରକ୍ସୀ ସେଟ୍ କରନ୍ତୁ। କେବଳ ଡିଭାଇସ୍ ମାଲିକ ଗ୍ଲୋବାଲ୍ ପ୍ରକ୍ସୀ ସେଟ୍ କରିପାରିବେ।"</string>
+ <string name="policylab_expirePassword" msgid="5610055012328825874">"ସ୍କ୍ରୀନ୍ ଲକ୍ ପାସ୍ୱର୍ଡର ସମୟ ସମାପ୍ତି ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"ସ୍କ୍ରୀନ୍ ଲକ୍ ପାସ୍ୱର୍ଡ, PIN କିମ୍ବା ପାଟର୍ନ କେତେ ବ୍ୟବଧାନରେ ପରିବର୍ତ୍ତନ କରିବାକୁ ହେବ, ତାହା ପରିବର୍ତ୍ତନ କରନ୍ତୁ।"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ଷ୍ଟୋରେଜ୍ ଏନକ୍ରିପସନ୍କୁ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଡାଟା ଏନ୍କ୍ରେପ୍ଟ କରିବା ଆବଶ୍ୟକ।"</string>
+ <string name="policylab_disableCamera" msgid="6395301023152297826">"କ୍ୟାମେରାଗୁଡ଼ିକୁ ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="policydesc_disableCamera" msgid="2306349042834754597">"ସମସ୍ତ ଡିଭାଇସ୍ର କ୍ୟାମେରା ବ୍ୟବହାର କରିବା ପ୍ରତିରୋଧ କରନ୍ତୁ।"</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"କିଛି ସ୍କ୍ରୀନ୍ ଲକ୍ ସୁବିଧାକୁ ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"କିଛି ସ୍କ୍ରୀନ୍ ଲକ୍ ସୁବିଧା ବ୍ୟବହାର କରିବାରେ ପ୍ରତିରୋଧ କରନ୍ତୁ।"</string>
+ <string-array name="phoneTypes">
+ <item msgid="8901098336658710359">"ହୋମ୍"</item>
+ <item msgid="869923650527136615">"ମୋବାଇଲ୍"</item>
+ <item msgid="7897544654242874543">"ୱାର୍କ"</item>
+ <item msgid="1103601433382158155">"ୱାର୍କ ଫ୍ୟାକ୍ସ"</item>
+ <item msgid="1735177144948329370">"ହୋମ୍ ଫାକ୍ସ"</item>
+ <item msgid="603878674477207394">"ପେଜର୍"</item>
+ <item msgid="1650824275177931637">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="9192514806975898961">"କଷ୍ଟମ୍"</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item msgid="8073994352956129127">"ହୋମ୍"</item>
+ <item msgid="7084237356602625604">"ୱାର୍କ"</item>
+ <item msgid="1112044410659011023">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="2374913952870110618">"କଷ୍ଟମ୍"</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item msgid="6880257626740047286">"ହୋମ୍"</item>
+ <item msgid="5629153956045109251">"ୱାର୍କ"</item>
+ <item msgid="4966604264500343469">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="4932682847595299369">"କଷ୍ଟମ୍"</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item msgid="1738585194601476694">"ହୋମ୍"</item>
+ <item msgid="1359644565647383708">"ୱାର୍କ"</item>
+ <item msgid="7868549401053615677">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="3145118944639869809">"କଷ୍ଟମ୍"</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item msgid="7546335612189115615">"ୱାର୍କ"</item>
+ <item msgid="4378074129049520373">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="3455047468583965104">"କଷ୍ଟମ୍"</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item msgid="8595261363518459565">"AIM"</item>
+ <item msgid="7390473628275490700">"Windows Live"</item>
+ <item msgid="7882877134931458217">"Yahoo"</item>
+ <item msgid="5035376313200585242">"Skype"</item>
+ <item msgid="7532363178459444943">"QQ"</item>
+ <item msgid="3713441034299660749">"Google ଟକ୍"</item>
+ <item msgid="2506857312718630823">"ICQ"</item>
+ <item msgid="1648797903785279353">"Jabber"</item>
+ </string-array>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"କଷ୍ଟମ୍"</string>
+ <string name="phoneTypeHome" msgid="2570923463033985887">"ହୋମ୍"</string>
+ <string name="phoneTypeMobile" msgid="6501463557754751037">"ମୋବାଇଲ୍"</string>
+ <string name="phoneTypeWork" msgid="8863939667059911633">"ୱାର୍କ"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ୱାର୍କ ଫାକ୍ସ"</string>
+ <string name="phoneTypeFaxHome" msgid="2067265972322971467">"ହୋମ୍ ଫାକ୍ସ"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"ପେଜର୍"</string>
+ <string name="phoneTypeOther" msgid="1544425847868765990">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="phoneTypeCallback" msgid="2712175203065678206">"କଲବ୍ୟାକ୍"</string>
+ <string name="phoneTypeCar" msgid="8738360689616716982">"କାର୍"</string>
+ <string name="phoneTypeCompanyMain" msgid="540434356461478916">"କମ୍ପାନୀର ମୁଖ୍ୟ"</string>
+ <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
+ <string name="phoneTypeMain" msgid="6766137010628326916">"ମୁଖ୍ୟ"</string>
+ <string name="phoneTypeOtherFax" msgid="8587657145072446565">"ଅନ୍ୟ ଫାକ୍ସ"</string>
+ <string name="phoneTypeRadio" msgid="4093738079908667513">"ରେଡିଓ"</string>
+ <string name="phoneTypeTelex" msgid="3367879952476250512">"ଟେଲେକ୍ସ"</string>
+ <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"ୱାର୍କ ମୋବାଇଲ୍"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"ୱାର୍କ ପେଜର୍"</string>
+ <string name="phoneTypeAssistant" msgid="5596772636128562884">"ସହାୟକ"</string>
+ <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"କଷ୍ଟମ୍"</string>
+ <string name="eventTypeBirthday" msgid="2813379844211390740">"ଜନ୍ମଦିନ"</string>
+ <string name="eventTypeAnniversary" msgid="3876779744518284000">"ଆନିଭର୍ସରୀ"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"କଷ୍ଟମ୍"</string>
+ <string name="emailTypeHome" msgid="449227236140433919">"ହୋମ୍"</string>
+ <string name="emailTypeWork" msgid="3548058059601149973">"ୱାର୍କ"</string>
+ <string name="emailTypeOther" msgid="2923008695272639549">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="emailTypeMobile" msgid="119919005321166205">"ମୋବାଇଲ୍"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"କଷ୍ଟମ୍"</string>
+ <string name="postalTypeHome" msgid="8165756977184483097">"ହୋମ୍"</string>
+ <string name="postalTypeWork" msgid="5268172772387694495">"ୱାର୍କ"</string>
+ <string name="postalTypeOther" msgid="2726111966623584341">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"କଷ୍ଟମ୍"</string>
+ <string name="imTypeHome" msgid="6241181032954263892">"ହୋମ୍"</string>
+ <string name="imTypeWork" msgid="1371489290242433090">"ୱାର୍କ"</string>
+ <string name="imTypeOther" msgid="5377007495735915478">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"କଷ୍ଟମ୍"</string>
+ <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
+ <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
+ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
+ <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string>
+ <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string>
+ <string name="imProtocolGoogleTalk" msgid="493902321140277304">"ହ୍ୟାଙ୍ଗଆଉଟ୍ସ"</string>
+ <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string>
+ <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string>
+ <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
+ <string name="orgTypeWork" msgid="29268870505363872">"ୱାର୍କ"</string>
+ <string name="orgTypeOther" msgid="3951781131570124082">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"କଷ୍ଟମ୍"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"କଷ୍ଟମ୍"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"ସହାୟକ"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"ଭାଇ"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"ଶିଶୁ"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"ଡୋମେଷ୍ଟିକ୍ ପାର୍ଟନର୍"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"ପିତା"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"ସାଙ୍ଗ"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"ମ୍ୟାନେଜର୍"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"ମାତା"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"ଅଭିଭାବକ"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"ସହଭାଗୀ"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"ରେଫର୍ କରିଛନ୍ତି"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"ସମ୍ପର୍କୀୟ"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"ଭଉଣୀ"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"ସ୍ଵାମୀ ବା ସ୍ତ୍ରୀ"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"କଷ୍ଟମ୍"</string>
+ <string name="sipAddressTypeHome" msgid="6093598181069359295">"ଘର"</string>
+ <string name="sipAddressTypeWork" msgid="6920725730797099047">"ୱାର୍କ"</string>
+ <string name="sipAddressTypeOther" msgid="4408436162950119849">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ଏହି ଯୋଗାଯୋଗ ଦେଖିବାକୁ କୌଣସି ଆପ୍ଲିକେଶନ୍ ମିଳିଲା ନାହିଁ।"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK ଓ ନୂଆ PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK କୋଡ୍"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"ନୂଆ PIN କୋଡ୍"</string>
+ <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</font></string>
+ <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ଅନଲକ୍ କରିବାକୁ ପାସୱର୍ଡ ଟାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"ଅନଲକ୍ କରିବାକୁ PIN ଟାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ଭୁଲ PIN କୋଡ୍।"</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"ଅନଲକ୍ କରିବା ପାଇଁ, ପ୍ରଥମେ ମେନୁ ଓ ତା’ପରେ 0 ଦବାନ୍ତୁ।"</string>
+ <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"ଜରୁରୀକାଳୀନ ନମ୍ବର୍"</string>
+ <string name="lockscreen_carrier_default" msgid="6169005837238288522">"କୌଣସି ସେବା ନାହିଁ"</string>
+ <string name="lockscreen_screen_locked" msgid="7288443074806832904">"ସ୍କ୍ରୀନ୍ ଲକ୍ ହୋଇଯାଇଛି।"</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"ଅନଲକ୍ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ କିମ୍ବା ଜରୁରୀକାଳୀନ କଲ୍ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"ଅନଲକ୍ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"ଅନଲକ୍ କରିବା ପାଇଁ ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
+ <string name="lockscreen_emergency_call" msgid="5298642613417801888">"ଜରୁରୀକାଳୀନ"</string>
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"କଲ୍କୁ ଫେରନ୍ତୁ"</string>
+ <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"ଠିକ୍!"</string>
+ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+ <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+ <string name="lockscreen_storage_locked" msgid="9167551160010625200">"ସମସ୍ତ ସୁବିଧା ତଥା ଡାଟା ପାଇଁ ଅନଲକ୍ କରନ୍ତୁ"</string>
+ <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ମାଲିକର ମୁହଁ ଚିହ୍ନି ଅନଲକ୍ କରିବାର ସର୍ବାଧିକ ଧାର୍ଯ୍ୟ ସୀମା ଅତିକ୍ରମ କଲା"</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"କୌଣସି SIM କାର୍ଡ ନାହିଁ"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ଟାବଲେଟ୍ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"ଟିଭିରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ଫୋନ୍ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"ଏକ SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM କାର୍ଡ ନାହିଁ କିମ୍ବା ଖରାପ ଅଛି। SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"SIM କାର୍ଡଟି ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ।"</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"ଆପଣଙ୍କ SIM କାର୍ଡକୁ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।\n ଅନ୍ୟ SIM କାର୍ଡ ପାଇଁ ଆପଣଙ୍କ ୱାୟରଲେସ୍ ସେବା ପ୍ରଦାନକାରୀଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"ପୂର୍ବବର୍ତ୍ତୀ ଟ୍ରାକ୍"</string>
+ <string name="lockscreen_transport_next_description" msgid="573285210424377338">"ପରବର୍ତ୍ତୀ ଟ୍ରାକ୍"</string>
+ <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"ପଜ୍ କରନ୍ତୁ"</string>
+ <string name="lockscreen_transport_play_description" msgid="1901258823643886401">"ପ୍ଲେ କରନ୍ତୁ"</string>
+ <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"ପଛକୁ ନିଅନ୍ତୁ"</string>
+ <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"ଫାଷ୍ଟ ଫର୍ୱାର୍ଡ"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"କେବଳ ଜରୁରୀକାଳୀନ କଲ୍"</string>
+ <string name="lockscreen_network_locked_message" msgid="143389224986028501">"ନେଟ୍ୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM କାର୍ଡଟିରେ PUK ଲକ୍ ହୋଇଯାଇଛି।"</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ୟୁଜର୍ ଗାଇଡ୍ ଦେଖନ୍ତୁ କିମ୍ବା ଗ୍ରାହକ ସେବା କେନ୍ଦ୍ର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM କାର୍ଡ ଲକ୍ ହୋଇଯାଇଛି"</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM କାର୍ଡକୁ ଅନଲକ୍ କରାଯାଉଛି…"</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ଆପଣଙ୍କ ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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_password_attempts_dialog_message" msgid="2725973286239344555">"ଆପଣଙ୍କ ପାସୱର୍ଡକୁ ଆପଣ <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="6216672706545696955">"ଆପଣଙ୍କ 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="9191611984625460820">"ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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="5316664559603394684">"ଆପଣ ନିଜର ଲକ୍ ଖୋଲିବା ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଆଙ୍କିଛନ୍ତି। ଅଧିକ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଅସଫଳ ଚେଷ୍ଟା ପରେ ଆପଣଙ୍କ Google ସାଇନ୍-ଇନ୍ର ବ୍ୟବହାର କରି ନିଜ TV କୁ ଅନଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ। \n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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="6128106399745755604">"ଟାବଲେଟ୍କୁ ଅନ୍ଲକ୍ କରିବା ପାଇଁ <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="950408382418270260">"ଟିଭିକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଆପଣ <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="default" msgid="8603565142156826565">"ଫୋନ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <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="280873516493934365">"ଟାବଲେଟ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଟାବଲେଟ୍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"ଟିଭିକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ୍ ପ୍ରୟାସ କଲେ। ଟିଭିଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"ଫୋନ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଫୋନ୍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"ପାଟର୍ନ ଭୁଲି ଯାଇଛନ୍ତି କି?"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"ଆକାଉଣ୍ଟ ଅନଲକ୍"</string>
+ <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"ଅତ୍ୟଧିକ ପାଟର୍ନ ଉଦ୍ୟମ"</string>
+ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"ଅନଲକ୍ କରିବା ପାଇଁ, ନିଜ Google ଆକାଉଣ୍ଟରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ୟୁଜରନେମ୍ (ଇମେଲ୍)"</string>
+ <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ପାସ୍ୱର୍ଡ:"</string>
+ <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ସାଇନ୍-ଇନ୍"</string>
+ <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ୟୁଜର୍ନେମ୍ କିମ୍ୱା ପାସ୍ୱର୍ଡ ଭୁଲ୍ ଅଛି।"</string>
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ଆପଣଙ୍କର ଯୁଜରନେମ୍ କିମ୍ୱା ପାସୱାର୍ଡ ଭୁଲି ଯାଇଛନ୍ତି କି?\n"<b>"google.com/accounts/recovery"</b>" ଭିଜିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"ଅନଲକ୍"</string>
+ <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ସାଉଣ୍ଡ ଅନ୍ ଅଛି"</string>
+ <string name="lockscreen_sound_off_label" msgid="996822825154319026">"ସାଉଣ୍ଡ ଅଫ୍ ଅଛି"</string>
+ <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"ପାଟର୍ନ ଆରମ୍ଭ ହେଲା"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"ପାଟର୍ନ ଖାଲି କରାଗଲା"</string>
+ <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"ସେଲ୍ ଯୋଡ଼ାଗଲା"</string>
+ <string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"ସେଲ୍ <xliff:g id="CELL_INDEX">%1$s</xliff:g> ଯୋଡ଼ାଗଲା"</string>
+ <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"ପାଟର୍ନ ସମ୍ପୂର୍ଣ୍ଣ ହେଲା"</string>
+ <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"ପାଟର୍ନ କ୍ଷେତ୍ର।"</string>
+ <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s। %3$dରୁ %2$d ୱିଜେଟ୍।"</string>
+ <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ୱିଜେଟ୍ ଯୋଡ଼ନ୍ତୁ।"</string>
+ <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ଖାଲି କରନ୍ତୁ"</string>
+ <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ଅନଲକ୍ କ୍ଷେତ୍ରକୁ ବଢ଼ାଇଦିଆଯାଇଛି।"</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"ଅନଲକ୍ କ୍ଷେତ୍ର ଛୋଟ କରିଦିଆଯାଇଛି।"</string>
+ <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ୱିଜେଟ୍।"</string>
+ <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ୟୁଜର୍ ଚୟନକାରୀ"</string>
+ <string name="keyguard_accessibility_status" msgid="8008264603935930611">"ସ୍ଥିତି"</string>
+ <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"କ୍ୟାମେରା"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"ମିଡିଆ ନିୟନ୍ତ୍ରଣ"</string>
+ <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"ୱିଜେଟ୍ ପୁନଃ ସଜାଇବା ଆରମ୍ଭ ହେଲା।"</string>
+ <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"ୱିଜେଟ୍ ପୁନଃ ସଜାଇବା ଶେଷ ହେଲା।"</string>
+ <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ୱିଜେଟ୍ ଡିଲିଟ୍ କରିଦିଆଗଲା।"</string>
+ <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ଅନଲକ୍ କ୍ଷେତ୍ରକୁ ବଢ଼ାନ୍ତୁ।"</string>
+ <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"ସ୍ଲାଇଡ୍ ଅନଲକ୍।"</string>
+ <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ପାଟର୍ନ ଅନଲକ୍।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"ଫେସ୍ ଅନଲକ୍।"</string>
+ <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN ଅନଲକ୍।"</string>
+ <!-- no translation found for keyguard_accessibility_sim_pin_unlock (9149698847116962307) -->
+ <skip />
+ <!-- no translation found for keyguard_accessibility_sim_puk_unlock (9106899279724723341) -->
+ <skip />
+ <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ପାସ୍ୱର୍ଡ ଅନଲକ୍।"</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ପାଟର୍ନ କ୍ଷେତ୍ର।"</string>
+ <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ସ୍ଲାଇଡ୍ କ୍ଷେତ୍ର।"</string>
+ <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
+ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
+ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
+ <string name="granularity_label_character" msgid="7336470535385009523">"ବର୍ଣ୍ଣ"</string>
+ <string name="granularity_label_word" msgid="7075570328374918660">"ଶବ୍ଦ"</string>
+ <string name="granularity_label_link" msgid="5815508880782488267">"ଲିଙ୍କ"</string>
+ <string name="granularity_label_line" msgid="5764267235026120888">"ରେଖା"</string>
+ <string name="factorytest_failed" msgid="5410270329114212041">"ଫ୍ୟାକ୍ଟୋରୀ ଟେଷ୍ଟ ବିଫଳ ହୋଇଛି"</string>
+ <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST କାର୍ଯ୍ୟ କରିବା ପାଇଁ /system/appରେ ଇନଷ୍ଟଲ୍ ହୋଇଥିବା ପ୍ୟାକେଜ୍ ପାଇଁ କେବଳ ସପୋର୍ଟ କରେ।"</string>
+ <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST କାର୍ଯ୍ୟ କରିବା ପାଇଁ କୌଣସି ପ୍ୟାକେଜ୍ ମିଲିଲା ନାହିଁ।"</string>
+ <string name="factorytest_reboot" msgid="6320168203050791643">"ରିବୁଟ୍ କରନ୍ତୁ"</string>
+ <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\" ରେ ଥିବା ପୃଷ୍ଠାଟି କୁହେ:"</string>
+ <string name="js_dialog_title_default" msgid="6961903213729667573">"ଜାଭାସ୍କ୍ରୀପ୍ଟ"</string>
+ <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"ନେଭିଗେଶନ୍ ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"ଏହି ପୃଷ୍ଠାରୁ ବାହାରିଯାଆନ୍ତୁ"</string>
+ <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"ଏହି ପୃଷ୍ଠାରେ ରୁହନ୍ତୁ"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nଆପଣ କ’ଣ ପ୍ରକୃତରେ ଏହି ପୃଷ୍ଠାରୁ ଦୂରକୁ ନେଭିଗେଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?"</string>
+ <string name="save_password_label" msgid="6860261758665825069">"ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="double_tap_toast" msgid="4595046515400268881">"ଧ୍ୟାନଦିଅନ୍ତୁ: ଜୁମ୍ ଇନ୍ ଓ ଆଉଟ୍ କରିବା ପାଇଁ ଡବଲ୍-ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="autofill_this_form" msgid="4616758841157816676">"ସ୍ୱତଃପୂରଣ"</string>
+ <string name="setup_autofill" msgid="7103495070180590814">"ଅଟୋଫିଲ୍ ସେଟ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for autofill_window_title (921006636895825007) -->
+ <skip />
+ <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
+ <string name="autofill_province" msgid="2231806553863422300">"ଅଞ୍ଚଳ"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"ପୋଷ୍ଟାଲ୍ କୋଡ୍"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"ରାଜ୍ୟ"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"ZIP କୋଡ୍"</string>
+ <string name="autofill_county" msgid="237073771020362891">"କାଉଣ୍ଟୀ"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"ଆଇଲ୍ୟାଣ୍ଡ"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"ଜିଲ୍ଲା"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"ବିଭାଗ"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"ପ୍ରଶାସକୀୟ କ୍ଷେତ୍ର"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"ପ୍ୟାରିସ୍"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"କ୍ଷେତ୍ର"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"ଭୂଖଣ୍ଡ"</string>
+ <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"ଆପଣଙ୍କ ୱେବ୍ ବୁକ୍ମାର୍କ ଓ ହିଷ୍ଟୋରୀ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ବ୍ରାଉଜର୍ରେ ଭିଜିଟ୍ କରାଯାଇଥିବା ସମସ୍ତ URL ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍ ବ୍ରାଉଜ୍ କରିବା ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
+ <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"ୱେବ୍ ବୁକ୍ମାର୍କ ଓ ହିଷ୍ଟୋରୀ ଲେଖନ୍ତୁ"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍ ହିଷ୍ଟୋରୀ କିମ୍ବା ବୁକ୍ମାର୍କଗୁଡ଼ିକ ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହାଦ୍ୱାରା ଆପ୍ଟି ବ୍ରାଉଜର୍ ଡାଟା ଲିଭାଇପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍ ବ୍ରାଉଜ୍ କରିବାର ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ଆପଣଙ୍କ ଟିଭିରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍ ହିଷ୍ଟୋରୀ କିମ୍ବା ବୁକମାର୍କଗୁଡ଼ିକ ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହାଦ୍ୱାରା ଆପ୍ଟି ବ୍ରାଉଜର୍ ଡାଟା ଲିଭାଇପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଧ୍ୟାଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍ ବ୍ରାଉଜ୍ କରିବା ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେ୍ନ୍ଶରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍ ହିଷ୍ଟୋରୀ କିମ୍ବା ବୁକ୍ମାର୍କଗୁଡ଼ିକ ବଦଳାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଏହାଦ୍ୱାରା ଆପ୍ଟି ବ୍ରାଉଜର୍ ଡାଟା ଲିଭାଇପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍ ବ୍ରାଉଜ୍ କରିବାର ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
+ <string name="permlab_setAlarm" msgid="1379294556362091814">"ଏକ ଆଲର୍ମ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_setAlarm" msgid="316392039157473848">"ଆପ୍କୁ, ଇନଷ୍ଟଲ୍ ହୋଇଥିବା ଆଲାର୍ମ କ୍ଲକ୍ ଆପ୍ରେ ଏକ ଆଲାର୍ମ ସେଟ୍ କରିବାକୁ ଦେଇଥାଏ। କିଛି ଆଲର୍ମ କ୍ଲକ୍ ଆପ୍ ଏହି ବୈଶିଷ୍ଟ୍ୟ ଲାଗୁ କରିନପାରନ୍ତି।"</string>
+ <string name="permlab_addVoicemail" msgid="5525660026090959044">"ଭଏସ୍ମେଲ୍ ଯୋଡ଼ନ୍ତୁ"</string>
+ <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ଆପଣଙ୍କ ଭଏସମେଲ୍ ଇନ୍ବକ୍ସରେ ମେସେଜ୍ ଯୋଡ଼ିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ବ୍ରାଉଜରର ଭୌଗଳିକ ଅନୁମତି ସଂଶୋଧନ କରନ୍ତୁ"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ଆପ୍କୁ, ବ୍ରାଉଜର୍ର ଭୌଗଳିକ ଅନୁମତି ବଦଳାଇବାକୁ ଦେଇଥାଏ। ହାନୀକାରକ ଆପ୍ ଆର୍ବିଟେରୀ ୱେବ୍ ସାଇଟଗୁଡ଼ିକୁ ଲୋକେଶନ୍ ସୂଚନା ପଠାଇବା ପାଇଁ ଏହା ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
+ <string name="save_password_message" msgid="767344687139195790">"ବ୍ରାଉଜର୍ ଏହି ପାସୱର୍ଡକୁ ମନେରଖୁ ବୋଲି ଆପଣ ଚାହୁଁଛନ୍ତି କି?"</string>
+ <string name="save_password_notnow" msgid="6389675316706699758">"ବର୍ତ୍ତମାନ ନୁହେଁଁ"</string>
+ <string name="save_password_remember" msgid="6491879678996749466">"ମନେରଖନ୍ତୁ"</string>
+ <string name="save_password_never" msgid="8274330296785855105">"କଦାପି ନୁହେଁ"</string>
+ <string name="open_permission_deny" msgid="7374036708316629800">"ଏହି ପୃଷ୍ଠା ଖୋଲିବାକୁ ଆପଣଙ୍କ ପାଖରେ ଅନୁମତି ନାହିଁ।"</string>
+ <string name="text_copied" msgid="4985729524670131385">"ଟେକ୍ସଟ୍ କ୍ଲିପବୋର୍ଡକୁ କପୀ ହୋଇଯାଇଛି"</string>
+ <string name="more_item_label" msgid="4650918923083320495">"ଅଧିକ"</string>
+ <string name="prepend_shortcut_label" msgid="2572214461676015642">"ମେନୁ"</string>
+ <string name="menu_space_shortcut_label" msgid="2410328639272162537">"ସ୍ପେସ୍"</string>
+ <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"ଏଣ୍ଟର୍"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"ଡିଲିଟ୍"</string>
+ <string name="search_go" msgid="8298016669822141719">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="search_hint" msgid="1733947260773056054">"ସର୍ଚ୍ଚ…"</string>
+ <string name="searchview_description_search" msgid="6749826639098512120">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="searchview_description_query" msgid="5911778593125355124">"କ୍ୱେରୀ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="searchview_description_clear" msgid="1330281990951833033">"କ୍ୱେରୀ ଖାଲି କରନ୍ତୁ"</string>
+ <string name="searchview_description_submit" msgid="2688450133297983542">"କ୍ୱେରୀ ଦାଖଲ କରନ୍ତୁ"</string>
+ <string name="searchview_description_voice" msgid="2453203695674994440">"ଭଏସ୍ ସର୍ଚ୍ଚ"</string>
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବେ?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବାକୁ ଚାହେଁ। ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ଅନ୍ ଥିବାବେଳେ, ଆପଣଙ୍କ ଆଙ୍ଗୁଠି ତଳେ କ’ଣ ଅଛି, ତାହାର ବ୍ୟାଖ୍ୟା ଦେଖିପାରିବେ କିମ୍ବା ଟାବ୍ଲେଟ୍ ସହ କଥାବାର୍ତ୍ତା କରିବାକୁ ଜେଶ୍ଚର୍ କରିପାରିବେ।"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବାକୁ ଚାହେଁ। ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ଅନ୍ ଥିବାବେଳେ, ଆପଣଙ୍କ ଆଙ୍ଗୁଠି ତଳେ କ’ଣ ଅଛି, ତାହାର ବ୍ୟାଖ୍ୟା ଦେଖିପାରିବେ କିମ୍ବା ଫୋନ୍ ସହ କଥାବାର୍ତ୍ତା କରିବାକୁ ଜେଶ୍ଚର୍ କରିପାରିବେ।"</string>
+ <string name="oneMonthDurationPast" msgid="7396384508953779925">"1 ମାସ ପୂର୍ବରୁ"</string>
+ <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 ମାସ ପୂର୍ବରୁ"</string>
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">ଶେଷ <xliff:g id="COUNT_1">%d</xliff:g> ଦିନ</item>
+ <item quantity="one">ଶେଷ <xliff:g id="COUNT_0">%d</xliff:g> ଦିନ</item>
+ </plurals>
+ <string name="last_month" msgid="3959346739979055432">"ଶେଷ ମାସ"</string>
+ <string name="older" msgid="5211975022815554840">"ପୁରାତନ"</string>
+ <string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>ରେ"</string>
+ <string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>ରେ"</string>
+ <string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>ରେ"</string>
+ <string name="day" msgid="8144195776058119424">"ଦିନ"</string>
+ <string name="days" msgid="4774547661021344602">"ଦିନ"</string>
+ <string name="hour" msgid="2126771916426189481">"ଘଣ୍ଟା"</string>
+ <string name="hours" msgid="894424005266852993">"ଘଣ୍ଟା"</string>
+ <string name="minute" msgid="9148878657703769868">"ମିନିଟ୍"</string>
+ <string name="minutes" msgid="5646001005827034509">"ମିନିଟ୍"</string>
+ <string name="second" msgid="3184235808021478">"ସେକେଣ୍ଡ"</string>
+ <string name="seconds" msgid="3161515347216589235">"ସେକେଣ୍ଡ"</string>
+ <string name="week" msgid="5617961537173061583">"ସପ୍ତାହ"</string>
+ <string name="weeks" msgid="6509623834583944518">"ସପ୍ତାହ"</string>
+ <string name="year" msgid="4001118221013892076">"ବର୍ଷ"</string>
+ <string name="years" msgid="6881577717993213522">"ବର୍ଷ"</string>
+ <string name="now_string_shortest" msgid="8912796667087856402">"ବର୍ତ୍ତମାନ"</string>
+ <plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ମିନିଟ୍</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ମିନିଟ୍</item>
+ </plurals>
+ <plurals name="duration_hours_shortest" formatted="false" msgid="3552182110578602356">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ଘଣ୍ଟା</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ଘଣ୍ଟା</item>
+ </plurals>
+ <plurals name="duration_days_shortest" formatted="false" msgid="5213655532597081640">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ଦିନ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ଦିନ</item>
+ </plurals>
+ <plurals name="duration_years_shortest" formatted="false" msgid="7848711145196397042">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ବର୍ଷ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ବର୍ଷ</item>
+ </plurals>
+ <plurals name="duration_minutes_shortest_future" formatted="false" msgid="3277614521231489951">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ମିନିଟରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ମିନିଟରେ</item>
+ </plurals>
+ <plurals name="duration_hours_shortest_future" formatted="false" msgid="2152452368397489370">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ଘଣ୍ଟାରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ଘଣ୍ଟାରେ</item>
+ </plurals>
+ <plurals name="duration_days_shortest_future" formatted="false" msgid="8088331502820295701">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ଦିନରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ଦିନରେ</item>
+ </plurals>
+ <plurals name="duration_years_shortest_future" formatted="false" msgid="2317006667145250301">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ବର୍ଷରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ବର୍ଷରେ</item>
+ </plurals>
+ <plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ମିନିଟ୍ ପୂର୍ବେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ମିନିଟ୍ ପୂର୍ବେ</item>
+ </plurals>
+ <plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ଘଣ୍ଟା ପୂର୍ବେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ଘଣ୍ଟା ପୂର୍ବେ</item>
+ </plurals>
+ <plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ଦିନ ପୂର୍ବେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ଦିନ ପୂର୍ବେ</item>
+ </plurals>
+ <plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ବର୍ଷ ପୂର୍ବେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ବର୍ଷ ପୂର୍ବେ</item>
+ </plurals>
+ <plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ମିନିଟରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ମିନିଟରେ</item>
+ </plurals>
+ <plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ଘଣ୍ଟାରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ଘଣ୍ଟାରେ</item>
+ </plurals>
+ <plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ଦିନରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ଦିନରେ</item>
+ </plurals>
+ <plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ବର୍ଷରେ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ବର୍ଷରେ</item>
+ </plurals>
+ <string name="VideoView_error_title" msgid="3534509135438353077">"ଭିଡିଓ ସମସ୍ୟା"</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ଏହି ଡିଭାଇସ୍କୁ ଷ୍ଟ୍ରିମ୍ କରିବା ପାଇଁ ଏହି ଭିଡିଓ ମାନ୍ୟ ନୁହେଁ।"</string>
+ <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ଏହି ଭିଡିଓ ଚଲାଇ ହେବନାହିଁ"</string>
+ <string name="VideoView_error_button" msgid="2822238215100679592">"ଠିକ୍ ଅଛି"</string>
+ <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="noon" msgid="7245353528818587908">"ମଧ୍ୟାହ୍ନ"</string>
+ <string name="Noon" msgid="3342127745230013127">"ମଧ୍ୟାହ୍ନ"</string>
+ <string name="midnight" msgid="7166259508850457595">"ମଧ୍ୟରାତ୍ର"</string>
+ <string name="Midnight" msgid="5630806906897892201">"ମଧ୍ୟରାତ୍ର"</string>
+ <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
+ <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
+ <string name="selectAll" msgid="6876518925844129331">"ସବୁ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="cut" msgid="3092569408438626261">"କଟ୍"</string>
+ <string name="copy" msgid="2681946229533511987">"କପୀ"</string>
+ <!-- no translation found for failed_to_copy_to_clipboard (1833662432489814471) -->
+ <skip />
+ <string name="paste" msgid="5629880836805036433">"ପେଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="paste_as_plain_text" msgid="5427792741908010675">"ସାଦା ଟେକ୍ସଟ୍ ଭାବରେ ପେଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="replace" msgid="5781686059063148930">"ବଦଳାନ୍ତୁ…"</string>
+ <string name="delete" msgid="6098684844021697789">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="copyUrl" msgid="2538211579596067402">"URL କପୀ କରନ୍ତୁ"</string>
+ <string name="selectTextMode" msgid="1018691815143165326">"ଟେକ୍ସଟ୍ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="undo" msgid="7905788502491742328">"ପୂର୍ବ ପରି କରନ୍ତୁ"</string>
+ <string name="redo" msgid="7759464876566803888">"ପୁଣି କରନ୍ତୁ"</string>
+ <!-- no translation found for autofill (3035779615680565188) -->
+ <skip />
+ <string name="textSelectionCABTitle" msgid="5236850394370820357">"ଟେକ୍ସଟ୍ ଚୟନ"</string>
+ <string name="addToDictionary" msgid="4352161534510057874">"ଶବ୍ଦକୋଷରେ ଯୋଡ଼ନ୍ତୁ"</string>
+ <string name="deleteText" msgid="6979668428458199034">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="inputMethod" msgid="1653630062304567879">"ଇନପୁଟ୍ ପଦ୍ଧତି"</string>
+ <string name="editTextMenuTitle" msgid="4909135564941815494">"ଟେକ୍ସଟ୍ କାର୍ଯ୍ୟ"</string>
+ <!-- no translation found for email (4560673117055050403) -->
+ <skip />
+ <!-- no translation found for dial (1253998302767701559) -->
+ <skip />
+ <!-- no translation found for map (6521159124535543457) -->
+ <skip />
+ <!-- no translation found for browse (1245903488306147205) -->
+ <skip />
+ <!-- no translation found for sms (4560537514610063430) -->
+ <skip />
+ <!-- no translation found for add_contact (7867066569670597203) -->
+ <skip />
+ <!-- no translation found for view_calendar (979609872939597838) -->
+ <skip />
+ <!-- no translation found for add_calendar_event (1953664627192056206) -->
+ <skip />
+ <!-- no translation found for view_flight (7691640491425680214) -->
+ <skip />
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ଷ୍ଟୋରେଜ୍ ସ୍ପେସ୍ ଶେଷ ହେବାରେ ଲାଗିଛି"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"କିଛି ସିଷ୍ଟମ ଫଙ୍କଶନ୍ କାମ କରିନପାରେ"</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ସିଷ୍ଟମ୍ ପାଇଁ ପ୍ରର୍ଯ୍ୟାପ୍ତ ଷ୍ଟୋରେଜ୍ ନାହିଁ। ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ, ଆପଣଙ୍କ ପାଖରେ 250MB ଖାଲି ଜାଗା ଅଛି ଏବଂ ପୁନଃ ଆରମ୍ଭ କରନ୍ତୁ।"</string>
+ <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଚାଲୁଛି"</string>
+ <string name="app_running_notification_text" msgid="1197581823314971177">"ଅଧିକ ସୂଚନା ପାଇଁ କିମ୍ବା ଆପ୍ ବନ୍ଦ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="ok" msgid="5970060430562524910">"ଠିକ୍ ଅଛି"</string>
+ <string name="cancel" msgid="6442560571259935130">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="yes" msgid="5362982303337969312">"ଠିକ୍ ଅଛି"</string>
+ <string name="no" msgid="5141531044935541497">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="dialog_alert_title" msgid="2049658708609043103">"ଧ୍ୟାନଦିଅନ୍ତୁ"</string>
+ <string name="loading" msgid="7933681260296021180">"ଲୋଡ୍ କରାଯାଉଛି…"</string>
+ <string name="capital_on" msgid="1544682755514494298">"ଅନ୍"</string>
+ <string name="capital_off" msgid="6815870386972805832">"ଅଫ୍"</string>
+ <string name="whichApplication" msgid="4533185947064773386">"ବ୍ୟବହାର କରି କାର୍ଯ୍ୟ ସମ୍ପୂର୍ଣ୍ଣ କରନ୍ତୁ"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ବ୍ୟବହାର କରି କାର୍ଯ୍ୟ ସମ୍ପୂର୍ଣ୍ଣ କରନ୍ତୁ"</string>
+ <!-- no translation found for whichApplicationLabel (7425855495383818784) -->
+ <skip />
+ <string name="whichViewApplication" msgid="3272778576700572102">"ସହିତ ଖୋଲନ୍ତୁ"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ସହିତ ଖୋଲନ୍ତୁ"</string>
+ <!-- no translation found for whichViewApplicationLabel (2666774233008808473) -->
+ <skip />
+ <string name="whichEditApplication" msgid="144727838241402655">"ସହିତ ଏଡିଟ୍ କରନ୍ତୁ"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sରେ ସଂଶୋଧନ କରନ୍ତୁ"</string>
+ <!-- no translation found for whichEditApplicationLabel (7183524181625290300) -->
+ <skip />
+ <string name="whichSendApplication" msgid="6902512414057341668">"ଏହାଙ୍କ ସହ ଶେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s ସହିତ ଶେୟାର୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for whichSendApplicationLabel (4579076294675975354) -->
+ <skip />
+ <!-- no translation found for whichSendToApplication (8272422260066642057) -->
+ <skip />
+ <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
+ <skip />
+ <!-- no translation found for whichSendToApplicationLabel (8878962419005813500) -->
+ <skip />
+ <string name="whichHomeApplication" msgid="4307587691506919691">"ହୋମ୍ ଆପ୍ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"ହୋମ୍ ରୂପରେ %1$s ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <!-- no translation found for whichHomeApplicationLabel (809529747002918649) -->
+ <skip />
+ <!-- no translation found for whichImageCaptureApplication (3680261417470652882) -->
+ <skip />
+ <!-- no translation found for whichImageCaptureApplicationNamed (8619384150737825003) -->
+ <skip />
+ <!-- no translation found for whichImageCaptureApplicationLabel (6390303445371527066) -->
+ <skip />
+ <string name="alwaysUse" msgid="4583018368000610438">"ଏହି କାର୍ଯ୍ୟ ପାଇଁ ଡିଫଲ୍ଟ ଭାବେ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
+ <string name="use_a_different_app" msgid="8134926230585710243">"ଏକ ଭିନ୍ନ ଆପ୍ର ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="clearDefaultHintMsg" msgid="3252584689512077257">"\"ସିଷ୍ଟମ୍ ସେଟିଙ୍ଗ > ଆପ୍ > ଡାଉନଲୋଡ୍ କରାଯାଇଛି\"ରେ ଡିଫଲ୍ଟ ଖାଲି କରନ୍ତୁ।"</string>
+ <string name="chooseActivity" msgid="7486876147751803333">"ଏକ କାର୍ଯ୍ୟାନୁଷ୍ଠାନ ବାଛନ୍ତୁ"</string>
+ <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ଡିଭାଇସ୍ ପାଇଁ ଗୋଟିଏ ଆପ୍ ବାଛନ୍ତୁ"</string>
+ <string name="noApplications" msgid="2991814273936504689">"କୌଣସି ଆପ୍ ଏହି କାର୍ଯ୍ୟ କରିପାରିବ ନାହିଁ।"</string>
+ <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string>
+ <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string>
+ <!-- no translation found for aerr_application_repeated (3146328699537439573) -->
+ <skip />
+ <!-- no translation found for aerr_process_repeated (6235302956890402259) -->
+ <skip />
+ <string name="aerr_restart" msgid="7581308074153624475">"ଆପ୍କୁ ପୁଣି ଖୋଲନ୍ତୁ"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"ମତାମତ ପଠାନ୍ତୁ"</string>
+ <string name="aerr_close" msgid="2991640326563991340">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <!-- no translation found for aerr_mute (1974781923723235953) -->
+ <skip />
+ <!-- no translation found for aerr_wait (3199956902437040261) -->
+ <skip />
+ <!-- no translation found for aerr_close_app (3269334853724920302) -->
+ <skip />
+ <string name="anr_title" msgid="4351948481459135709"></string>
+ <!-- no translation found for anr_activity_application (8493290105678066167) -->
+ <skip />
+ <!-- no translation found for anr_activity_process (1622382268908620314) -->
+ <skip />
+ <!-- no translation found for anr_application_process (6417199034861140083) -->
+ <skip />
+ <!-- no translation found for anr_process (6156880875555921105) -->
+ <skip />
+ <string name="force_close" msgid="8346072094521265605">"ଠିକ୍ ଅଛି"</string>
+ <string name="report" msgid="4060218260984795706">"ରିପୋର୍ଟ"</string>
+ <string name="wait" msgid="7147118217226317732">"ଅପେକ୍ଷା କରନ୍ତୁ"</string>
+ <string name="webpage_unresponsive" msgid="3272758351138122503">"ଏହି ପୃଷ୍ଠାଟି ଚାଲୁନାହିଁ।\n\nଆପଣ ଏହାକୁ ବନ୍ଦ କରିବେ କି?"</string>
+ <string name="launch_warning_title" msgid="1547997780506713581">"ଆପ୍କୁ ରିଡାଇରେକ୍ଟ କରାଗଲା"</string>
+ <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଏବେ ଚାଲୁଅଛି।"</string>
+ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ବାସ୍ତବିକ ରୂପରେ ଲଞ୍ଚ କରାଯାଇଥିଲା।"</string>
+ <string name="screen_compat_mode_scale" msgid="3202955667675944499">"ସ୍କେଲ୍"</string>
+ <string name="screen_compat_mode_show" msgid="4013878876486655892">"ସର୍ବଦା ଦେଖାନ୍ତୁ"</string>
+ <string name="screen_compat_mode_hint" msgid="1064524084543304459">"\"ସିଷ୍ଟମ୍ ସେଟିଙ୍ଗ > ଆପ୍ > ଡାଉନଲୋଡ୍ କରାଯାଇଛି\"ରେ ଏହାକୁ ପୁନଃ-ସକ୍ଷମ କରନ୍ତୁ।"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବର୍ତ୍ତମାନର ଡିସ୍ପ୍ଲେ ଆକାର ସେଟିଙ୍ଗ ସପୋର୍ଟ କରେନାହିଁ ଏବଂ ଅପ୍ରତ୍ୟାଶିତ କାର୍ଯ୍ୟ କରିପାରେ।"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ସର୍ବଦା ଦେଖାନ୍ତୁ"</string>
+ <!-- no translation found for unsupported_compile_sdk_message (4253168368781441759) -->
+ <skip />
+ <!-- no translation found for unsupported_compile_sdk_show (2681877855260970231) -->
+ <skip />
+ <!-- no translation found for unsupported_compile_sdk_check_update (3312723623323216101) -->
+ <skip />
+ <string name="smv_application" msgid="3307209192155442829">"ଆପ୍ <xliff:g id="APPLICATION">%1$s</xliff:g> (ପ୍ରକ୍ରିୟା <xliff:g id="PROCESS">%2$s</xliff:g>) ଏହାର ସ୍ୱ-ଲାଗୁ କରାଯାଇଥିବା ଷ୍ଟ୍ରିକ୍ଟ-ମୋଡ୍ ପଲିସୀ ଉଲ୍ଲଂଘନ କରିଛି।"</string>
+ <string name="smv_process" msgid="5120397012047462446">"ଏହି {0/PROCESS<xliff:g id="PROCESS">%1$s</xliff:g> ନିଜ ଦ୍ୱାରା ଲାଗୁ କରାଯାଇଥିବା ଷ୍ଟ୍ରିକ୍ଟମୋଡ୍ ପଲିସୀକୁ ଉଲ୍ଲଂଘନ କରିଛି।"</string>
+ <!-- no translation found for android_upgrading_title (7513829952443484438) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (4503169817302593560) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (7009520271220804517) -->
+ <skip />
+ <!-- no translation found for android_start_title (4536778526365907780) -->
+ <skip />
+ <!-- no translation found for android_start_title (4929837533850340472) -->
+ <skip />
+ <!-- no translation found for android_start_title (7467484093260449437) -->
+ <skip />
+ <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ଷ୍ଟୋରେଜ୍ ବଢ଼ାଯାଉଛି"</string>
+ <!-- no translation found for android_upgrading_notification_title (1511552415039349062) -->
+ <skip />
+ <string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅପଗ୍ରେଡ୍ କରାଯାଉଛି…"</string>
+ <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ରୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଆପ୍ ଅନୁକୂଳନ କରୁଛି।"</string>
+ <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ପ୍ରସ୍ତୁତ କରାଯାଉଛି।"</string>
+ <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ଆପ୍ ଆରମ୍ଭ କରାଯାଉଛି।"</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"ବୁଟ୍ ସମାପ୍ତ କରୁଛି।"</string>
+ <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string>
+ <!-- no translation found for heavy_weight_notification_detail (2304833848484424985) -->
+ <skip />
+ <!-- no translation found for heavy_weight_switcher_title (387882830435195342) -->
+ <skip />
+ <!-- no translation found for heavy_weight_switcher_text (4176781660362912010) -->
+ <skip />
+ <!-- no translation found for old_app_action (3044685170829526403) -->
+ <skip />
+ <!-- no translation found for new_app_action (6694851182870774403) -->
+ <skip />
+ <!-- no translation found for new_app_description (5894852887817332322) -->
+ <skip />
+ <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> ଧାର୍ଯ୍ୟ ମେମୋରୀରୁ ବାହାରକୁ ଗଲା"</string>
+ <string name="dump_heap_notification_detail" msgid="6901391084243999274">"ହିପ୍ ଡମ୍ପ ସଂଗ୍ରହ କରାଯାଇଛି; ଶେୟାର୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="dump_heap_title" msgid="5864292264307651673">"ହିପ୍ ଡମ୍ପ ଶେୟାର୍ କରିବେ?"</string>
+ <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> ପ୍ରୋସେସ୍ ଏହାର ଧାର୍ଯ୍ୟ <xliff:g id="SIZE">%2$s</xliff:g> ମେମୋରୀ ସୀମାରୁ ବାହରକୁ ଗଲା। ଏହାର ଡେଭଲପରଙ୍କ ସହ ଶେୟାର୍ କରିବାକୁ ଏକ ହିପ୍ ଡମ୍ପ ଉପଲବ୍ଧ ଅଛି। ସାବଧାନ ରୁହନ୍ତୁ: ଆପ୍ଲିକେଶନର ଆକ୍ସେସ୍ ରହିଥିବା ଆପଣଙ୍କର ଯେକୌଣସି ବ୍ୟକ୍ତିଗତ ସୂଚନା ଏହି ହିପ୍ ଡମ୍ପରେ ରହିପାରେ।"</string>
+ <string name="sendText" msgid="5209874571959469142">"ଟେକ୍ସଟ୍ ପାଇଁ ଏକ କାର୍ଯ୍ୟ ବାଛନ୍ତୁ"</string>
+ <string name="volume_ringtone" msgid="6885421406845734650">"ରିଙ୍ଗର୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_music" msgid="5421651157138628171">"ମିଡିଆ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"ବ୍ଲୁ-ଟୁଥ୍ ମାଧ୍ୟମରେ ଚାଲୁଛି"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"ରିଙ୍ଗଟୋନ୍କୁ ନିରବ ଭାବେ ସେଟ୍ କରାଯାଇଛି"</string>
+ <string name="volume_call" msgid="3941680041282788711">"ଇନ୍-କଲ୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_bluetooth_call" msgid="2002891926351151534">"ବ୍ଲୁ-ଟୁଥ୍ ଇନ୍-କଲ୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_alarm" msgid="1985191616042689100">"ଆଲାର୍ମର ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_notification" msgid="2422265656744276715">"ବିଜ୍ଞପ୍ତି ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_unknown" msgid="1400219669770445902">"ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ବ୍ଲୁ-ଟୁଥ୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_icon_description_ringer" msgid="3326003847006162496">"ରିଙ୍ଗଟୋନ୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_icon_description_incall" msgid="8890073218154543397">"କଲ୍ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_icon_description_media" msgid="4217311719665194215">"ମିଡିଆ ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_icon_description_notification" msgid="7044986546477282274">"ବିଜ୍ଞପ୍ତି ଭଲ୍ୟୁମ୍"</string>
+ <string name="ringtone_default" msgid="3789758980357696936">"ଡିଫଲ୍ଟ ରିଙ୍ଗଟୋନ୍"</string>
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ଡିଫଲ୍ଟ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_silent" msgid="7937634392408977062">"କିଛିନୁହେଁ"</string>
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"ରିଙ୍ଗଟୋନ୍"</string>
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"ଆଲାର୍ମ ଶବ୍ଦ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ବିଜ୍ଞପ୍ତି ଶବ୍ଦ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ଅଜଣା"</string>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କଗୁଡ଼ିକ ଉପଲବ୍ଧ</item>
+ <item quantity="one">ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">ମୁକ୍ତ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କଗୁଡ଼ିକ ଉପଲବ୍ଧ</item>
+ <item quantity="one">ମୁକ୍ତ ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ</item>
+ </plurals>
+ <!-- no translation found for wifi_available_title (3817100557900599505) -->
+ <skip />
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
+ <!-- no translation found for wifi_available_title_connecting (1557292688310330032) -->
+ <skip />
+ <!-- no translation found for wifi_available_title_connected (7542672851522241548) -->
+ <skip />
+ <!-- no translation found for wifi_available_title_failed_to_connect (6861772233582618132) -->
+ <skip />
+ <!-- no translation found for wifi_available_content_failed_to_connect (3377406637062802645) -->
+ <skip />
+ <!-- no translation found for wifi_available_action_connect (2635699628459488788) -->
+ <skip />
+ <!-- no translation found for wifi_available_action_all_networks (4368435796357931006) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_onboarding_title (228772560195634292) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_onboarding_subtext (3989697580301186973) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_onboarding_action_disable (838648204200836028) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+ <skip />
+ <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+ <skip />
+ <string name="wifi_available_sign_in" msgid="9157196203958866662">"ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ"</string>
+ <string name="network_available_sign_in" msgid="1848877297365446605">"ନେଟ୍ୱର୍କରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
+ <skip />
+ <!-- no translation found for wifi_no_internet (8938267198124654938) -->
+ <skip />
+ <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>କୁ ବଦଳାଗଲା"</string>
+ <!-- no translation found for network_switch_metered_detail (775163331794506615) -->
+ <skip />
+ <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ରୁ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>କୁ ବଦଳାଗଲା"</string>
+ <!-- no translation found for network_switch_type_name:0 (3979506840912951943) -->
+ <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ଏକ ଅଜଣା ନେଟ୍ୱର୍କ ପ୍ରକାର"</string>
+ <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ୱାଇ-ଫାଇ ସହ ସଂଯୋଗ ହୋଇପାରିଲା ନାହିଁ"</string>
+ <string name="wifi_watchdog_network_disabled_detailed" msgid="4917472096696322767">" ଏହାର ଦୁର୍ବଳ ଇଣ୍ଟରନେଟ୍ ସଂଯୋଗ ରହିଛି।"</string>
+ <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ସଂଯୋଗର ଅନୁମତି ଦେବେ?"</string>
+ <string name="wifi_connect_alert_message" msgid="6451273376815958922">"ଆପ୍ଲିକେଶନ୍ %1$s %2$s ୱାଇ-ଫାଇ ନେଟୱର୍କକୁ ସଂଯୋଗ କରିବାକୁ ଚାହେଁ"</string>
+ <string name="wifi_connect_default_application" msgid="7143109390475484319">"ଏକ ଅନୁପ୍ରୟୋଗ"</string>
+ <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"ୱାଇ-ଫାଇ ଡାଇରେକ୍ଟ"</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ୱାଇ-ଫାଇ ଡାଇରେକ୍ଟ ଆରମ୍ଭ କରନ୍ତୁ। ଏହା ୱାଇ-ଫାଇ କ୍ଲାଏଣ୍ଟ/ହଟସ୍ପଟ୍କୁ ବନ୍ଦ କରିଦେବ।"</string>
+ <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"ୱାଇ-ଫାଇ ଡାଇରେକ୍ଟ ଆରମ୍ଭ କରିପାରିଲା ନାହିଁ।"</string>
+ <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"ୱାଇ-ଫାଇ ଡାଇରେକ୍ଟ ଅନ୍ ଅଛି"</string>
+ <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"ସେଟିଙ୍ଗ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="accept" msgid="1645267259272829559">"ସ୍ୱୀକାର କରନ୍ତୁ"</string>
+ <string name="decline" msgid="2112225451706137894">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
+ <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"ନିମନ୍ତ୍ରଣ ପଠାଗଲା"</string>
+ <string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"ସଂଯୁକ୍ତ ହେବାକୁ ନିମନ୍ତ୍ରଣ"</string>
+ <string name="wifi_p2p_from_message" msgid="570389174731951769">"ପ୍ରେରକ:"</string>
+ <string name="wifi_p2p_to_message" msgid="248968974522044099">"ପ୍ରାପ୍ତେଷୁ:"</string>
+ <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"ଆବଶ୍ୟକ PIN ଟାଇପ୍ କରନ୍ତୁ:"</string>
+ <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୁକ୍ତ ହୋଇଥିବାବେଳେ, ୱାଇ-ଫାଇଠାରୁ ଟାବଲେଟ୍ଟି ଅସ୍ଥାୟୀ ଭାବେ ବିଚ୍ଛିନ୍ନ ହେବ"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୋଗ ହେବାବେଳେ ଟିଭି ଅସ୍ଥାୟୀ ଭାବେ ୱାଇ-ଫାଇରୁ ବିଚ୍ଛିନ୍ନ ହେବ"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୋଗ ଥିବାବେଳେ ଫୋନ୍ଟି ୱାଇ-ଫାଇରୁ ଅସ୍ଥାୟୀ ଭାବରେ ବିଚ୍ଛିନ୍ନ ହେବ"</string>
+ <string name="select_character" msgid="3365550120617701745">"ବର୍ଣ୍ଣ ଲେଖନ୍ତୁ"</string>
+ <string name="sms_control_title" msgid="7296612781128917719">"SMS ମେସେଜ୍ଗୁଡ଼ିକୁ ପଠାଯାଉଛି"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ବହୁତ ସଂଖ୍ୟାର SMS ମେସେଜ୍ ପଠାଉଛି। ଏହି ଆପ୍ ମେସେଜ୍ ପଠାଇବା ଜାରି ରଖିବାକୁ ଆପଣ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="sms_control_yes" msgid="3663725993855816807">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="sms_control_no" msgid="625438561395534982">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
+ <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<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="5873295990846059400">"ଏହା ଦ୍ୱାରା "<b>" ଆପଣଙ୍କ ମୋବାଇଲ୍ ଆକାଉଣ୍ଟରୁ ପଇସା କଟିପାରେ। "</b></string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>" ଆପଣଙ୍କ ମୋବାଇଲ୍ ଆକାଉଣ୍ଟରୁ ପଇସା କଟିପାରେ। "</b></string>
+ <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ପଠାନ୍ତୁ"</string>
+ <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ମୋ ପସନ୍ଦ ମନେରଖନ୍ତୁ"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"ଏହାକୁ ଆପଣ ସେଟିଙ୍ଗ ଓ ଆପ୍ରେ ପରବର୍ତ୍ତୀ ସମୟରେ ବଦଳାଇପାରିବେ"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ସର୍ବଦା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ଆଦୌ ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"SIM କାର୍ଡ ବାହାର କରିଦିଆଯାଇଛି"</string>
+ <string name="sim_removed_message" msgid="2333164559970958645">"ଯେପର୍ଯ୍ୟନ୍ତ ଆପଣ କୌଣସି ବୈଧ SIM କାର୍ଡ ବ୍ୟବହାର କରି ରିଷ୍ଟାଟ୍ କରିନାହାନ୍ତି, ସେପର୍ଯ୍ୟନ୍ତ କୌଣସି ମୋବାଇଲ୍ ନେଟୱର୍କ ଉପଲବ୍ଧ ହେବନାହିଁ।"</string>
+ <string name="sim_done_button" msgid="827949989369963775">"ହୋଇଗଲା"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"SIM କାର୍ଡ ଯୋଡ଼ାଯାଇଛି"</string>
+ <string name="sim_added_message" msgid="6599945301141050216">"ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
+ <!-- no translation found for install_carrier_app_notification_title (9056007111024059888) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_text (3346681446158696001) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_text_app_name (1196505084835248137) -->
+ <skip />
+ <!-- no translation found for install_carrier_app_notification_button (3094206295081900849) -->
+ <skip />
+ <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+ <skip />
+ <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+ <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"ସମୟ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"ତାରିଖ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="date_time_set" msgid="5777075614321087758">"ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="date_time_done" msgid="2507683751759308828">"ହୋଇଗଲା"</string>
+ <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ନୂଆ: "</font></string>
+ <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଦ୍ୱରା ପ୍ରଦତ୍ତ।"</string>
+ <string name="no_permissions" msgid="7283357728219338112">"କୌଣସି ଅନୁମତିର ଆବଶ୍ୟକତା ନାହିଁ"</string>
+ <string name="perm_costs_money" msgid="4902470324142151116">"ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ"</string>
+ <string name="dlg_ok" msgid="7376953167039865701">"ଠିକ୍ ଅଛି"</string>
+ <!-- no translation found for usb_charging_notification_title (1595122345358177163) -->
+ <skip />
+ <!-- no translation found for usb_supplying_notification_title (4631045789893086181) -->
+ <skip />
+ <!-- no translation found for usb_mtp_notification_title (4238227258391151029) -->
+ <skip />
+ <!-- no translation found for usb_ptp_notification_title (5425857879922006878) -->
+ <skip />
+ <!-- no translation found for usb_tether_notification_title (3716143122035802501) -->
+ <skip />
+ <!-- no translation found for usb_midi_notification_title (5356040379749154805) -->
+ <skip />
+ <!-- no translation found for usb_accessory_notification_title (1899977434994900306) -->
+ <skip />
+ <string name="usb_notification_message" msgid="3370903770828407960">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for usb_power_notification_message (4647527153291917218) -->
+ <skip />
+ <!-- no translation found for usb_unsupported_audio_accessory_title (3529881374464628084) -->
+ <skip />
+ <!-- no translation found for usb_unsupported_audio_accessory_message (6309553946441565215) -->
+ <skip />
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ଡିବଗିଙ୍ଗ ସଂଯୁକ୍ତ ହୋଇଛି"</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ଡିବଗିଙ୍ଗକୁ ଅକ୍ଷମ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB ଡିବଗିଙ୍ଗକୁ ଅକ୍ଷମ କରିବା ପାଇଁ ଚୟନ କରନ୍ତୁ।"</string>
+ <!-- no translation found for taking_remote_bugreport_notification_title (6742483073875060934) -->
+ <skip />
+ <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
+ <skip />
+ <!-- no translation found for sharing_remote_bugreport_notification_title (7572089031496651372) -->
+ <skip />
+ <!-- no translation found for share_remote_bugreport_notification_message_finished (6029609949340992866) -->
+ <skip />
+ <!-- no translation found for share_remote_bugreport_action (6249476773913384948) -->
+ <skip />
+ <!-- no translation found for decline_remote_bugreport_action (6230987241608770062) -->
+ <skip />
+ <string name="select_input_method" msgid="8547250819326693584">"କୀ’ବୋର୍ଡ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="show_ime" msgid="2506087537466597099">"ଫିଜିକାଲ୍ କୀ’ବୋର୍ଡ ସକ୍ରିୟ ଥିବାବେଳେ ଏହାକୁ ସ୍କ୍ରୀନ୍ ଉପରେ ରଖନ୍ତୁ"</string>
+ <string name="hardware" msgid="194658061510127999">"ଭର୍ଚୁଆଲ୍ କୀ’ବୋର୍ଡ ଦେଖାନ୍ତୁ"</string>
+ <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
+ <skip />
+ <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
+ <skip />
+ <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+ <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+ <skip />
+ <!-- no translation found for alert_windows_notification_channel_name (3116610965549449803) -->
+ <skip />
+ <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
+ <skip />
+ <!-- no translation found for alert_windows_notification_message (8917232109522912560) -->
+ <skip />
+ <!-- no translation found for alert_windows_notification_turn_off_action (2902891971380544651) -->
+ <skip />
+ <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ପ୍ରସ୍ତୁତ କରାଯାଉଛି"</string>
+ <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ତ୍ରୁଟି ପାଇଁ ଯାଞ୍ଚ କରାଯାଉଛି"</string>
+ <string name="ext_media_new_notification_message" msgid="7589986898808506239">"ନୂଆ <xliff:g id="NAME">%s</xliff:g> ଚିହ୍ନଟ ହେଲା"</string>
+ <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ଫଟୋ ଓ ମିଡିଆ ସ୍ଥାନାନ୍ତର କରାଯିବା ପାଇଁ"</string>
+ <string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"<xliff:g id="NAME">%s</xliff:g> କରପ୍ଟ ହୋଇଯାଇଛି"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> କରପ୍ଟ ହୋଇଯାଇଛି। ଠିକ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for ext_media_unmountable_notification_message (3941179940297874950) -->
+ <skip />
+ <string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> ସପୋର୍ଟ କରୁନାହିଁ"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟ୍ରେ ସେଟ୍ ଅପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for ext_media_unsupported_notification_message (3725436899820390906) -->
+ <skip />
+ <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>କୁ ହଠାତ୍ କାଢ଼ିଦିଆଗଲା"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"ଡାଟା ନଷ୍ଟ ନହେବା ପାଇଁ ବାହାର କରିବା ପୂର୍ବରୁ <xliff:g id="NAME">%s</xliff:g>କୁ ଅନ୍ମାଉଣ୍ଟ କରନ୍ତୁ"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"<xliff:g id="NAME">%s</xliff:g> କାଢ଼ିଦିଆଗଲା"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"<xliff:g id="NAME">%s</xliff:g> ବାହାର କରାଗଲା; ନୂଆ ଗୋଟିଏ ଭର୍ତ୍ତି କରନ୍ତୁ"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"<xliff:g id="NAME">%s</xliff:g> ଏପର୍ଯ୍ୟନ୍ତ ବାହାର କରାଯାଉଛି…"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="4182843895023357756">"କାଢ଼ନ୍ତୁ ନାହିଁ"</string>
+ <string name="ext_media_init_action" msgid="7952885510091978278">"ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
+ <string name="ext_media_unmount_action" msgid="1121883233103278199">"ବାହାର କରନ୍ତୁ"</string>
+ <string name="ext_media_browse_action" msgid="8322172381028546087">"ଖୋଜନ୍ତୁ"</string>
+ <string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> ନାହିଁ"</string>
+ <string name="ext_media_missing_message" msgid="5761133583368750174">"ଏହି ଡିଭାଇସ୍ ପୁଣି ଭର୍ତ୍ତି କରନ୍ତୁ"</string>
+ <string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> ନିଆଯାଉଛି"</string>
+ <string name="ext_media_move_title" msgid="1022809140035962662">"ଡାଟା ନିଆଯାଉଛି"</string>
+ <string name="ext_media_move_success_title" msgid="8575300932957954671">"ନେବା ସମ୍ପୂର୍ଣ୍ଣ ହେଲା"</string>
+ <string name="ext_media_move_success_message" msgid="4199002148206265426">"ଡାଟା <xliff:g id="NAME">%s</xliff:g>କୁ ନିଆଗଲା"</string>
+ <string name="ext_media_move_failure_title" msgid="7613189040358789908">"ଡାଟା ନିଆଯାଇପାରିଲା ନାହିଁ"</string>
+ <string name="ext_media_move_failure_message" msgid="1978096440816403360">"ଡାଟାକୁ ମୂଳ ଲୋକେଶନରେ ଛାଡ଼ିଦିଆଗଲା"</string>
+ <string name="ext_media_status_removed" msgid="6576172423185918739">"ବାହାର କରିଦିଆଗଲା"</string>
+ <string name="ext_media_status_unmounted" msgid="2551560878416417752">"ବାହାର କରାଗଲା"</string>
+ <string name="ext_media_status_checking" msgid="6193921557423194949">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
+ <string name="ext_media_status_mounted" msgid="7253821726503179202">"ପ୍ରସ୍ତୁତ"</string>
+ <string name="ext_media_status_mounted_ro" msgid="8020978752406021015">"କେବଳ-ପଢ଼ିବା ପାଇଁ"</string>
+ <string name="ext_media_status_bad_removal" msgid="8395398567890329422">"ଅସୁରକ୍ଷିତ ଭାବେ କାଢ଼ିଦିଆଗଲା"</string>
+ <string name="ext_media_status_unmountable" msgid="805594039236667894">"କରପ୍ଟ ହୋଇଯାଇଛି"</string>
+ <string name="ext_media_status_unsupported" msgid="4691436711745681828">"ସପୋର୍ଟ କରୁନାହିଁ"</string>
+ <string name="ext_media_status_ejecting" msgid="5463887263101234174">"ବାହାର କରାଯାଉଛି…"</string>
+ <string name="ext_media_status_formatting" msgid="1085079556538644861">"ଫର୍ମାଟ୍ କରାଯାଉଛି…"</string>
+ <string name="ext_media_status_missing" msgid="5638633895221670766">"ଭର୍ତ୍ତି କରାଯାଇନାହିଁ"</string>
+ <string name="activity_list_empty" msgid="1675388330786841066">"କୌଣସି ଗତିବିଧି ମେଳ ହେଉନାହିଁ।"</string>
+ <string name="permlab_route_media_output" msgid="6243022988998972085">"ମିଡିଆ ଆଉଟପୁଟ୍କୁ ରୁଟ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_route_media_output" msgid="4932818749547244346">"ମିଡିଆ ଆଉଟ୍ପୁଟ୍କୁ ଅନ୍ୟ ଏକ୍ସଟର୍ନଲ୍ ଡିଭାଇସ୍ରେ ଚଲାଇବା ପାଇଁ ଆପ୍ଲିକେଶନ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_readInstallSessions" msgid="3713753067455750349">"ଇନଷ୍ଟଲ୍ ସେସନ୍ ପଢ଼ନ୍ତୁ"</string>
+ <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ଅନୁପ୍ରୟୋଗର ଇନଷ୍ଟଲ୍ ଅବଧିକୁ ପଢିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ସକ୍ରିୟ ପ୍ୟାକେଜ୍କୁ ଇନଷ୍ଟଲ୍ ବିଷୟରେ ବିବରଣୀ ଦେଖିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ପ୍ୟାକେଜ୍ ଇନଷ୍ଟଲ୍ କରିବା ପାଇଁ ଅନୁରୋଧ କରନ୍ତୁ"</string>
+ <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ପ୍ୟାକେଜଗୁଡ଼ିକର ଇନଷ୍ଟଲେଶନ୍ ଅନୁରୋଧ କରିବା ପାଇଁ ଆପ୍ଲିକେଶନକୁ ଅନୁମତି ଦିଏ।"</string>
+ <!-- no translation found for permlab_requestDeletePackages (1703686454657781242) -->
+ <skip />
+ <!-- no translation found for permdesc_requestDeletePackages (3406172963097595270) -->
+ <skip />
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ବ୍ୟାଟେରୀ ଅନୁକୂଳନ ଏଡ଼ାଇବା ପାଇଁ ପଚାରନ୍ତୁ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ଆପ୍ ପାଇଁ ବ୍ୟାଟେରୀ ଅନୁକୂଳନ ଏଡ଼ାଇବାର ଅନୁମତି ମାଗିବା ନିମନ୍ତେ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ଜୁମ୍ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଦୁଇଥର ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ୱିଜେଟ୍ ଯୋଡ଼ିପାରିବ ନାହିଁ।"</string>
+ <string name="ime_action_go" msgid="8320845651737369027">"ଯାଆନ୍ତୁ"</string>
+ <string name="ime_action_search" msgid="658110271822807811">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="ime_action_send" msgid="2316166556349314424">"ପଠାନ୍ତୁ"</string>
+ <string name="ime_action_next" msgid="3138843904009813834">"ପରବର୍ତ୍ତୀ"</string>
+ <string name="ime_action_done" msgid="8971516117910934605">"ହୋଇଗଲା"</string>
+ <string name="ime_action_previous" msgid="1443550039250105948">"ପୂର୍ବବର୍ତ୍ତୀ"</string>
+ <string name="ime_action_default" msgid="2840921885558045721">"କାମ କରନ୍ତୁ"</string>
+ <string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g>ବ୍ୟବହାର କରି\n ଡାଏଲ୍ କରନ୍ତୁ"</string>
+ <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g>ବ୍ୟବହାର କରି\n ଯୋଗାଯୋଗ ତିଆରି କରନ୍ତୁ"</string>
+ <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"ବର୍ତ୍ତମାନ ଓ ଭବିଷ୍ୟତରେ ଆପଣଙ୍କ ଆକାଉଣ୍ଟ ଆକ୍ସେସ୍ କରିବାକୁ ନିମ୍ନରୁ ଗୋଟିଏ କିମ୍ବା ଅଧିକ ଆପ୍ ଅନୁମତି ଅନୁରୋଧ କରନ୍ତି।"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"ଆପଣ ଏହି ଅନୁରୋଧକୁ ଅନୁମତି ଦେବାକୁ ଚାହାଁନ୍ତି କି?"</string>
+ <string name="grant_permissions_header_text" msgid="6874497408201826708">"ଆକ୍ସେସ୍ ଅନୁରୋଧ"</string>
+ <string name="allow" msgid="7225948811296386551">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="deny" msgid="2081879885755434506">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
+ <string name="permission_request_notification_title" msgid="6486759795926237907">"ଅନୁମତି ଅନୁରୋଧ କରାଯାଇଛି"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"<xliff:g id="ACCOUNT">%s</xliff:g> ଆକାଉଣ୍ଟ ପାଇଁ ଅନୁମତି\n ଅନୁରୋଧ କରାଯାଇଛି।"</string>
+ <string name="forward_intent_to_owner" msgid="1207197447013960896">"ଆପଣ ନିଜର ୱର୍କ ପ୍ରୋଫାଇଲ୍ ବାହାରେ ଏହି ଆପ୍ର ପ୍ରୟୋଗ କରୁଛନ୍ତି"</string>
+ <string name="forward_intent_to_work" msgid="621480743856004612">"ଆପଣ ନିଜ ୱର୍କ ପ୍ରୋଫାଇଲ୍ରେ ଏହି ଆପ୍ର ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
+ <string name="input_method_binding_label" msgid="1283557179944992649">"ଇନପୁଟ୍ ପଦ୍ଧତି"</string>
+ <string name="sync_binding_label" msgid="3687969138375092423">"ସିଙ୍କ୍"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"ଆକ୍ସେସିବିଲିଟୀ"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"ୱାଲପେପର୍"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"ୱାଲପେପର୍ ପରିବର୍ତ୍ତନ କରନ୍ତୁ।"</string>
+ <string name="notification_listener_binding_label" msgid="2014162835481906429">"ବିଜ୍ଞପ୍ତି ଶ୍ରୋତା"</string>
+ <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
+ <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ସର୍ତ୍ତ ପ୍ରଦାତା"</string>
+ <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
+ <skip />
+ <string name="vpn_title" msgid="19615213552042827">"VPN ସକ୍ରିୟ ହେଲା"</string>
+ <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ଦ୍ୱାରା VPN ସକ୍ରିୟ କରାଯାଇଛି"</string>
+ <string name="vpn_text" msgid="1610714069627824309">"ନେଟ୍ୱର୍କକୁ ପରିଚାଳନା କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>ରେ ସଂଯୋଗ କରାଯାଇଛି। ନେଟୱର୍କକୁ ପରିଚାଳନା କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ସର୍ବଦା-ଅନ୍ VPNରେ ସଂଯୋଗ କରୁଛି…"</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ସର୍ବଦା-ଅନ୍ VPN ସଂଯୁକ୍ତ"</string>
+ <!-- no translation found for vpn_lockdown_disconnected (735805531187559719) -->
+ <skip />
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"ସର୍ବଦା-ଅନ୍ VPN ତ୍ରୁଟି"</string>
+ <!-- no translation found for vpn_lockdown_config (8151951501116759194) -->
+ <skip />
+ <string name="upload_file" msgid="2897957172366730416">"ଫାଇଲ୍ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"କୌଣସି ଫାଇଲ୍ ଚୟନ କରାଯାଇନାହିଁ"</string>
+ <string name="reset" msgid="2448168080964209908">"ରିସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="submit" msgid="1602335572089911941">"ଦାଖଲ କରନ୍ତୁ"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"କାର୍ ମୋଡ୍ ସକ୍ଷମ କରାଯାଇଛି"</string>
+ <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"କାର୍ ମୋଡ୍ରୁ ବାହାରିଯିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"ଟିଥରିଙ୍ଗ କିମ୍ୱା ହଟସ୍ପଟ୍ ସକ୍ରିୟ ଅଛି"</string>
+ <string name="tethered_notification_message" msgid="2113628520792055377">"ସେଟଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for disable_tether_notification_title (7526977944111313195) -->
+ <skip />
+ <!-- no translation found for disable_tether_notification_message (2913366428516852495) -->
+ <skip />
+ <string name="back_button_label" msgid="2300470004503343439">"ଫେରନ୍ତୁ"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"ପରବର୍ତ୍ତୀ"</string>
+ <string name="skip_button_label" msgid="1275362299471631819">"ଛାଡ଼ିଦିଅନ୍ତୁ"</string>
+ <string name="no_matches" msgid="8129421908915840737">"କୌଣସି ମେଳକ ନାହିଁ"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"ପୃଷ୍ଠାରେ ଖୋଜନ୍ତୁ"</string>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>ରୁ <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1ଟି ମେଳ</item>
+ </plurals>
+ <string name="action_mode_done" msgid="7217581640461922289">"ହୋଇଗଲା"</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"USB ଷ୍ଟୋରେଜ୍ ଲିଭାଯାଉଛି…"</string>
+ <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD କାର୍ଡ ଲିଭାଯାଉଛି…"</string>
+ <string name="share" msgid="1778686618230011964">"ଶେୟାର୍"</string>
+ <string name="find" msgid="4808270900322985960">"ଖୋଜନ୍ତୁ"</string>
+ <string name="websearch" msgid="4337157977400211589">"ୱେବ୍ ସର୍ଚ୍ଚ"</string>
+ <string name="find_next" msgid="5742124618942193978">"ପରବର୍ତ୍ତୀ ଖୋଜନ୍ତୁ"</string>
+ <string name="find_previous" msgid="2196723669388360506">"ପୂର୍ବବର୍ତ୍ତୀ ଖୋଜନ୍ତୁ"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>ଙ୍କଠାରୁ ଲୋକେଶନ୍ ଅନୁରୋଧ ଆସିଛି"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"ଲୋକେଶନ୍ ଅନୁରୋଧ"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)ଙ୍କ ଦ୍ୱାରା ଅନୁରୋଧ କରାଯାଇଛି"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"ହଁ"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"ନା"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"ଡିଲିଟ୍ କରିବାର ସୀମା ଅତିକ୍ରମ ହୋଇଯାଇଛି"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> ଆକାଉଣ୍ଟର <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> ପାଇଁ <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> ଟି ଡିଲିଟ୍ କରାଯାଇଥିବା ଆଇଟମ୍ ରହିଛି। ଆପଣ କ’ଣ କରିବାକୁ ଚାହାଁନ୍ତି?"</string>
+ <string name="sync_really_delete" msgid="2572600103122596243">"ଆଇଟମ୍ ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="sync_undo_deletes" msgid="2941317360600338602">"ଡିଲିଟ୍ଗୁଡ଼ିକୁ ପୂର୍ବାବସ୍ଥାକୁ ଫେରାଇ ଆଣନ୍ତୁ"</string>
+ <string name="sync_do_nothing" msgid="3743764740430821845">"ଏବେ କିଛି କରନ୍ତୁ ନାହିଁ"</string>
+ <string name="choose_account_label" msgid="5655203089746423927">"ଗୋଟିଏ ଆକାଉଣ୍ଟର ଚୟନ କରନ୍ତୁ"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"ଗୋଟିଏ ଆକାଉଣ୍ଟ ଯୋଡ଼ନ୍ତୁ"</string>
+ <string name="add_account_button_label" msgid="3611982894853435874">"ଆକାଉଣ୍ଟ ଯୋଡ଼ନ୍ତୁ"</string>
+ <string name="number_picker_increment_button" msgid="2412072272832284313">"ବଢ଼ାନ୍ତୁ"</string>
+ <string name="number_picker_decrement_button" msgid="476050778386779067">"କମ୍ କରନ୍ତୁ"</string>
+ <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> ସ୍ପର୍ଶ କରନ୍ତୁ ଏବଂ ଧରିରଖନ୍ତୁ"</string>
+ <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"ବଢ଼ାଇବା ପାଇଁ ଉପରକୁ ଓ କମାଇବା ପାଇଁ ତଳକୁ ସ୍ଲାଇଡ୍ କରନ୍ତୁ।"</string>
+ <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"ମିନିଟ୍ ବଢ଼ାନ୍ତୁ"</string>
+ <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"ମିନିଟ୍ କମ୍ କରନ୍ତୁ"</string>
+ <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"ଘଣ୍ଟା ବଢ଼ାନ୍ତୁ"</string>
+ <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ଘଣ୍ଟା କମ୍ କରନ୍ତୁ"</string>
+ <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="date_picker_increment_month_button" msgid="5369998479067934110">"ମାସ ବଢ଼ାନ୍ତୁ"</string>
+ <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"ମାସ କମ୍ କରନ୍ତୁ"</string>
+ <string name="date_picker_increment_day_button" msgid="7130465412308173903">"ଦିନ ବଢ଼ାନ୍ତୁ"</string>
+ <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ଦିନ କମ୍ କରନ୍ତୁ"</string>
+ <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ବର୍ଷ ବଢ଼ାନ୍ତୁ"</string>
+ <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ବର୍ଷ କମ୍ କରନ୍ତୁ"</string>
+ <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ପୂର୍ବ ମାସ"</string>
+ <string name="date_picker_next_month_button" msgid="5559507736887605055">"ପରବର୍ତ୍ତୀ ମାସ"</string>
+ <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"ALT"</string>
+ <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="keyboardview_keycode_done" msgid="1992571118466679775">"ହୋଇଗଲା"</string>
+ <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ମୋଡ୍ ପରିବର୍ତ୍ତନ"</string>
+ <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"ଶିଫ୍ଟ"</string>
+ <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"ଏଣ୍ଟର୍"</string>
+ <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ଗୋଟିଏ ଆପ୍ ବାଛନ୍ତୁ"</string>
+ <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ଲଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ"</string>
+ <string name="shareactionprovider_share_with" msgid="806688056141131819">"ଏହାଙ୍କ ସହ ଶେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ସହ ଶେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="content_description_sliding_handle" msgid="415975056159262248">"ହ୍ୟାଣ୍ଡେଲ୍ ସ୍ଲାଇଡ୍ କରାଯାଉଛି। ସ୍ପର୍ଶ କରି ଧରିରଖନ୍ତୁ।"</string>
+ <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ଅନଲକ୍ କରିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="action_bar_home_description" msgid="5293600496601490216">"ହୋମ୍ ପେଜ୍କୁ ନେଭିଗେଟ୍ କରନ୍ତୁ"</string>
+ <string name="action_bar_up_description" msgid="2237496562952152589">"ଉପରକୁ ନେଭିଗେଟ୍ କରନ୍ତୁ"</string>
+ <string name="action_menu_overflow_description" msgid="2295659037509008453">"ଅଧିକ ବିକଳ୍ପ"</string>
+ <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
+ <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
+ <string name="storage_sd_card" msgid="3282948861378286745">"SD କାର୍ଡ"</string>
+ <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD କାର୍ଡ"</string>
+ <string name="storage_usb_drive" msgid="6261899683292244209">"USB ଡ୍ରାଇଭ୍"</string>
+ <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ଡ୍ରାଇଭ୍"</string>
+ <string name="storage_usb" msgid="3017954059538517278">"USB ଷ୍ଟୋରେଜ୍"</string>
+ <string name="extract_edit_menu_button" msgid="8940478730496610137">"ଏଡିଟ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for data_usage_warning_title (6499834033204801605) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (7340198905103751676) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (6561099244084267376) -->
+ <skip />
+ <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"ୱାଇ-ଫାଇ ଡାଟା ସୀମାରେ ପହଞ୍ଚିଗଲା"</string>
+ <!-- no translation found for data_usage_limit_body (2908179506560812973) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_snoozed_title (3171402244827034372) -->
+ <skip />
+ <!-- no translation found for data_usage_wifi_limit_snoozed_title (3547771791046344188) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_snoozed_body (1671222777207603301) -->
+ <skip />
+ <string name="data_usage_restricted_title" msgid="5965157361036321914">"ବ୍ୟାକଗ୍ରାଉଣ୍ଡ ଡାଟା ପ୍ରତିବନ୍ଧିତ"</string>
+ <string name="data_usage_restricted_body" msgid="469866376337242726">"ପ୍ରତିବନ୍ଧକ ବାହାର କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for data_usage_rapid_title (1809795402975261331) -->
+ <skip />
+ <!-- no translation found for data_usage_rapid_body (6897825788682442715) -->
+ <skip />
+ <!-- no translation found for data_usage_rapid_app_body (5396680996784142544) -->
+ <skip />
+ <string name="ssl_certificate" msgid="6510040486049237639">"ସୁରକ୍ଷା ସର୍ଟିଫିକେଟ୍"</string>
+ <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ସର୍ଟିଫିକେଟ୍ ବୈଧ ନୁହେଁ।"</string>
+ <string name="issued_to" msgid="454239480274921032">"ଏହାଙ୍କୁ ଜାରି କରାଯାଇଛି:"</string>
+ <string name="common_name" msgid="2233209299434172646">"ସାଧାରଣ ନାମ:"</string>
+ <string name="org_name" msgid="6973561190762085236">"ସଂସ୍ଥା:"</string>
+ <string name="org_unit" msgid="7265981890422070383">"ସଂଗଠନାତ୍ମକ ୟୁନିଟ୍:"</string>
+ <string name="issued_by" msgid="2647584988057481566">"ଜାରି କରିଛନ୍ତି:"</string>
+ <string name="validity_period" msgid="8818886137545983110">"ବୈଧତା:"</string>
+ <string name="issued_on" msgid="5895017404361397232">"ଜାରି କରାଯାଇଥିବା ତାରିଖ:"</string>
+ <string name="expires_on" msgid="3676242949915959821">"ସମାପ୍ତ ହେବାର ତାରିଖ ହେଉଛି:"</string>
+ <string name="serial_number" msgid="758814067660862493">"କ୍ରମିକ ସଂଖ୍ୟା:"</string>
+ <string name="fingerprints" msgid="4516019619850763049">"ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
+ <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
+ <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
+ <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ସମସ୍ତ ଦେଖନ୍ତୁ"</string>
+ <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ଗତିବିଧି ଚୟନ କରନ୍ତୁ"</string>
+ <string name="share_action_provider_share_with" msgid="5247684435979149216">"ଏହାଙ୍କ ସହ ଶେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="sending" msgid="3245653681008218030">"ପଠାଯାଉଛି…"</string>
+ <string name="launchBrowserDefault" msgid="2057951947297614725">"ବ୍ରାଉଜର୍ ଲଞ୍ଚ କରିବେ?"</string>
+ <string name="SetupCallDefault" msgid="5834948469253758575">"କଲ୍ ସ୍ୱୀକାର କରିବେ?"</string>
+ <string name="activity_resolver_use_always" msgid="8017770747801494933">"ସର୍ବଦା"</string>
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"ଥରେ ମାତ୍ର"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ୱର୍କ ପ୍ରୋଫାଇଲ୍କୁ ସପୋର୍ଟ କରୁନାହିଁ"</string>
+ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ଟାବଲେଟ୍"</string>
+ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string>
+ <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ଫୋନ୍"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ଡକ୍ ସ୍ପିକର୍"</string>
+ <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) -->
+ <skip />
+ <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ହେଡଫୋନ୍"</string>
+ <!-- no translation found for default_audio_route_name_usb (1234984851352637769) -->
+ <skip />
+ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ସିଷ୍ଟମ୍"</string>
+ <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ବ୍ଲୁ-ଟୁଥ୍ ଅଡିଓ"</string>
+ <string name="wireless_display_route_description" msgid="9070346425023979651">"ୱେୟାର୍ଲେସ୍ ଡିସ୍ପ୍ଲେ"</string>
+ <string name="media_route_button_content_description" msgid="591703006349356016">"କାଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="media_route_chooser_title" msgid="1751618554539087622">"ଡିଭାଇସ୍ ସଂଯୋଗ କରନ୍ତୁ"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ଡିଭାଇସ୍ରେ ସ୍କ୍ରୀନ୍ କାଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"ଡିଭାଇସ୍ ଖୋଜାଯାଉଛି…"</string>
+ <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ସେଟିଙ୍ଗ"</string>
+ <string name="media_route_controller_disconnect" msgid="8966120286374158649">"ବିଛିନ୍ନ କରନ୍ତୁ"</string>
+ <string name="media_route_status_scanning" msgid="7279908761758293783">"ସ୍କାନ୍ କରୁଛି…"</string>
+ <string name="media_route_status_connecting" msgid="6422571716007825440">"ସଂଯୋଗ କରୁଛି..."</string>
+ <string name="media_route_status_available" msgid="6983258067194649391">"ଉପଲବ୍ଧ"</string>
+ <string name="media_route_status_not_available" msgid="6739899962681886401">"ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="media_route_status_in_use" msgid="4533786031090198063">"ବ୍ୟବହାରରେ ଅଛି"</string>
+ <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"ବିଲ୍ଟ-ଇନ୍ ସ୍କ୍ରୀନ୍"</string>
+ <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ସ୍କ୍ରୀନ୍"</string>
+ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ପ୍ରାୟତଃ #<xliff:g id="ID">%1$d</xliff:g>"</string>
+ <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<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="6022119702628572080">", ସୁରକ୍ଷିତ"</string>
+ <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ପାଟର୍ନ ଭୁଲି ଯାଇଛନ୍ତି"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"ଭୁଲ ପାଟର୍ନ"</string>
+ <string name="kg_wrong_password" msgid="2333281762128113157">"ଭୁଲ ପାସ୍ୱର୍ଡ"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"ଭୁଲ PIN"</string>
+ <!-- no translation found for kg_too_many_failed_attempts_countdown (8790651267324125694) -->
+ <string name="kg_pattern_instructions" msgid="398978611683075868">"ନିଜ ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ଲେଖନ୍ତୁ"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ଲେଖନ୍ତୁ"</string>
+ <string name="kg_password_instructions" msgid="5753646556186936819">"ପାସ୍ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ୍ ଏଣ୍ଟର୍ କରନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କେରିଅର୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ଲେଖନ୍ତୁ"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM କାର୍ଡ ଅନଲକ୍ କରାଯାଉଛି…"</string>
+ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"ଭୁଲ PIN କୋଡ୍।"</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 ରୁ 8 ନମ୍ବର ବିଶିଷ୍ଟ ଏକ PIN ଟାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK କୋଡ୍ରେ 8ଟି ନମ୍ବର ରହିଥାଏ।"</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"ଠିକ୍ PUK କୋଡ୍ ପୁଣି ଲେଖନ୍ତୁ। ବାରମ୍ବାର ପ୍ରୟାସ କଲେ SIM କାର୍ଡ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ ହୋଇଯିବ।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN କୋଡ୍ ମେଳ ଖାଉନାହିଁ"</string>
+ <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ଅନେକ ପାଟର୍ନ ପ୍ରୟାସ"</string>
+ <string name="kg_login_instructions" msgid="1100551261265506448">"ଅନଲକ୍ କରିବା ପାଇଁ, ଆପଣଙ୍କ Google ଆକାଉଣ୍ଟ ସହ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ।"</string>
+ <string name="kg_login_username_hint" msgid="5718534272070920364">"ୟୁଜରନେମ୍ (ଇମେଲ୍)"</string>
+ <string name="kg_login_password_hint" msgid="9057289103827298549">"ପାସ୍ୱର୍ଡ"</string>
+ <string name="kg_login_submit_button" msgid="5355904582674054702">"ସାଇନ୍-ଇନ୍"</string>
+ <string name="kg_login_invalid_input" msgid="5754664119319872197">"ଅମାନ୍ୟ ୟୁଜରନେମ୍ କିମ୍ୱା ପାସ୍ୱର୍ଡ।"</string>
+ <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ଆପଣଙ୍କର ୟୁଜରନେମ୍ କିମ୍ୱା ପାସ୍ୱର୍ଡ ଭୁଲି ଯାଇଛନ୍ତି କି?\n"<b>"google.com/accounts/recovery"</b>" ଭିଜିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="kg_login_checking_password" msgid="1052685197710252395">"ଆକାଉଣ୍ଟ ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"ଆପଣଙ୍କ PINକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ \n\nପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"ଆପଣଙ୍କ ପାସ୍ୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ \n\nପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ଆପଣଙ୍କ ଲକ୍ ଖୋଲିବା ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ \n\nପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"ଟାବଲେଟ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <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="5621231220154419413">"ଟିଭିଟିକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଆପଣ <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="default" msgid="4051015943038199910">"ଫୋନ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <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="2072996269148483637">"ଟାବଲେଟ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଟାବଲେଟ୍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"ଟିଭିକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ୍ ପ୍ରୟାସ କଲେ। ଟିଭିଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"ଫୋନ୍ ଅନଲକ୍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଫୋନ୍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ଆପଣଙ୍କ ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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="4224651132862313471">"ଆପଣଙ୍କ ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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="1437638152015574839">"ଆପଣଙ୍କ ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <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="4160700433287233771">" — "</string>
+ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ବାହାର କରନ୍ତୁ"</string>
+ <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିସ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
+ <!-- no translation found for accessibility_shortcut_warning_dialog_title (8404780875025725199) -->
+ <skip />
+ <!-- no translation found for accessibility_shortcut_toogle_warning (7256507885737444807) -->
+ <skip />
+ <!-- no translation found for disable_accessibility_shortcut (627625354248453445) -->
+ <skip />
+ <!-- no translation found for leave_accessibility_shortcut_on (7653111894438512680) -->
+ <skip />
+ <!-- no translation found for color_inversion_feature_name (4231186527799958644) -->
+ <skip />
+ <!-- no translation found for color_correction_feature_name (6779391426096954933) -->
+ <skip />
+ <!-- no translation found for accessibility_shortcut_enabling_service (7771852911861522636) -->
+ <skip />
+ <!-- no translation found for accessibility_shortcut_disabling_service (2747243438223109821) -->
+ <skip />
+ <!-- no translation found for accessibility_button_prompt_text (4234556536456854251) -->
+ <skip />
+ <!-- no translation found for accessibility_button_instructional_text (6942300463612999993) -->
+ <skip />
+ <!-- no translation found for accessibility_magnification_chooser_text (1227146738764986237) -->
+ <skip />
+ <string name="user_switched" msgid="3768006783166984410">"ବର୍ତ୍ତମାନର ୟୁଜର୍ ହେଉଛନ୍ତି <xliff:g id="NAME">%1$s</xliff:g>।"</string>
+ <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> ରେ ସୁଇଚ୍ କରନ୍ତୁ…"</string>
+ <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g>ଙ୍କୁ ଲଗଆଉଟ୍ କରାଯାଉଛି…"</string>
+ <string name="owner_name" msgid="2716755460376028154">"ମାଲିକ"</string>
+ <string name="error_message_title" msgid="4510373083082500195">"ତ୍ରୁଟି"</string>
+ <!-- no translation found for error_message_change_not_allowed (1238035947357923497) -->
+ <skip />
+ <string name="app_not_found" msgid="3429141853498927379">"ଏହି କାର୍ଯ୍ୟକୁ ନିୟନ୍ତ୍ରଣ କରିବା ପାଇଁ କୌଣସି ଆପ୍ଲିକେଶନ୍ ମିଳିଲା ନାହିଁ"</string>
+ <string name="revoke" msgid="5404479185228271586">"ବାହାର କରନ୍ତୁ"</string>
+ <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
+ <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string>
+ <string name="mediasize_iso_a2" msgid="3097535991925798280">"ISO A2"</string>
+ <string name="mediasize_iso_a3" msgid="3023213259314236123">"ISO A3"</string>
+ <string name="mediasize_iso_a4" msgid="231745325296873764">"ISO A4"</string>
+ <string name="mediasize_iso_a5" msgid="3484327407340865411">"ISO A5"</string>
+ <string name="mediasize_iso_a6" msgid="4861908487129577530">"ISO A6"</string>
+ <string name="mediasize_iso_a7" msgid="5890208588072936130">"ISO A7"</string>
+ <string name="mediasize_iso_a8" msgid="4319425041085816612">"ISO A8"</string>
+ <string name="mediasize_iso_a9" msgid="4882220529506432008">"ISO A9"</string>
+ <string name="mediasize_iso_a10" msgid="2382866026365359391">"ISO A10"</string>
+ <string name="mediasize_iso_b0" msgid="3651827147402009675">"ISO B0"</string>
+ <string name="mediasize_iso_b1" msgid="6072859628278739957">"ISO B1"</string>
+ <string name="mediasize_iso_b2" msgid="1348731852150380378">"ISO B2"</string>
+ <string name="mediasize_iso_b3" msgid="2612510181259261379">"ISO B3"</string>
+ <string name="mediasize_iso_b4" msgid="695151378838115434">"ISO B4"</string>
+ <string name="mediasize_iso_b5" msgid="4863754285582212487">"ISO B5"</string>
+ <string name="mediasize_iso_b6" msgid="5305816292139647241">"ISO B6"</string>
+ <string name="mediasize_iso_b7" msgid="531673542602786624">"ISO B7"</string>
+ <string name="mediasize_iso_b8" msgid="9164474595708850034">"ISO B8"</string>
+ <string name="mediasize_iso_b9" msgid="282102976764774160">"ISO B9"</string>
+ <string name="mediasize_iso_b10" msgid="4517141714407898976">"ISO B10"</string>
+ <string name="mediasize_iso_c0" msgid="3103521357901591100">"ISO C0"</string>
+ <string name="mediasize_iso_c1" msgid="1231954105985048595">"ISO C1"</string>
+ <string name="mediasize_iso_c2" msgid="927702816980087462">"ISO C2"</string>
+ <string name="mediasize_iso_c3" msgid="835154173518304159">"ISO C3"</string>
+ <string name="mediasize_iso_c4" msgid="5095951985108194011">"ISO C4"</string>
+ <string name="mediasize_iso_c5" msgid="1985397450332305739">"ISO C5"</string>
+ <string name="mediasize_iso_c6" msgid="8147421924174693013">"ISO C6"</string>
+ <string name="mediasize_iso_c7" msgid="8993994925276122950">"ISO C7"</string>
+ <string name="mediasize_iso_c8" msgid="6871178104139598957">"ISO C8"</string>
+ <string name="mediasize_iso_c9" msgid="7983532635227561362">"ISO C9"</string>
+ <string name="mediasize_iso_c10" msgid="5040764293406765584">"ISO C10"</string>
+ <string name="mediasize_na_letter" msgid="2841414839888344296">"ଲେଟର୍"</string>
+ <string name="mediasize_na_gvrnmt_letter" msgid="5295836838862962809">"ସରକାରୀ ଲେଟର୍"</string>
+ <string name="mediasize_na_legal" msgid="8621364037680465666">"ଲିଗାଲ"</string>
+ <string name="mediasize_na_junior_legal" msgid="3309324162155085904">"ଜୁନିଅର୍ ଲିଗାଲ୍"</string>
+ <string name="mediasize_na_ledger" msgid="5567030340509075333">"ଲେଜର୍"</string>
+ <string name="mediasize_na_tabloid" msgid="4571735038501661757">"ଟାବଲୋଏଡ୍"</string>
+ <string name="mediasize_na_index_3x5" msgid="5182901917818625126">"ଇଣ୍ଡେକ୍ସ କାର୍ଡ 3x5"</string>
+ <string name="mediasize_na_index_4x6" msgid="7687620625422312396">"ଇଣ୍ଡେକ୍ସ କାର୍ଡ 4x6"</string>
+ <string name="mediasize_na_index_5x8" msgid="8834215284646872800">"ଇଣ୍ଡେକ୍ସ କାର୍ଡ 5x8"</string>
+ <string name="mediasize_na_monarch" msgid="213639906956550754">"ମୋନାର୍କ"</string>
+ <string name="mediasize_na_quarto" msgid="835778493593023223">"କ୍ୱାର୍ଟୋ"</string>
+ <string name="mediasize_na_foolscap" msgid="1573911237983677138">"Foolscap"</string>
+ <string name="mediasize_chinese_roc_8k" msgid="3626855847189438896">"ROC 8K"</string>
+ <string name="mediasize_chinese_roc_16k" msgid="9182191577022943355">"ROC 16K"</string>
+ <string name="mediasize_chinese_prc_1" msgid="4793232644980170500">"PRC 1"</string>
+ <string name="mediasize_chinese_prc_2" msgid="5404109730975720670">"PRC 2"</string>
+ <string name="mediasize_chinese_prc_3" msgid="1335092253339363526">"PRC 3"</string>
+ <string name="mediasize_chinese_prc_4" msgid="9167997800486569834">"PRC 4"</string>
+ <string name="mediasize_chinese_prc_5" msgid="845875168823541497">"PRC 5"</string>
+ <string name="mediasize_chinese_prc_6" msgid="3220325667692648789">"PRC 6"</string>
+ <string name="mediasize_chinese_prc_7" msgid="1776792138507038527">"PRC 7"</string>
+ <string name="mediasize_chinese_prc_8" msgid="1417176642687456692">"PRC 8"</string>
+ <string name="mediasize_chinese_prc_9" msgid="4785983473123798365">"PRC 9"</string>
+ <string name="mediasize_chinese_prc_10" msgid="7847982299391851899">"PRC 10"</string>
+ <string name="mediasize_chinese_prc_16k" msgid="262793383539980677">"PRC 16K"</string>
+ <string name="mediasize_chinese_om_pa_kai" msgid="5256815579447959814">"Pa Kai"</string>
+ <string name="mediasize_chinese_om_dai_pa_kai" msgid="7336412963441354407">"Dai Pa Kai"</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai" msgid="6324465444100490742">"Jurro Ku Kai"</string>
+ <string name="mediasize_japanese_jis_b10" msgid="1787262845627694376">"JIS B10"</string>
+ <string name="mediasize_japanese_jis_b9" msgid="3336035783663287470">"JIS B9"</string>
+ <string name="mediasize_japanese_jis_b8" msgid="6195398299104345731">"JIS B8"</string>
+ <string name="mediasize_japanese_jis_b7" msgid="1674621886902828884">"JIS B7"</string>
+ <string name="mediasize_japanese_jis_b6" msgid="4170576286062657435">"JIS B6"</string>
+ <string name="mediasize_japanese_jis_b5" msgid="4899297958100032533">"JIS B5"</string>
+ <string name="mediasize_japanese_jis_b4" msgid="4213158129126666847">"JIS B4"</string>
+ <string name="mediasize_japanese_jis_b3" msgid="8513715307410310696">"JIS B3"</string>
+ <string name="mediasize_japanese_jis_b2" msgid="4777690211897131190">"JIS B2"</string>
+ <string name="mediasize_japanese_jis_b1" msgid="4608142385457034603">"JIS B1"</string>
+ <string name="mediasize_japanese_jis_b0" msgid="7587108366572243991">"JIS B0"</string>
+ <string name="mediasize_japanese_jis_exec" msgid="5244075432263649068">"JIS Exec"</string>
+ <string name="mediasize_japanese_chou4" msgid="4941652015032631361">"Chou4"</string>
+ <string name="mediasize_japanese_chou3" msgid="6387319169263957010">"Chou3"</string>
+ <string name="mediasize_japanese_chou2" msgid="1299112025415343982">"Chou2"</string>
+ <string name="mediasize_japanese_hagaki" msgid="8070115620644254565">"Hagaki"</string>
+ <string name="mediasize_japanese_oufuku" msgid="6049065587307896564">"Oufuku"</string>
+ <string name="mediasize_japanese_kahu" msgid="6872696027560065173">"Kahu"</string>
+ <string name="mediasize_japanese_kaku2" msgid="2359077233775455405">"Kaku2"</string>
+ <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string>
+ <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"ଅଜଣା ପୋର୍ଟ୍ରେଟ୍"</string>
+ <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"ଅଜଣା ଲ୍ୟାଣ୍ଡସ୍କେପ୍"</string>
+ <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"କ୍ୟାନ୍ସଲ୍ କରାଗଲା"</string>
+ <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"କଣ୍ଟେଣ୍ଟ ଲେଖିବାବେଳେ ତ୍ରୁଟି"</string>
+ <string name="reason_unknown" msgid="6048913880184628119">"ଅଜଣା"</string>
+ <string name="reason_service_unavailable" msgid="7824008732243903268">"ପ୍ରିଣ୍ଟ ସେବାକୁ ସକ୍ଷମ କରାଯାଇନାହିଁ"</string>
+ <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> ସେବା ଇନଷ୍ଟଲ୍ କରାଯାଇସାରିଛି"</string>
+ <string name="print_service_installed_message" msgid="5897362931070459152">"ସକ୍ଷମ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for restr_pin_enter_admin_pin (8641662909467236832) -->
+ <skip />
+ <string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN ଲେଖନ୍ତୁ"</string>
+ <string name="restr_pin_incorrect" msgid="8571512003955077924">"ଭୁଲ"</string>
+ <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"ବର୍ତ୍ତମାନର PIN"</string>
+ <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"ନୂଆ PIN"</string>
+ <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"ନୂଆ PIN ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="restr_pin_create_pin" msgid="8017600000263450337">"ପ୍ରତିବନ୍ଧକ ବଦଳାଇବା ପାଇଁ ଏକ PIN ତିଆରି କରନ୍ତୁ"</string>
+ <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINଗୁଡିକ ମେଳ ହେଉନାହିଁ। ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ବହୁତ ଛୋଟ। ଅତି କମ୍ରେ 4 ସଂଖ୍ୟା ବିଶିଷ୍ଟ ହେବା ଦରକାର।"</string>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ</item>
+ <item quantity="one">1 ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ</item>
+ </plurals>
+ <string name="restr_pin_try_later" msgid="973144472490532377">"ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+ <string name="immersive_cling_title" msgid="8394201622932303336">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ଦେଖାଯାଉଛି"</string>
+ <string name="immersive_cling_description" msgid="3482371193207536040">"ବାହାରିବା ପାଇଁ, ଉପରୁ ତଳକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="immersive_cling_positive" msgid="5016839404568297683">"ବୁଝିଲି"</string>
+ <string name="done_label" msgid="2093726099505892398">"ହୋଇଗଲା"</string>
+ <string name="hour_picker_description" msgid="6698199186859736512">"ଘଣ୍ଟା ସର୍କୁଲାର୍ ସ୍ଲାଇଡର୍"</string>
+ <string name="minute_picker_description" msgid="8606010966873791190">"ମିନିଟ୍ସ ସର୍କୁଲାର୍ ସ୍ଲାଇଡର୍"</string>
+ <string name="select_hours" msgid="6043079511766008245">"ଘଣ୍ଟା ଚୟନ କରନ୍ତୁ"</string>
+ <string name="select_minutes" msgid="3974345615920336087">"ମିନିଟ୍ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="select_day" msgid="7774759604701773332">"ମାସ ଓ ଦିନ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="select_year" msgid="7952052866994196170">"ବର୍ଷ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ଡିଲିଟ୍ ହୋଇଗଲା"</string>
+ <string name="managed_profile_label_badge" msgid="2355652472854327647">"କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ PIN ପଚାରନ୍ତୁ"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ ଲକ୍ ଖୋଲିବା ପାଟର୍ନ ପଚାରନ୍ତୁ"</string>
+ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ ପାସ୍ୱର୍ଡ ପଚାରନ୍ତୁ"</string>
+ <!-- no translation found for package_installed_device_owner (6875717669960212648) -->
+ <skip />
+ <!-- no translation found for package_updated_device_owner (1847154566357862089) -->
+ <skip />
+ <!-- no translation found for package_deleted_device_owner (2307122077550236438) -->
+ <skip />
+ <!-- no translation found for battery_saver_description (5394663545060026162) -->
+ <skip />
+ <!-- no translation found for data_saver_description (6015391409098303235) -->
+ <skip />
+ <string name="data_saver_enable_title" msgid="4674073932722787417">"ଡାଟା ସେଭର୍ ଅନ୍ କରିବେ?"</string>
+ <string name="data_saver_enable_button" msgid="7147735965247211818">"ଅନ୍ କରନ୍ତୁ"</string>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d ମିନିଟ୍ ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ <item quantity="one">ଏକ ମିନିଟ୍ ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="6830154222366042597">
+ <item quantity="other">%1$d ମିନିଟ୍ ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ <item quantity="one">1 ମିନିଟ୍ ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ <item quantity="one">ଏକ ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
+ <item quantity="other">%1$d ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ <item quantity="one">1 ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d ମିନିଟ୍ ପାଇଁ</item>
+ <item quantity="one">ଏକ ମିନିଟ୍ ପାଇଁ</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2199350154433426128">
+ <item quantity="other">%d ମିନିଟ୍ ପାଇଁ</item>
+ <item quantity="one">1 ମିନିଟ୍ ପାଇଁ</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d ଘଣ୍ଟା ପାଇଁ</item>
+ <item quantity="one">ଏକ ଘଣ୍ଟା ପାଇଁ</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
+ <item quantity="other">%d ଘଣ୍ଟା ପାଇଁ</item>
+ <item quantity="one">1 ଘଣ୍ଟା ପାଇଁ</item>
+ </plurals>
+ <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ପରବର୍ତ୍ତୀ ଆଲାର୍ମ) ପର୍ଯ୍ୟନ୍ତ"</string>
+ <!-- no translation found for zen_mode_forever (931849471004038757) -->
+ <skip />
+ <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ଆପଣ \"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅଫ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ"</string>
+ <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
+ <string name="toolbar_collapse_description" msgid="2821479483960330739">"ଛୋଟ କରନ୍ତୁ"</string>
+ <string name="zen_mode_feature_name" msgid="5254089399895895004">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
+ <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"ବନ୍ଦ ରହିବାର ସମୟ"</string>
+ <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"ସପ୍ତାହରାତି"</string>
+ <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"ସପ୍ତାହାନ୍ତ"</string>
+ <string name="zen_mode_default_events_name" msgid="8158334939013085363">"ଇଭେଣ୍ଟ"</string>
+ <!-- no translation found for zen_mode_default_every_night_name (3012363838882944175) -->
+ <skip />
+ <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ଦ୍ୱାରା ନିଶବ୍ଦ କରନ୍ତୁ"</string>
+ <string name="system_error_wipe_data" msgid="6608165524785354962">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଏକ ସମସ୍ୟା ରହିଛି ଏବଂ ଆପଣ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଅସ୍ଥିର ରହିପାରେ।"</string>
+ <string name="system_error_manufacturer" msgid="8086872414744210668">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଏକ ସମସ୍ୟା ରହିଛି। ବିବରଣୀ ପାଇଁ ଆପଣଙ୍କ ଉତ୍ପାଦକଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD ଅନୁରୋଧ DIAL ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD ଅନୁରୋଧ SS ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD ଅନୁରୋଧ ନୂଆ USSD ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <!-- no translation found for stk_cc_ussd_to_dial_video (585340552561515305) -->
+ <skip />
+ <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS ଅନୁରୋଧ DIAL ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <!-- no translation found for stk_cc_ss_to_dial_video (4306210904450719045) -->
+ <skip />
+ <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS ଅନୁରୋଧ USSD ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS ଅନୁରୋଧ ନୂତନ SS ଅନୁରୋଧକୁ ସଂଶୋଧନ କରାଗଲା।"</string>
+ <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
+ <!-- no translation found for expand_button_content_description_collapsed (3609784019345534652) -->
+ <skip />
+ <!-- no translation found for expand_button_content_description_expanded (8520652707158554895) -->
+ <skip />
+ <string name="expand_action_accessibility" msgid="5307730695723718254">"ଟୋଗଲ୍ ସମ୍ପ୍ରସାରଣ"</string>
+ <string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Android USB ପେରିଫେରିଆଲ୍ ପୋର୍ଟ"</string>
+ <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+ <string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"USB ପେରିଫେରିଆଲ୍ ପୋର୍ଟ"</string>
+ <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"ଅଧିକ ବିକଳ୍ପ"</string>
+ <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"ଓଭରଫ୍ଲୋ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="maximize_button_text" msgid="7543285286182446254">"ବଡ଼ କରନ୍ତୁ"</string>
+ <string name="close_button_text" msgid="3937902162644062866">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
+ <plurals name="selected_count" formatted="false" msgid="7187339492915744615">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ଚୟନିତ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ଚୟନିତ</item>
+ </plurals>
+ <!-- no translation found for default_notification_channel_label (5929663562028088222) -->
+ <skip />
+ <!-- no translation found for importance_from_user (7318955817386549931) -->
+ <skip />
+ <string name="importance_from_person" msgid="9160133597262938296">"ସମ୍ପୃକ୍ତ ଲୋକଙ୍କ କାରଣରୁ ଏହା ଗୁରୁତ୍ୱପୂର୍ଣ୍ଣ ଅଟେ।"</string>
+ <!-- no translation found for user_creation_account_exists (1942606193570143289) -->
+ <skip />
+ <!-- no translation found for user_creation_adding (4482658054622099197) -->
+ <skip />
+ <!-- no translation found for language_selection_title (2680677278159281088) -->
+ <skip />
+ <string name="country_selection_title" msgid="2954859441620215513">"ପସନ୍ଦର ଅଞ୍ଚଳ"</string>
+ <string name="search_language_hint" msgid="7042102592055108574">"ଭାଷାର ନାମ ଟାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="language_picker_section_suggested" msgid="8414489646861640885">"ପରାମର୍ଶିତ"</string>
+ <string name="language_picker_section_all" msgid="3097279199511617537">"ସମସ୍ତ ଭାଷା"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ସମସ୍ତ ଅଞ୍ଚଳ"</string>
+ <string name="locale_search_menu" msgid="2560710726687249178">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <!-- no translation found for work_mode_off_title (1118691887588435530) -->
+ <skip />
+ <!-- no translation found for work_mode_off_message (5130856710614337649) -->
+ <skip />
+ <string name="work_mode_turn_on" msgid="2062544985670564875">"ଅନ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for deprecated_target_sdk_message (1449696506742572767) -->
+ <skip />
+ <!-- no translation found for deprecated_target_sdk_app_store (5032340500368495077) -->
+ <skip />
+ <string name="new_sms_notification_title" msgid="8442817549127555977">"ଆପଣଙ୍କ ପାଖରେ ନୂଆ ମେସେଜ୍ ରହିଛି"</string>
+ <string name="new_sms_notification_content" msgid="7002938807812083463">"ଦେଖିବା ପାଇଁ SMS ଆପ୍ ଖୋଲନ୍ତୁ"</string>
+ <!-- no translation found for user_encrypted_title (9054897468831672082) -->
+ <skip />
+ <!-- no translation found for user_encrypted_message (4923292604515744267) -->
+ <skip />
+ <!-- no translation found for user_encrypted_detail (5708447464349420392) -->
+ <skip />
+ <!-- no translation found for profile_encrypted_detail (3700965619978314974) -->
+ <skip />
+ <!-- no translation found for profile_encrypted_message (6964994232310195874) -->
+ <skip />
+ <!-- no translation found for usb_mtp_launch_notification_title (8359219638312208932) -->
+ <skip />
+ <!-- no translation found for usb_mtp_launch_notification_description (8541876176425411358) -->
+ <skip />
+ <string name="pin_target" msgid="3052256031352291362">"ପିନ୍"</string>
+ <!-- no translation found for unpin_target (3556545602439143442) -->
+ <skip />
+ <string name="app_info" msgid="6856026610594615344">"ଆପ୍ ସୂଚନା"</string>
+ <!-- no translation found for negative_duration (5688706061127375131) -->
+ <skip />
+ <string name="demo_starting_message" msgid="5268556852031489931">"ଡେମୋ ଆରମ୍ଭ କରାଯାଉଛି…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"ଡିଭାଇସ୍କୁ ରିସେଟ୍ କରାଯାଉଛି…"</string>
+ <string name="suspended_widget_accessibility" msgid="6712143096475264190">"ଅକ୍ଷମ ହୋଇଛି <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="conference_call" msgid="3751093130790472426">"କନ୍ଫରେନ୍ସ କଲ୍"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ଟୁଲଟିପ୍"</string>
+ <!-- no translation found for app_category_game (5431836943981492993) -->
+ <skip />
+ <!-- no translation found for app_category_audio (1659853108734301647) -->
+ <skip />
+ <!-- no translation found for app_category_video (2728726078629384196) -->
+ <skip />
+ <!-- no translation found for app_category_image (4867854544519846048) -->
+ <skip />
+ <!-- no translation found for app_category_social (5842783057834965912) -->
+ <skip />
+ <!-- no translation found for app_category_news (7496506240743986873) -->
+ <skip />
+ <!-- no translation found for app_category_maps (5878491404538024367) -->
+ <skip />
+ <!-- no translation found for app_category_productivity (3742083261781538852) -->
+ <skip />
+ <!-- no translation found for device_storage_monitor_notification_channel (3295871267414816228) -->
+ <skip />
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
+ <!-- no translation found for time_picker_hour_label (2979075098868106450) -->
+ <skip />
+ <!-- no translation found for time_picker_minute_label (5168864173796598399) -->
+ <skip />
+ <!-- no translation found for time_picker_header_text (143536825321922567) -->
+ <skip />
+ <!-- no translation found for time_picker_input_error (7574999942502513765) -->
+ <skip />
+ <!-- no translation found for time_picker_prompt_label (7588093983899966783) -->
+ <skip />
+ <!-- no translation found for time_picker_text_input_mode_description (4148166758173708199) -->
+ <skip />
+ <!-- no translation found for time_picker_radial_mode_description (4953403779779557198) -->
+ <skip />
+ <!-- no translation found for autofill_picker_accessibility_title (8469043291648711535) -->
+ <skip />
+ <!-- no translation found for autofill_save_accessibility_title (7244365268417107822) -->
+ <skip />
+ <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
+ <skip />
+ <!-- no translation found for autofill_picker_no_suggestions (3908514303773350735) -->
+ <skip />
+ <!-- no translation found for autofill_picker_some_suggestions (5506565809835815274) -->
+ <!-- no translation found for autofill_save_title (3345527308992082601) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_type (8637809388029313305) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_2types (5214035651838265325) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_3types (6943161834231458441) -->
+ <skip />
+ <!-- no translation found for autofill_save_yes (6398026094049005921) -->
+ <skip />
+ <!-- no translation found for autofill_save_no (2625132258725581787) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_password (5288448918465971568) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_address (4936707762193009542) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_credit_card (7127694776265563071) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_username (239040540379769562) -->
+ <skip />
+ <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
+ <skip />
+ <!-- no translation found for etws_primary_default_message_earthquake (5541962250262769193) -->
+ <skip />
+ <!-- no translation found for etws_primary_default_message_tsunami (1887685943498368548) -->
+ <skip />
+ <!-- no translation found for etws_primary_default_message_earthquake_and_tsunami (998797956848445862) -->
+ <skip />
+ <!-- no translation found for etws_primary_default_message_test (2709597093560037455) -->
+ <skip />
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
+ <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
+ <!-- no translation found for mmcc_authentication_reject (5767701075994754356) -->
+ <skip />
+ <!-- no translation found for mmcc_imsi_unknown_in_hlr (5316658473301462825) -->
+ <skip />
+ <!-- no translation found for mmcc_illegal_ms (807334478177362062) -->
+ <skip />
+ <!-- no translation found for mmcc_illegal_me (1950705155760872972) -->
+ <skip />
+ <!-- no translation found for popup_window_default_title (4874318849712115433) -->
+ <skip />
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
+ <!-- no translation found for shortcut_restored_on_lower_version (4860853725206702336) -->
+ <skip />
+ <!-- no translation found for shortcut_restore_not_supported (5028808567940014190) -->
+ <skip />
+ <!-- no translation found for shortcut_restore_signature_mismatch (2406209324521327518) -->
+ <skip />
+ <!-- no translation found for shortcut_restore_unknown_issue (8703738064603262597) -->
+ <skip />
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
+ <skip />
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
+ <skip />
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
+ <skip />
+ <!-- no translation found for slices_permission_request (8484943441501672932) -->
+ <skip />
+ <!-- no translation found for screenshot_edit (7867478911006447565) -->
+ <skip />
+ <!-- no translation found for notification_channel_system_changes (5072715579030948646) -->
+ <skip />
+ <!-- no translation found for zen_upgrade_notification_title (3799603322910377294) -->
+ <skip />
+ <!-- no translation found for zen_upgrade_notification_content (6603123479476554768) -->
+ <skip />
+</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 45512a5..5ab8d33 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -181,7 +181,7 @@
<string name="network_logging_notification_title" msgid="6399790108123704477">"O dispositivo é gerenciado"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Sua organização gerencia este dispositivo e pode monitorar o tráfego de rede. Toque para ver detalhes."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Seu dispositivo será limpo"</string>
- <string name="factory_reset_message" msgid="7972496262232832457">"Não é possível usar o app para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
+ <string name="factory_reset_message" msgid="9024647691106150160">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
<string name="printing_disabled_by" msgid="8936832919072486965">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opções do tablet"</string>
@@ -236,6 +236,9 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avião"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avião ATIVADO"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avião DESATIVADO"</string>
+ <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Economia de bateria"</string>
+ <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"A Economia de bateria está DESATIVADA"</string>
+ <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"A Economia de bateria está ATIVADA"</string>
<string name="global_action_settings" msgid="1756531602592545966">"Configurações"</string>
<string name="global_action_assist" msgid="3892832961594295030">"Assistência"</string>
<string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
@@ -305,7 +308,7 @@
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
- <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
@@ -356,6 +359,8 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que o app torne partes de si mesmo persistentes na memória. Pode limitar a memória disponível para outros apps, deixando o tablet mais lento."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que o app torne partes de si mesmo persistentes na memória. Isso pode limitar a memória disponível para outros apps, deixando a TV mais lenta."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Permite que o app torne partes de si mesmo persistentes na memória. Pode limitar a memória disponível para outros apps, deixando o telefone mais lento."</string>
+ <string name="permlab_foregroundService" msgid="3310786367649133115">"executar serviço em primeiro plano"</string>
+ <string name="permdesc_foregroundService" msgid="6471634326171344622">"Permite que o app use serviços em primeiro plano."</string>
<string name="permlab_getPackageSize" msgid="7472921768357981986">"medir o espaço de armazenamento do app"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Permite que o app recupere o código, os dados e os tamanhos de cache"</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"modificar configurações do sistema"</string>
@@ -802,6 +807,8 @@
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueio facial."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
+ <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Desbloqueio com PIN do SIM."</string>
+ <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Desbloqueio com PUK do SIM."</string>
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
<string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
<string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
@@ -1074,29 +1081,33 @@
<string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Verificar atualizações"</string>
<string name="smv_application" msgid="3307209192155442829">"O app <xliff:g id="APPLICATION">%1$s</xliff:g>, processo <xliff:g id="PROCESS">%2$s</xliff:g>, violou a política StrictMode imposta automaticamente."</string>
<string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode imposta automaticamente."</string>
- <string name="android_upgrading_title" msgid="1584192285441405746">"O Android está sendo atualizado..."</string>
- <string name="android_start_title" msgid="8418054686415318207">"O Android está iniciando..."</string>
+ <!-- no translation found for android_upgrading_title (7513829952443484438) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (4503169817302593560) -->
+ <skip />
+ <!-- no translation found for android_upgrading_title (7009520271220804517) -->
+ <skip />
+ <!-- no translation found for android_start_title (4536778526365907780) -->
+ <skip />
+ <!-- no translation found for android_start_title (4929837533850340472) -->
+ <skip />
+ <!-- no translation found for android_start_title (7467484093260449437) -->
+ <skip />
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
- <string name="android_upgrading_notification_title" msgid="8428357096969413169">"Concluindo atualização do Android…"</string>
- <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alguns apps podem não funcionar corretamente até que a atualização seja concluída"</string>
+ <!-- no translation found for android_upgrading_notification_title (1511552415039349062) -->
+ <skip />
<string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> está fazendo upgrade…"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
<string name="android_upgrading_complete" msgid="1405954754112999229">"Concluindo a inicialização."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
- <!-- no translation found for heavy_weight_notification_detail (2304833848484424985) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_title (387882830435195342) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_text (4176781660362912010) -->
- <skip />
- <!-- no translation found for old_app_action (3044685170829526403) -->
- <skip />
- <!-- no translation found for new_app_action (6694851182870774403) -->
- <skip />
- <!-- no translation found for new_app_description (5894852887817332322) -->
- <skip />
+ <string name="heavy_weight_notification_detail" msgid="2304833848484424985">"Toque para voltar ao jogo"</string>
+ <string name="heavy_weight_switcher_title" msgid="387882830435195342">"Escolha o jogo"</string>
+ <string name="heavy_weight_switcher_text" msgid="4176781660362912010">"Para ter um melhor desempenho, apenas um desses jogos pode ser aberto por vez."</string>
+ <string name="old_app_action" msgid="3044685170829526403">"Voltar para o app <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="new_app_action" msgid="6694851182870774403">"Abrir <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
+ <string name="new_app_description" msgid="5894852887817332322">"O app <xliff:g id="OLD_APP">%1$s</xliff:g> será fechado sem salvar"</string>
<string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> excedeu o limite de memória"</string>
<string name="dump_heap_notification_detail" msgid="6901391084243999274">"O despejo de heap foi coletado. Toque para compartilhar"</string>
<string name="dump_heap_title" msgid="5864292264307651673">"Compartilhar despejo de heap?"</string>
@@ -1138,7 +1149,8 @@
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível conectar-se à rede Wi‑Fi"</string>
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
- <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
+ <!-- no translation found for wifi_available_action_all_networks (4368435796357931006) -->
+ <skip />
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando você estiver perto de uma rede salva de alta qualidade"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não ativar novamente"</string>
@@ -1204,6 +1216,7 @@
<string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
<string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Ativar serviço móvel"</string>
<string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Faça o download do app da operadora para ativar seu novo SIM"</string>
+ <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo SIM"</string>
<string name="install_carrier_app_notification_button" msgid="3094206295081900849">"Fazer download do app"</string>
<string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
<string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
@@ -1247,7 +1260,7 @@
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se você não deseja que o <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
- <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
+ <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Desativar"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Procurando erros"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detectado"</string>
@@ -1418,22 +1431,19 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
- <string name="data_usage_warning_title" msgid="3620440638180218181">"Alerta de uso de dados"</string>
- <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver uso e config."</string>
- <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de dados 2G-3G atingido"</string>
- <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de dados 4G atingido"</string>
+ <string name="data_usage_warning_title" msgid="6499834033204801605">"Aviso de dados"</string>
+ <string name="data_usage_warning_body" msgid="7340198905103751676">"Você usou <xliff:g id="APP">%s</xliff:g> de dados"</string>
<string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Limite de dados móveis atingido"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Limite de dados Wi-Fi atingido"</string>
- <string name="data_usage_limit_body" msgid="291731708279614081">"Dados pausados no resto do ciclo"</string>
- <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Limite de dados 2G-3G excedido"</string>
- <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Limite de dados 4G excedido"</string>
- <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Limite de dados do celular excedido"</string>
- <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Limite de dados Wi-Fi excedido"</string>
- <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> acima do limite especificado."</string>
+ <string name="data_usage_limit_body" msgid="2908179506560812973">"Uso de dados pausado pelo restante do seu ciclo"</string>
+ <string name="data_usage_mobile_limit_snoozed_title" msgid="3171402244827034372">"Acima do limite de dados móveis"</string>
+ <string name="data_usage_wifi_limit_snoozed_title" msgid="3547771791046344188">"Acima do limite de dados Wi-Fi"</string>
+ <string name="data_usage_limit_snoozed_body" msgid="1671222777207603301">"Você ultrapassou <xliff:g id="SIZE">%s</xliff:g> do limite definido"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dados de segundo plano restritos"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Toque para remover a restrição."</string>
- <string name="data_usage_rapid_title" msgid="4579994056245665351">"Uso de dados excessivo"</string>
- <string name="data_usage_rapid_body" msgid="4899922842674185567">"Seu uso de dados nos últimos dias é maior que o normal. Toque para ver o uso e as configurações."</string>
+ <string name="data_usage_rapid_title" msgid="1809795402975261331">"Alto uso de dados móveis"</string>
+ <string name="data_usage_rapid_body" msgid="6897825788682442715">"Seus apps usaram mais dados do que o normal"</string>
+ <string name="data_usage_rapid_app_body" msgid="5396680996784142544">"O app <xliff:g id="APP">%s</xliff:g> usou mais dados do que o normal"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificado de segurança"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado é válido."</string>
<string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 796030e..021e88e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1114,6 +1114,9 @@
<!-- The color applied to framework switch thumbs in their normal state. -->
<attr name="colorSwitchThumbNormal" format="color" />
+ <!-- The color applied to framework progress and seek bar backgrounds in their normal state. -->
+ <attr name="colorProgressBackgroundNormal" format="color" />
+
<!-- The color applied to the edge effect on scrolling containers. -->
<attr name="colorEdgeEffect" format="color" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 979a0d6..fa0fb94 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2457,6 +2457,7 @@
<java-symbol type="bool" name="config_defaultWindowFeatureOptionsPanel" />
<java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" />
<java-symbol type="bool" name="config_overrideRemoteViewsActivityTransition" />
+ <java-symbol type="attr" name="colorProgressBackgroundNormal" />
<java-symbol type="layout" name="simple_account_item" />
<java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index cb11d8d..fdbcd8a 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -127,6 +127,7 @@
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.RatingBar.Indicator</item>
@@ -230,6 +231,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -253,6 +255,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -278,6 +281,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -302,6 +306,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -334,6 +339,7 @@
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -357,6 +363,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -379,6 +386,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -402,6 +410,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -441,6 +450,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -465,6 +475,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -487,6 +498,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -511,6 +523,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -534,6 +547,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -557,6 +571,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -580,6 +595,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -603,6 +619,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -626,6 +643,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -647,6 +665,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -668,6 +687,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -748,6 +768,7 @@
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.Light.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.Light.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
@@ -846,6 +867,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -868,6 +890,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -891,6 +914,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -916,6 +940,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -940,6 +965,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -970,6 +996,7 @@
<item name="colorAccent">@color/accent_device_default_light</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -993,6 +1020,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1015,6 +1043,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1038,6 +1067,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1087,6 +1117,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1111,6 +1142,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1133,6 +1165,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1157,6 +1190,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1180,6 +1214,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1201,6 +1236,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1222,6 +1258,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1256,6 +1293,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1278,6 +1316,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1290,6 +1329,7 @@
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1313,6 +1353,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1335,6 +1376,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1357,6 +1399,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1379,6 +1422,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
@@ -1408,6 +1452,7 @@
<item name="colorAccent">@color/accent_device_default_light</item>
<!-- Progress bar attributes -->
+ <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
</style>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 76d9ea6..9b633fc 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -403,6 +403,7 @@
<item name="colorControlHighlight">@color/ripple_material_dark</item>
<item name="colorButtonNormal">@color/btn_default_material_dark</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
+ <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
<!-- Tooltip popup properties -->
<item name="tooltipForegroundColor">@color/foreground_material_light</item>
@@ -777,6 +778,7 @@
<item name="colorControlHighlight">@color/ripple_material_light</item>
<item name="colorButtonNormal">@color/btn_default_material_light</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+ <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
<!-- Tooltip popup properties -->
<item name="tooltipForegroundColor">@color/foreground_material_dark</item>
@@ -837,6 +839,7 @@
<item name="colorControlHighlight">@color/ripple_material_light</item>
<item name="colorButtonNormal">@color/btn_default_material_light</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+ <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
</style>
<!-- Theme overlay that replaces colors with their dark versions but preserves
@@ -870,6 +873,7 @@
<item name="colorControlHighlight">@color/ripple_material_dark</item>
<item name="colorButtonNormal">@color/btn_default_material_dark</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
+ <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
</style>
<!-- Theme overlay that replaces the normal control color, which by default is the same as the
diff --git a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
index b28a4b5..781e343 100644
--- a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
@@ -1,15 +1,11 @@
package android.graphics.drawable;
-import static org.junit.Assert.assertTrue;
-
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
-import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Rect;
@@ -19,10 +15,12 @@
import android.test.AndroidTestCase;
import android.util.Log;
import android.util.PathParser;
+
+import org.junit.Test;
+
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
-import org.junit.Test;
@LargeTest
public class AdaptiveIconDrawableTest extends AndroidTestCase {
@@ -173,6 +171,28 @@
assertTrue("outline path should be convex", outline.mPath.isConvex());
}
+ @Test
+ public void testSetAlpha() throws Exception {
+ mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+ mIconDrawable.setBounds(0, 0, 100, 100);
+
+ Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+
+ mIconDrawable.draw(canvas);
+ assertEquals(255, Color.alpha(bitmap.getPixel(50, 50)));
+
+ mIconDrawable.setAlpha(200);
+ bitmap.eraseColor(Color.TRANSPARENT);
+ mIconDrawable.draw(canvas);
+ assertEquals(200, Color.alpha(bitmap.getPixel(50, 50)));
+
+ mIconDrawable.setAlpha(100);
+ bitmap.eraseColor(Color.TRANSPARENT);
+ mIconDrawable.draw(canvas);
+ assertEquals(100, Color.alpha(bitmap.getPixel(50, 50)));
+ }
+
//
// Utils
//
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index b135025..8db1bfa 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -16,8 +16,13 @@
package android.view.accessibility;
+import static org.hamcrest.Matchers.emptyCollectionOf;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import android.os.Parcel;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.ArraySet;
@@ -38,10 +43,10 @@
public void testStandardActions_serializationFlagIsValid() {
AccessibilityAction brokenStandardAction = CollectionUtils.find(
new ArrayList<>(AccessibilityAction.sStandardActions),
- action -> Integer.bitCount(action.mSerializationFlag) != 1);
+ action -> Long.bitCount(action.mSerializationFlag) != 1);
if (brokenStandardAction != null) {
String message = "Invalid serialization flag(0x"
- + Integer.toHexString(brokenStandardAction.mSerializationFlag)
+ + Long.toHexString(brokenStandardAction.mSerializationFlag)
+ ") in " + brokenStandardAction;
if (brokenStandardAction.mSerializationFlag == 0L) {
message += "\nThis is likely due to an overflow";
@@ -56,7 +61,7 @@
&& action.getId() != action.mSerializationFlag);
if (brokenStandardAction != null) {
fail("Serialization flag(0x"
- + Integer.toHexString(brokenStandardAction.mSerializationFlag)
+ + Long.toHexString(brokenStandardAction.mSerializationFlag)
+ ") is different from legacy action id(0x"
+ Integer.toHexString(brokenStandardAction.getId())
+ ") in " + brokenStandardAction);
@@ -77,4 +82,36 @@
}
}
+ @Test
+ public void testStandardActions_allComeThroughParceling() {
+ for (AccessibilityAction action : AccessibilityAction.sStandardActions) {
+ final AccessibilityNodeInfo nodeWithAction = AccessibilityNodeInfo.obtain();
+ nodeWithAction.addAction(action);
+ assertThat(nodeWithAction.getActionList(), hasItem(action));
+ final Parcel parcel = Parcel.obtain();
+ nodeWithAction.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ final AccessibilityNodeInfo unparceledNode =
+ AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
+ assertThat(unparceledNode.getActionList(), hasItem(action));
+ }
+ }
+
+ @Test
+ public void testEmptyListOfActions_parcelsCorrectly() {
+ // Also set text, as if there's nothing else in the parcel it can unparcel even with
+ // a bug present.
+ final String text = "text";
+ final AccessibilityNodeInfo nodeWithEmptyActionList = AccessibilityNodeInfo.obtain();
+ nodeWithEmptyActionList.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
+ nodeWithEmptyActionList.removeAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
+ nodeWithEmptyActionList.setText(text);
+ final Parcel parcel = Parcel.obtain();
+ nodeWithEmptyActionList.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ final AccessibilityNodeInfo unparceledNode =
+ AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
+ assertThat(unparceledNode.getActionList(), emptyCollectionOf(AccessibilityAction.class));
+ assertThat(unparceledNode.getText(), equalTo(text));
+ }
}
diff --git a/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java b/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
index 9fa9be9..6129b5b 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
@@ -16,12 +16,10 @@
package android.widget.layout.linear;
-import junit.framework.Assert;
-
-import android.widget.EditText;
import android.content.Context;
-import android.util.AttributeSet;
import android.text.BoringLayout;
+import android.util.AttributeSet;
+import android.widget.EditText;
/**
@@ -50,10 +48,8 @@
}
@Override
- protected void makeNewLayout(int w, int hintWidth,
- BoringLayout.Metrics boring,
- BoringLayout.Metrics hintMetrics,
- int ellipsizedWidth, boolean bringIntoView) {
+ public void makeNewLayout(int w, int hintWidth, BoringLayout.Metrics boring,
+ BoringLayout.Metrics hintMetrics, int ellipsizedWidth, boolean bringIntoView) {
if (w < 0) {
mFailed = true;
w = 100;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
index 312af16..06f51c9 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
@@ -104,6 +104,30 @@
}
@Test
+ public void testReadAbsolute() throws Exception {
+ final int cores = 8;
+ final int[] uids = {1, 22, 333, 4444, 5555};
+
+ final long[][] times = increaseTime(new long[uids.length][cores]);
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
+ mReader.readAbsolute(mCallback);
+ for (int i = 0; i < uids.length; i++) {
+ verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
+ }
+ verifyNoMoreInteractions(mCallback);
+
+ // Verify that a second call still returns absolute values
+ Mockito.reset(mCallback);
+ final long[][] times1 = increaseTime(times);
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times1));
+ mReader.readAbsolute(mCallback);
+ for (int i = 0; i < uids.length; i++) {
+ verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times1[i]));
+ }
+ verifyNoMoreInteractions(mCallback);
+ }
+
+ @Test
public void testReadDelta_malformedData() throws Exception {
final int cores = 8;
final int[] uids = {1, 22, 333, 4444, 5555};
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
index d21f541..85dce02 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
@@ -114,6 +114,34 @@
}
@Test
+ public void testReadAbsolute() throws Exception {
+ VerifiableCallback cb = new VerifiableCallback();
+ final int cores = 6;
+ final int[] clusters = {2, 4};
+ final int[] uids = {1, 22, 333, 4444, 5555};
+
+ // Verify return absolute value
+ final long[][] times = increaseTime(new long[uids.length][cores]);
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times));
+ mReader.readAbsolute(cb);
+ for (int i = 0; i < uids.length; i++) {
+ cb.verify(uids[i], getTotal(clusters, times[i]));
+ }
+ cb.verifyNoMoreInteractions();
+
+ // Verify that a second call should return the same absolute value
+ cb.clear();
+ Mockito.reset(mProcReader);
+ final long[][] times1 = increaseTime(times);
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times1));
+ mReader.readAbsolute(cb);
+ for (int i = 0; i < uids.length; i++) {
+ cb.verify(uids[i], getTotal(clusters, times1[i]));
+ }
+ cb.verifyNoMoreInteractions();
+ }
+
+ @Test
public void testReadDelta_malformedData() throws Exception {
final int cores = 6;
final int[] clusters = {2, 4};
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
index 0950721..a6b99c3 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -297,6 +297,46 @@
}
@Test
+ public void testReadAbsolute() throws Exception {
+ VerifiableCallback cb = new VerifiableCallback();
+ final long[] freqs = {110, 123, 145, 167, 289, 997};
+ final int[] uids = {1, 22, 333, 444, 555};
+ final long[][] times = new long[uids.length][freqs.length];
+ for (int i = 0; i < uids.length; ++i) {
+ for (int j = 0; j < freqs.length; ++j) {
+ times[i][j] = uids[i] * freqs[j] * 10;
+ }
+ }
+ when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs));
+ long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mBufferedReader, mPowerProfile);
+
+ assertArrayEquals(freqs, actualFreqs);
+ // Verify that the absolute values are returned
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
+ mKernelUidCpuFreqTimeReader.readAbsolute(cb);
+ for (int i = 0; i < uids.length; ++i) {
+ cb.verify(uids[i], times[i]);
+ }
+ cb.verifyNoMoreInteractions();
+
+ // Verify that a second call should still return absolute values
+ cb.clear();
+ Mockito.reset(mProcReader);
+ final long[][] newTimes1 = new long[uids.length][freqs.length];
+ for (int i = 0; i < uids.length; ++i) {
+ for (int j = 0; j < freqs.length; ++j) {
+ newTimes1[i][j] = times[i][j] + (uids[i] + freqs[j]) * 50;
+ }
+ }
+ when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes1));
+ mKernelUidCpuFreqTimeReader.readAbsolute(cb);
+ for (int i = 0; i < uids.length; ++i) {
+ cb.verify(uids[i], newTimes1[i]);
+ }
+ cb.verifyNoMoreInteractions();
+ }
+
+ @Test
public void testReadDelta_malformedData() throws Exception {
final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
final int[] uids = {1, 22, 333, 4444, 5555};
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 1d0cfa5..fdd638a 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -44,6 +44,7 @@
import android.util.PathParser;
import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -668,13 +669,7 @@
@Override
public void setAlpha(int alpha) {
- final ChildDrawable[] array = mLayerState.mChildren;
- for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
- final Drawable dr = array[i].mDrawable;
- if (dr != null) {
- dr.setAlpha(alpha);
- }
- }
+ mPaint.setAlpha(alpha);
}
@Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 2ea745c..c0f4920 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -34,6 +34,7 @@
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
+import android.view.View;
import com.android.internal.R;
@@ -389,11 +390,25 @@
public void setAutoMirrored(boolean mirrored) {
if (mState.mAutoMirrored != mirrored) {
mState.mAutoMirrored = mirrored;
- invalidateSelf();
+ if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL && mState.mNativePtr != 0) {
+ nSetMirrored(mState.mNativePtr, mirrored);
+ invalidateSelf();
+ }
}
}
@Override
+ public boolean onLayoutDirectionChanged(int layoutDirection) {
+ if (!mState.mAutoMirrored || mState.mNativePtr == 0) {
+ return false;
+ }
+
+ final boolean mirror = layoutDirection == View.LAYOUT_DIRECTION_RTL;
+ nSetMirrored(mState.mNativePtr, mirror);
+ return true;
+ }
+
+ @Override
public final boolean isAutoMirrored() {
return mState.mAutoMirrored;
}
@@ -585,4 +600,6 @@
private static native long nNativeByteSize(long nativePtr);
@FastNative
private static native void nMarkInvisible(long nativePtr);
+ @FastNative
+ private static native void nSetMirrored(long nativePtr, boolean mirror);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 35790b6..813eae7 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -6,7 +6,10 @@
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
"hwui_pgo",
- "hwui_lto",
+ // Disable LTO temporarily. LTO does not seem to interact well with
+ // PGO profile-file updates and incremental builds in the build
+ // servers.
+ // "hwui_lto",
],
cpp_std: "c++17",
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 7e4f755..28d0bc4 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -32,8 +32,7 @@
}
void AnimatedImageDrawable::syncProperties() {
- mAlpha = mStagingAlpha;
- mColorFilter = mStagingColorFilter;
+ mProperties = mStagingProperties;
}
bool AnimatedImageDrawable::start() {
@@ -115,12 +114,18 @@
// Only called on the RenderThread.
void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
SkTLazy<SkPaint> lazyPaint;
- if (mAlpha != SK_AlphaOPAQUE || mColorFilter.get()) {
+ SkAutoCanvasRestore acr(canvas, false);
+ if (mProperties.mAlpha != SK_AlphaOPAQUE || mProperties.mColorFilter.get()) {
lazyPaint.init();
- lazyPaint.get()->setAlpha(mAlpha);
- lazyPaint.get()->setColorFilter(mColorFilter);
+ lazyPaint.get()->setAlpha(mProperties.mAlpha);
+ lazyPaint.get()->setColorFilter(mProperties.mColorFilter);
lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
}
+ if (mProperties.mMirrored) {
+ canvas->save();
+ canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
+ canvas->scale(-1, 1);
+ }
mDidDraw = true;
@@ -131,7 +136,6 @@
if (drawDirectly) {
// The image is not animating, and never was. Draw directly from
// mSkAnimatedImage.
- SkAutoCanvasRestore acr(canvas, false);
if (lazyPaint.isValid()) {
canvas->saveLayer(mSkAnimatedImage->getBounds(), lazyPaint.get());
}
@@ -190,12 +194,17 @@
double AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
SkAutoCanvasRestore acr(canvas, false);
- if (mStagingAlpha != SK_AlphaOPAQUE || mStagingColorFilter.get()) {
+ if (mStagingProperties.mAlpha != SK_AlphaOPAQUE || mStagingProperties.mColorFilter.get()) {
SkPaint paint;
- paint.setAlpha(mStagingAlpha);
- paint.setColorFilter(mStagingColorFilter);
+ paint.setAlpha(mStagingProperties.mAlpha);
+ paint.setColorFilter(mStagingProperties.mColorFilter);
canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint);
}
+ if (mStagingProperties.mMirrored) {
+ canvas->save();
+ canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
+ canvas->scale(-1, 1);
+ }
if (!mRunning) {
// Continue drawing the current frame, and return 0 to indicate no need
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index a5260be..f4e2ba7 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -55,9 +55,12 @@
*/
bool isDirty();
- int getStagingAlpha() const { return mStagingAlpha; }
- void setStagingAlpha(int alpha) { mStagingAlpha = alpha; }
- void setStagingColorFilter(sk_sp<SkColorFilter> filter) { mStagingColorFilter = filter; }
+ int getStagingAlpha() const { return mStagingProperties.mAlpha; }
+ void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; }
+ void setStagingColorFilter(sk_sp<SkColorFilter> filter) {
+ mStagingProperties.mColorFilter = filter;
+ }
+ void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
void syncProperties();
virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); }
@@ -131,11 +134,18 @@
// Locked when mSkAnimatedImage is being updated or drawn.
std::mutex mImageLock;
- int mStagingAlpha = SK_AlphaOPAQUE;
- sk_sp<SkColorFilter> mStagingColorFilter;
+ struct Properties {
+ int mAlpha = SK_AlphaOPAQUE;
+ sk_sp<SkColorFilter> mColorFilter;
+ bool mMirrored = false;
- int mAlpha = SK_AlphaOPAQUE;
- sk_sp<SkColorFilter> mColorFilter;
+ Properties() = default;
+ Properties(Properties&) = default;
+ Properties& operator=(Properties&) = default;
+ };
+
+ Properties mStagingProperties;
+ Properties mProperties;
std::unique_ptr<OnAnimationEndListener> mEndListener;
};
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index ef6a8ff..b3ed393 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -43,6 +43,9 @@
// incidentd read file and gzip the data in bytes field
SECTION_GZIP = 5;
+
+ // incidentd calls tombstoned for annotated field
+ SECTION_TOMBSTONE = 6;
}
message SectionFlags {
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 39cdcf0..fca0cc7 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -162,6 +162,11 @@
}
/** @hide */
+ public boolean isAffectingUsage(int usage) {
+ return mRule.isAffectingUsage(usage);
+ }
+
+ /** @hide */
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 866b574..749a45e 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -135,6 +135,17 @@
}
}
+ boolean isAffectingUsage(int usage) {
+ for (AudioMixMatchCriterion criterion : mCriteria) {
+ if ((criterion.mRule & RULE_MATCH_ATTRIBUTE_USAGE) != 0
+ && criterion.mAttr != null
+ && criterion.mAttr.getUsage() == usage) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static boolean areCriteriaEquivalent(ArrayList<AudioMixMatchCriterion> cr1,
ArrayList<AudioMixMatchCriterion> cr2) {
if (cr1 == null || cr2 == null) return false;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index ecc2ff4..299e337 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -70,6 +70,11 @@
*/
public MenuItem getLongpressMenuItem(Context context);
+ /**
+ * @return the {@link MenuItem} to display when app ops icons are pressed.
+ */
+ public MenuItem getAppOpsMenuItem(Context context);
+
public void setMenuItems(ArrayList<MenuItem> items);
public void setMenuClickListener(OnMenuEventListener listener);
diff --git a/packages/SystemUI/res/layout/app_ops_info.xml b/packages/SystemUI/res/layout/app_ops_info.xml
new file mode 100644
index 0000000..74a4c6e
--- /dev/null
+++ b/packages/SystemUI/res/layout/app_ops_info.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018, 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.
+-->
+
+<com.android.systemui.statusbar.AppOpsInfo
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/app_ops_info"
+ android:clickable="true"
+ android:orientation="vertical"
+ android:paddingStart="@*android:dimen/notification_content_margin_start"
+ android:paddingEnd="@*android:dimen/notification_content_margin_end"
+ android:background="@color/notification_guts_bg_color"
+ android:theme="@*android:style/Theme.DeviceDefault.Light">
+
+ <!-- Package Info -->
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top" >
+ <ImageView
+ android:id="@+id/pkgicon"
+ android:layout_width="@dimen/notification_guts_header_height"
+ android:layout_height="@dimen/notification_guts_header_height"
+ android:layout_centerVertical="true"
+ android:layout_marginEnd="3dp" />
+ <TextView
+ android:id="@+id/pkgname"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+ android:layout_marginStart="3dp"
+ android:layout_marginEnd="2dp"
+ android:singleLine="true"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/pkgicon" />
+ </RelativeLayout>
+
+ <TextView
+ android:id="@+id/prompt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top"
+ style="@style/TextAppearance.NotificationInfo.Secondary" />
+
+ <!-- Settings and Done buttons -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/notification_guts_button_spacing"
+ android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+ android:gravity="end" >
+
+ <TextView
+ android:id="@+id/settings"
+ android:text="@string/notification_appops_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@drawable/ripple_drawable"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/ok"
+ android:text="@string/notification_appops_ok"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@drawable/ripple_drawable"
+ android:minWidth="48dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="-8dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </LinearLayout>
+</com.android.systemui.statusbar.AppOpsInfo>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c89d818..4420103 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1545,6 +1545,25 @@
<!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
<string name="notification_unblockable_desc">These notifications can\'t be turned off</string>
+ <string name="notification_appops_camera_active">camera</string>
+
+ <string name="notification_appops_microphone_active">microphone</string>
+
+ <string name="notification_appops_overlay_active">displaying over other apps on your screen</string>
+
+ <plurals name="notification_appops">
+ <item quantity="one">This app is <xliff:g id="performing activity" example="using the camera">%1$s</xliff:g>.</item>
+ <item quantity="other">This app is <xliff:g id="performing activity" example="using the camera">%1$s</xliff:g> and <xliff:g id="performing activity" example="using the microphone">%2$s</xliff:g>.</item>
+ </plurals>
+
+ <plurals name="notification_using">
+ <item quantity="one">using the <xliff:g id="performing activity" example="camera">%1$s</xliff:g></item>
+ <item quantity="other">using the <xliff:g id="performing activity" example="camera">%1$s</xliff:g> and <xliff:g id="performing activity" example="microphone">%2$s</xliff:g></item>
+ </plurals>
+
+ <string name="notification_appops_settings">Settings</string>
+ <string name="notification_appops_ok">Ok</string>
+
<!-- Notification: Control panel: Accessibility description for expanded inline controls view, used
to control settings about notifications related to the current notification. -->
<string name="notification_channel_controls_opened_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> opened</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index e200a7f..ef36610 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -65,4 +65,19 @@
* Sent for each movement over the nav bar while the user is scrubbing it to switch tasks.
*/
void onQuickScrubProgress(float progress);
+
+ /**
+ * Sent when overview button is pressed to toggle show/hide of overview.
+ */
+ void onOverviewToggle();
+
+ /**
+ * Sent when overview is to be shown.
+ */
+ void onOverviewShown(boolean triggeredFromAltTab);
+
+ /**
+ * Sent when overview is to be hidden.
+ */
+ void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
index 17191868..b8193a89 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
@@ -22,12 +22,13 @@
public class NavigationBarCompat {
@Retention(RetentionPolicy.SOURCE)
- @IntDef({HIT_TARGET_NONE, HIT_TARGET_BACK, HIT_TARGET_HOME})
+ @IntDef({HIT_TARGET_NONE, HIT_TARGET_BACK, HIT_TARGET_HOME, HIT_TARGET_OVERVIEW})
public @interface HitTarget{}
public static final int HIT_TARGET_NONE = 0;
public static final int HIT_TARGET_BACK = 1;
public static final int HIT_TARGET_HOME = 2;
+ public static final int HIT_TARGET_OVERVIEW = 3;
@Retention(RetentionPolicy.SOURCE)
@IntDef({FLAG_DISABLE_SWIPE_UP,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index a3ffa40..8a4f324 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -20,6 +20,7 @@
import android.app.AlarmManager;
import android.app.IActivityManager;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
@@ -357,7 +358,7 @@
updateDozeVisibleViews();
mKeyguardSlice.setDark(darkAmount);
mClockView.setTextColor(blendedTextColor);
- mClockSeparator.setBackgroundColor(blendedTextColor);
+ mClockSeparator.setBackgroundTintList(ColorStateList.valueOf(blendedTextColor));
}
public void setPulsing(boolean pulsing) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index df4a975..674ccd8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -51,6 +51,7 @@
import com.android.systemui.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
+import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.SystemUI;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
@@ -252,10 +253,13 @@
return;
}
- if (mOverviewProxyService.getProxy() != null) {
- // TODO: Proxy to Launcher
- if (!triggeredFromAltTab) {
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ try {
+ overviewProxy.onOverviewShown(triggeredFromAltTab);
return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send overview show event to launcher.", e);
}
}
@@ -294,10 +298,13 @@
return;
}
- if (mOverviewProxyService.getProxy() != null) {
- // TODO: Proxy to Launcher
- if (!triggeredFromAltTab) {
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ try {
+ overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send overview hide event to launcher.", e);
}
}
@@ -332,9 +339,15 @@
return;
}
- if (mOverviewProxyService.getProxy() != null) {
- // TODO: Proxy to Launcher
- return;
+ // If connected to launcher service, let it handle the toggle logic
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ try {
+ overviewProxy.onOverviewToggle();
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
+ }
}
int growTarget = getComponent(Divider.class).getView().growsRecents();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java
new file mode 100644
index 0000000..322a529
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2018 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.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
+/**
+ * The guts of a notification revealed when performing a long press.
+ */
+public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
+ private static final String TAG = "AppOpsGuts";
+
+ private PackageManager mPm;
+
+ private String mPkg;
+ private String mAppName;
+ private int mAppUid;
+ private StatusBarNotification mSbn;
+ private ArraySet<Integer> mAppOps;
+ private MetricsLogger mMetricsLogger;
+ private OnSettingsClickListener mOnSettingsClickListener;
+ private NotificationGuts mGutsContainer;
+
+ private OnClickListener mOnOk = v -> {
+ closeControls(v);
+ };
+
+ public AppOpsInfo(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public interface OnSettingsClickListener {
+ void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
+ }
+
+ public void bindGuts(final PackageManager pm,
+ final OnSettingsClickListener onSettingsClick,
+ final StatusBarNotification sbn,
+ ArraySet<Integer> activeOps) {
+ mPkg = sbn.getPackageName();
+ mSbn = sbn;
+ mPm = pm;
+ mAppName = mPkg;
+ mOnSettingsClickListener = onSettingsClick;
+ mAppOps = activeOps;
+
+ bindHeader();
+ bindPrompt();
+ bindButtons();
+
+ mMetricsLogger = new MetricsLogger();
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
+ }
+
+ private void bindHeader() {
+ // Package name
+ Drawable pkgicon = null;
+ ApplicationInfo info;
+ try {
+ info = mPm.getApplicationInfo(mPkg,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (info != null) {
+ mAppUid = mSbn.getUid();
+ mAppName = String.valueOf(mPm.getApplicationLabel(info));
+ pkgicon = mPm.getApplicationIcon(info);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // app is gone, just show package name and generic icon
+ pkgicon = mPm.getDefaultActivityIcon();
+ }
+ ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+ ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
+ }
+
+ private void bindPrompt() {
+ final TextView prompt = findViewById(R.id.prompt);
+ prompt.setText(getPromptString());
+ }
+
+ private void bindButtons() {
+ View settings = findViewById(R.id.settings);
+ settings.setOnClickListener((View view) -> {
+ mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
+ });
+ TextView ok = findViewById(R.id.ok);
+ ok.setOnClickListener(mOnOk);
+ }
+
+ private String getPromptString() {
+ String cameraString =
+ mContext.getResources().getString(R.string.notification_appops_camera_active);
+ String micString =
+ mContext.getResources().getString(R.string.notification_appops_microphone_active);
+ String overlayString =
+ mContext.getResources().getString(R.string.notification_appops_overlay_active);
+ String using = null;
+ String promptString;
+ if (mAppOps.contains(AppOpsManager.OP_CAMERA)
+ && mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
+ using = mContext.getResources().getQuantityString(
+ R.plurals.notification_using, 2, micString, cameraString);
+ } else if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
+ using = mContext.getResources().getQuantityString(
+ R.plurals.notification_using, 1, cameraString);
+ } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)){
+ using = mContext.getResources().getQuantityString(
+ R.plurals.notification_using, 1, micString);
+ }
+
+ if (mAppOps.contains(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)) {
+ if (using != null) {
+ promptString = mContext.getResources().getQuantityString(
+ R.plurals.notification_appops, 2, overlayString, using);
+ } else {
+ promptString = mContext.getResources().getQuantityString(
+ R.plurals.notification_appops, 1, overlayString);
+ }
+ } else {
+ promptString = mContext.getResources().getQuantityString(
+ R.plurals.notification_appops, 1, using);
+ }
+
+ return promptString;
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ if (mGutsContainer != null &&
+ event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ if (mGutsContainer.isExposed()) {
+ event.getText().add(mContext.getString(
+ R.string.notification_channel_controls_opened_accessibility, mAppName));
+ } else {
+ event.getText().add(mContext.getString(
+ R.string.notification_channel_controls_closed_accessibility, mAppName));
+ }
+ }
+ }
+
+ private void closeControls(View v) {
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ mGutsContainer.closeControls(x, y, false, false);
+ }
+
+ @Override
+ public void setGutsParent(NotificationGuts guts) {
+ mGutsContainer = guts;
+ }
+
+ @Override
+ public boolean willBeRemoved() {
+ return false;
+ }
+
+ @Override
+ public View getContentView() {
+ return this;
+ }
+
+ @Override
+ public boolean handleCloseControls(boolean save, boolean force) {
+ return false;
+ }
+
+ @Override
+ public int getActualHeight() {
+ return getHeight();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 785fc1c..e5c5dcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -25,8 +25,8 @@
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Resources;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
@@ -188,6 +188,7 @@
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
+ private View.OnClickListener mOnAppOpsClickListener;
// Listener will be called when receiving a long click event.
// Use #setLongPressPosition to optionally assign positional data with the long press.
@@ -890,6 +891,7 @@
ArrayList<MenuItem> items = new ArrayList<>();
items.add(NotificationMenuRow.createInfoItem(mContext));
items.add(NotificationMenuRow.createSnoozeItem(mContext));
+ items.add(NotificationMenuRow.createAppOpsItem(mContext));
mMenuRow.setMenuItems(items);
}
if (existed) {
@@ -1363,6 +1365,20 @@
mPublicLayout.showAppOpsIcons(activeOps);
}
+ public View.OnClickListener getAppOpsOnClickListener() {
+ return mOnAppOpsClickListener;
+ }
+
+ protected void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
+ mOnAppOpsClickListener = v -> {
+ createMenu();
+ MenuItem menuItem = getProvider().getAppOpsMenuItem(mContext);
+ if (menuItem != null) {
+ l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem);
+ }
+ };
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -2658,4 +2674,15 @@
*/
boolean onLongPress(View v, int x, int y, MenuItem item);
}
+
+ /**
+ * Equivalent to View.OnClickListener with coordinates
+ */
+ public interface OnAppOpsClickListener {
+ /**
+ * Equivalent to {@link View.OnClickListener#onClick(View)} with coordinates
+ * @return whether the click was handled
+ */
+ boolean onClick(View v, int x, int y, MenuItem item);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 71f7911..146de00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -124,6 +124,7 @@
protected boolean mUseHeadsUp = false;
protected boolean mDisableNotificationAlerts;
protected NotificationListContainer mListContainer;
+ private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
private final class NotificationClicker implements View.OnClickListener {
@@ -271,6 +272,7 @@
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
mHeadsUpObserver.onChange(true); // set up
+ mOnAppOpsClickListener = mGutsManager::openGuts;
}
public NotificationData getNotificationData() {
@@ -361,6 +363,8 @@
row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}
+ row.setAppOpsOnClickListener(mOnAppOpsClickListener);
+
mCallback.onBindRow(entry, pmUser, sbn, row);
}
@@ -622,7 +626,7 @@
}
}
- private void updateNotification(NotificationData.Entry entry, PackageManager pmUser,
+ protected void updateNotification(NotificationData.Entry entry, PackageManager pmUser,
StatusBarNotification sbn, ExpandableNotificationRow row) {
row.setNeedsRedaction(mLockscreenUserManager.needsRedaction(entry));
boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
index f730601..9b2f939 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
@@ -15,9 +15,13 @@
*/
package com.android.systemui.statusbar;
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.service.notification.NotificationListenerService.Ranking
.USER_SENTIMENT_NEGATIVE;
+import android.app.AppOpsManager;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.content.Context;
@@ -147,6 +151,23 @@
mPresenter.startNotificationGutsIntent(intent, appUid, row);
}
+ protected void startAppOpsSettingsActivity(String pkg, int uid, ArraySet<Integer> ops,
+ ExpandableNotificationRow row) {
+ if (ops.contains(OP_SYSTEM_ALERT_WINDOW)) {
+ if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
+ startAppNotificationSettingsActivity(pkg, uid, null, row);
+ } else {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+ intent.setData(Uri.fromParts("package", pkg, null));
+ mPresenter.startNotificationGutsIntent(intent, uid, row);
+ }
+ } else if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
+ Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, pkg);
+ mPresenter.startNotificationGutsIntent(intent, uid, row);
+ }
+ }
+
public void bindGuts(final ExpandableNotificationRow row) {
bindGuts(row, mGutsMenuItem);
}
@@ -185,6 +206,22 @@
});
}
+ if (gutsView instanceof AppOpsInfo) {
+ AppOpsInfo info = (AppOpsInfo) gutsView;
+ final UserHandle userHandle = sbn.getUser();
+ PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+ userHandle.getIdentifier());
+ final AppOpsInfo.OnSettingsClickListener onSettingsClick = (View v,
+ String pkg, int uid, ArraySet<Integer> ops) -> {
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
+ guts.resetFalsingCheck();
+ startAppOpsSettingsActivity(pkg, uid, ops, row);
+ };
+ if (!row.getEntry().mActiveAppOps.isEmpty()) {
+ info.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
+ }
+ }
+
if (gutsView instanceof NotificationInfo) {
final UserHandle userHandle = sbn.getUser();
PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 037eeb2..0eb6bd4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -30,6 +30,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
@@ -68,6 +69,7 @@
private Context mContext;
private FrameLayout mMenuContainer;
private MenuItem mInfoItem;
+ private MenuItem mAppOpsItem;
private ArrayList<MenuItem> mMenuItems;
private OnMenuEventListener mMenuListener;
@@ -121,6 +123,11 @@
}
@Override
+ public MenuItem getAppOpsMenuItem(Context context) {
+ return mAppOpsItem;
+ }
+
+ @Override
public void setSwipeActionHelper(NotificationSwipeActionHelper helper) {
mSwipeHelper = helper;
}
@@ -189,6 +196,9 @@
mInfoItem = createInfoItem(mContext);
mMenuItems.add(mInfoItem);
+ mAppOpsItem = createAppOpsItem(mContext);
+ mMenuItems.add(mAppOpsItem);
+
// Construct the menu views
if (mMenuContainer != null) {
mMenuContainer.removeAllViews();
@@ -614,6 +624,14 @@
return info;
}
+ public static MenuItem createAppOpsItem(Context context) {
+ AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
+ R.layout.app_ops_info, null, false);
+ MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
+ -1 /*don't show in slow swipe menu */);
+ return info;
+ }
+
private void addMenuView(MenuItem item, ViewGroup parent) {
View menuView = item.getMenuView();
if (menuView != null) {
@@ -631,22 +649,29 @@
GutsContent mGutsContent;
String mContentDescription;
+ /**
+ * Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
+ * but can still be exposed via other affordances.
+ */
public NotificationMenuItem(Context context, String s, GutsContent content, int iconResId) {
Resources res = context.getResources();
int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
int tint = res.getColor(R.color.notification_gear_color);
- AlphaOptimizedImageView iv = new AlphaOptimizedImageView(context);
- iv.setPadding(padding, padding, padding, padding);
- Drawable icon = context.getResources().getDrawable(iconResId);
- iv.setImageDrawable(icon);
- iv.setColorFilter(tint);
- iv.setAlpha(1f);
- mMenuView = iv;
+ if (iconResId >= 0) {
+ AlphaOptimizedImageView iv = new AlphaOptimizedImageView(context);
+ iv.setPadding(padding, padding, padding, padding);
+ Drawable icon = context.getResources().getDrawable(iconResId);
+ iv.setImageDrawable(icon);
+ iv.setColorFilter(tint);
+ iv.setAlpha(1f);
+ mMenuView = iv;
+ }
mContentDescription = s;
mGutsContent = content;
}
@Override
+ @Nullable
public View getMenuView() {
return mMenuView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index b95b8a3..dfcd5e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -98,6 +98,7 @@
}, TRANSFORMING_VIEW_TITLE);
resolveHeaderViews();
updateInvertHelper();
+ addAppOpsOnClickListener(row);
}
@Override
@@ -121,6 +122,10 @@
getDozer().setColor(mColor);
}
+ private void addAppOpsOnClickListener(ExpandableNotificationRow row) {
+ mNotificationHeader.setAppOpsOnClickListener(row.getAppOpsOnClickListener());
+ }
+
private int resolveColor(ImageView icon) {
if (icon != null && icon.getDrawable() != null) {
ColorFilter filter = icon.getDrawable().getColorFilter();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 3b080cf..056874f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -79,6 +79,7 @@
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
final static boolean DEBUG = false;
@@ -106,6 +107,7 @@
private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE;
private Rect mHomeButtonBounds = new Rect();
private Rect mBackButtonBounds = new Rect();
+ private Rect mRecentsButtonBounds = new Rect();
private int[] mTmpPosition = new int[2];
private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
@@ -117,7 +119,7 @@
private KeyButtonDrawable mImeIcon;
private KeyButtonDrawable mMenuIcon;
private KeyButtonDrawable mAccessibilityIcon;
- private KeyButtonDrawable mRotateSuggestionIcon;
+ private TintedKeyButtonDrawable mRotateSuggestionIcon;
private GestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -306,6 +308,8 @@
mDownHitTarget = HIT_TARGET_BACK;
} else if (mHomeButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_HOME;
+ } else if (mRecentsButtonBounds.contains(x, y)) {
+ mDownHitTarget = HIT_TARGET_OVERVIEW;
}
break;
}
@@ -479,7 +483,7 @@
darkContext.getDrawable(darkIcon));
}
- private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
+ private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
@ColorInt int lightColor, @ColorInt int darkColor) {
return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
}
@@ -745,8 +749,15 @@
Context rotateContext = new ContextThemeWrapper(ctx, style);
// Recreate the icon and set it if needed
+ TintedKeyButtonDrawable priorIcon = mRotateSuggestionIcon;
mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
lightColor, darkColor);
+
+ // Apply any prior set dark intensity
+ if (priorIcon != null && priorIcon.isDarkIntensitySet()) {
+ mRotateSuggestionIcon.setDarkIntensity(priorIcon.getDarkIntensity());
+ }
+
if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
}
@@ -816,6 +827,7 @@
super.onLayout(changed, left, top, right, bottom);
updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
+ updateButtonLocationOnScreen(getRecentsButton(), mRecentsButtonBounds);
mGestureHelper.onLayout(changed, left, top, right, bottom);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
index acf9c00..56f6726 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
@@ -30,6 +30,9 @@
private final int mLightColor;
private final int mDarkColor;
+ public static final float DARK_INTENSITY_NOT_SET = -1f;
+ private float mDarkIntensity = DARK_INTENSITY_NOT_SET;
+
public static TintedKeyButtonDrawable create(Drawable drawable, @ColorInt int lightColor,
@ColorInt int darkColor) {
return new TintedKeyButtonDrawable(new Drawable[] { drawable }, lightColor, darkColor);
@@ -39,11 +42,13 @@
super(drawables);
mLightColor = lightColor;
mDarkColor = darkColor;
+ setDarkIntensity(0f); // Set initial coloration
}
@Override
public void setDarkIntensity(float intensity) {
// Duplicate intensity scaling from KeyButtonDrawable
+ mDarkIntensity = intensity;
int intermediateColor = ColorUtils.compositeColors(
setAlphaFloat(mDarkColor, intensity),
setAlphaFloat(mLightColor,1f - intensity));
@@ -52,6 +57,16 @@
}
private int setAlphaFloat(int color, float alpha) {
- return ColorUtils.setAlphaComponent(color, (int) (alpha * 255f));
+ // Ensure alpha is clamped [0-255] or ColorUtils will crash
+ final int alphaInt = alpha > 1f ? 255 : (alpha < 0f ? 0 : ((int) alpha*255));
+ return ColorUtils.setAlphaComponent(color, alphaInt);
+ }
+
+ public boolean isDarkIntensitySet() {
+ return mDarkIntensity == DARK_INTENSITY_NOT_SET;
+ }
+
+ public float getDarkIntensity() {
+ return mDarkIntensity;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java
new file mode 100644
index 0000000..660d2dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 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 static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.UiThreadTest;
+import android.util.ArraySet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@UiThreadTest
+public class AppOpsInfoTest extends SysuiTestCase {
+ private static final String TEST_PACKAGE_NAME = "test_package";
+ private static final int TEST_UID = 1;
+
+ private AppOpsInfo mAppOpsInfo;
+ private final PackageManager mMockPackageManager = mock(PackageManager.class);
+ private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
+ private StatusBarNotification mSbn;
+
+ @Before
+ public void setUp() throws Exception {
+ // Inflate the layout
+ final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null);
+ mAppOpsInfo.setGutsParent(mGutsParent);
+
+ // PackageManager must return a packageInfo and applicationInfo.
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
+ .thenReturn(packageInfo);
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = TEST_UID; // non-zero
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+ applicationInfo);
+
+ mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
+ new Notification(), UserHandle.CURRENT, null, 0);
+ }
+
+ @Test
+ public void testBindNotification_SetsTextApplicationName() {
+ when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+ final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname);
+ assertTrue(textView.getText().toString().contains("App Name"));
+ }
+
+ @Test
+ public void testBindNotification_SetsPackageIcon() {
+ final Drawable iconDrawable = mock(Drawable.class);
+ when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
+ .thenReturn(iconDrawable);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+ final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon);
+ assertEquals(iconDrawable, iconView.getDrawable());
+ }
+
+ @Test
+ public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+ ArraySet<Integer> ops) -> {
+ assertEquals(TEST_PACKAGE_NAME, pkg);
+ assertEquals(expectedOps, ops);
+ assertEquals(TEST_UID, uid);
+ latch.countDown();
+ }, mSbn, expectedOps);
+
+ final View settingsButton = mAppOpsInfo.findViewById(R.id.settings);
+ settingsButton.performClick();
+ // Verify that listener was triggered.
+ assertEquals(0, latch.getCount());
+ }
+
+ @Test
+ public void testOk() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+ ArraySet<Integer> ops) -> {
+ assertEquals(TEST_PACKAGE_NAME, pkg);
+ assertEquals(expectedOps, ops);
+ assertEquals(TEST_UID, uid);
+ latch.countDown();
+ }, mSbn, expectedOps);
+
+ final View okButton = mAppOpsInfo.findViewById(R.id.ok);
+ okButton.performClick();
+ assertEquals(1, latch.getCount());
+ verify(mGutsParent, times(1)).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
+ }
+
+ @Test
+ public void testPrompt_camera() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_mic() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_RECORD_AUDIO);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the microphone.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_mic() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_RECORD_AUDIO);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the microphone and camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_mic_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_RECORD_AUDIO);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the microphone and camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_mic_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_RECORD_AUDIO);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the microphone.", prompt.getText());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index ce629bb..34e444e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -153,14 +154,15 @@
}
@Test
- public void testShowAppOpsIcons_noHeader() {
+ public void testShowAppOps_noHeader() {
// public notification is custom layout - no header
mGroup.setSensitive(true, true);
- mGroup.showAppOpsIcons(new ArraySet<>());
+ mGroup.setAppOpsOnClickListener(null);
+ mGroup.showAppOpsIcons(null);
}
@Test
- public void testShowAppOpsIcons_header() throws Exception {
+ public void testShowAppOpsIcons_header() {
NotificationHeaderView mockHeader = mock(NotificationHeaderView.class);
NotificationContentView publicLayout = mock(NotificationContentView.class);
@@ -181,4 +183,16 @@
verify(publicLayout, times(1)).showAppOpsIcons(ops);
}
+
+ @Test
+ public void testAppOpsOnClick() {
+ ExpandableNotificationRow.OnAppOpsClickListener l = mock(
+ ExpandableNotificationRow.OnAppOpsClickListener.class);
+ View view = mock(View.class);
+
+ mGroup.setAppOpsOnClickListener(l);
+
+ mGroup.getAppOpsOnClickListener().onClick(view);
+ verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
index 37dd939..7e5db34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
@@ -37,6 +37,8 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
index 8f38c2c..6209d59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
@@ -16,6 +16,10 @@
package com.android.systemui.statusbar;
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
@@ -34,14 +38,17 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.ArraySet;
import android.view.LayoutInflater;
import android.view.View;
@@ -58,6 +65,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoRule;
import org.mockito.junit.MockitoJUnit;
@@ -164,6 +172,81 @@
verify(row, times(2)).setGutsView(any());
}
+ @Test
+ public void testAppOpsSettingsIntent_camera() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_CAMERA);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_mic() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_RECORD_AUDIO);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_camera_mic() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_CAMERA);
+ ops.add(OP_RECORD_AUDIO);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_overlay() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_SYSTEM_ALERT_WINDOW);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_camera_mic_overlay() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_CAMERA);
+ ops.add(OP_RECORD_AUDIO);
+ ops.add(OP_SYSTEM_ALERT_WINDOW);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_camera_overlay() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_CAMERA);
+ ops.add(OP_SYSTEM_ALERT_WINDOW);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+ }
+
+ @Test
+ public void testAppOpsSettingsIntent_mic_overlay() {
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(OP_RECORD_AUDIO);
+ ops.add(OP_SYSTEM_ALERT_WINDOW);
+ mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////
// Utility methods:
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 2a2acab..2a5a1ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -14,14 +14,23 @@
package com.android.systemui.statusbar;
+import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.ViewUtils;
import android.testing.ViewUtils;
+import android.view.View;
+import android.view.ViewGroup;
+
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -63,4 +72,19 @@
NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
row.resetMenu();
}
+
+ @Test
+ public void testNoAppOpsInSlowSwipe() {
+ NotificationMenuRow row = new NotificationMenuRow(mContext);
+ Notification n = mock(Notification.class);
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getNotification()).thenReturn(n);
+ ExpandableNotificationRow parent = mock(ExpandableNotificationRow.class);
+ when(parent.getStatusBarNotification()).thenReturn(sbn);
+ row.createMenu(parent, null);
+
+ ViewGroup container = (ViewGroup) row.getMenuView();
+ // one for snooze and one for noti blocking
+ assertEquals(2, container.getChildCount());
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index a06490b..266b2d7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -565,16 +565,19 @@
}
}
- private @Nullable Set<String> getWhitelistedCompatModePackages() {
- final String compatPackagesSetting = Settings.Global.getString(
+ private String getWhitelistedCompatModePackagesFromSettings() {
+ return Settings.Global.getString(
mContext.getContentResolver(),
Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
+ }
+
+ private @Nullable Set<String> getWhitelistedCompatModePackages() {
+ final String compatPackagesSetting = getWhitelistedCompatModePackagesFromSettings();
if (TextUtils.isEmpty(compatPackagesSetting)) {
return null;
}
final Set<String> compatPackages = new ArraySet<>();
- final SimpleStringSplitter splitter = new SimpleStringSplitter(
- COMPAT_PACKAGE_DELIMITER);
+ final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER);
splitter.setString(compatPackagesSetting);
while (splitter.hasNext()) {
compatPackages.add(splitter.next());
@@ -1045,6 +1048,8 @@
mUi.dump(pw);
pw.print("Autofill Compat State: ");
pw.println(mAutofillCompatState.mUserSpecs);
+ pw.print(prefix); pw.print("from settings: ");
+ pw.println(getWhitelistedCompatModePackagesFromSettings());
}
if (showHistory) {
pw.println(); pw.println("Requests history:"); pw.println();
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 5eee9ed..4abf0f8 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -254,7 +254,7 @@
// change AssistStructure so it provides a "one-way" writeToParcel() method that
// sends all the data
try {
- structure.ensureData();
+ structure.ensureDataForAutofill();
} catch (RuntimeException e) {
wtf(e, "Exception lazy loading assist structure for %s: %s",
structure.getActivityComponent(), e);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d066056..8ce4e64 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1868,6 +1868,7 @@
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
+ final long nowUPTIME = SystemClock.uptimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
pw.print(" nowRTC="); pw.print(nowRTC);
@@ -1883,6 +1884,25 @@
pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
+
+ SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
+ if (ssm != null) {
+ pw.println();
+ pw.print(" RuntimeStarted=");
+ pw.print(sdf.format(
+ new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
+ if (ssm.isRuntimeRestarted()) {
+ pw.print(" (Runtime restarted)");
+ }
+ pw.println();
+ pw.print(" Runtime uptime (elapsed): ");
+ TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
+ pw.println();
+ pw.print(" Runtime uptime (uptime): ");
+ TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
+ pw.println();
+ }
+
pw.println();
if (!mInteractive) {
pw.print(" Time since non-interactive: ");
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 581914d..63584d9 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -39,6 +39,8 @@
private final Context mContext;
private boolean mSafeMode;
private boolean mRuntimeRestarted;
+ private long mRuntimeStartElapsedTime;
+ private long mRuntimeStartUptime;
// Services that should receive lifecycle events.
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
@@ -287,8 +289,25 @@
return mRuntimeRestarted;
}
- void setRuntimeRestarted(boolean runtimeRestarted) {
+ /**
+ * @return Time when SystemServer was started, in elapsed realtime.
+ */
+ public long getRuntimeStartElapsedTime() {
+ return mRuntimeStartElapsedTime;
+ }
+
+ /**
+ * @return Time when SystemServer was started, in uptime.
+ */
+ public long getRuntimeStartUptime() {
+ return mRuntimeStartUptime;
+ }
+
+ void setStartInfo(boolean runtimeRestarted,
+ long runtimeStartElapsedTime, long runtimeStartUptime) {
mRuntimeRestarted = runtimeRestarted;
+ mRuntimeStartElapsedTime = runtimeStartElapsedTime;
+ mRuntimeStartUptime = runtimeStartUptime;
}
private void warnIfTooLong(long duration, SystemService service, String operation) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index f4a4af2..666f3a2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -347,6 +347,9 @@
private final Rect mTmpRect2 = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
+ /** List for processing through a set of activities */
+ private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
+
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
@@ -4405,11 +4408,15 @@
"Removing app " + app + " from history with " + i + " entries");
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- --i;
+ mTmpActivities.clear();
+ mTmpActivities.addAll(activities);
+
+ while (!mTmpActivities.isEmpty()) {
+ final int targetIndex = mTmpActivities.size() - 1;
+ final ActivityRecord r = mTmpActivities.remove(targetIndex);
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
- "Record #" + i + " " + r + ": app=" + r.app);
+ "Record #" + targetIndex + " " + r + ": app=" + r.app);
+
if (r.app == app) {
if (r.visible) {
hasVisibleActivities = true;
@@ -4827,9 +4834,11 @@
ComponentName homeActivity = null;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
- int numActivities = activities.size();
- for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
- ActivityRecord r = activities.get(activityNdx);
+ mTmpActivities.clear();
+ mTmpActivities.addAll(activities);
+
+ while (!mTmpActivities.isEmpty()) {
+ ActivityRecord r = mTmpActivities.remove(0);
final boolean sameComponent =
(r.packageName.equals(packageName) && (filterByClasses == null
|| filterByClasses.contains(r.realActivity.getClassName())))
@@ -4862,12 +4871,8 @@
r.app = null;
}
lastTask = r.getTask();
- if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
- true)) {
- // r has been deleted from mActivities, accommodate.
- --numActivities;
- --activityNdx;
- }
+ finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
+ true);
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 6f6e0d9..8174f40 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -2002,7 +2002,7 @@
} else if (intent != null) {
sb.append(" I=");
sb.append(intent.getComponent().flattenToShortString());
- } else if (affinityIntent != null) {
+ } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
sb.append(" aI=");
sb.append(affinityIntent.getComponent().flattenToShortString());
} else {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 3b5cad6..94a64eb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -144,6 +144,7 @@
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -5683,7 +5684,9 @@
}
// ignore condition on device being actually used for music when in communication
// because music routing is altered in this case.
- if (((device == musicDevice) || isInCommunication()) && (device == devices)) {
+ // also checks whether media routing if affected by a dynamic policy
+ if (((device == musicDevice) || isInCommunication()) && (device == devices)
+ && !hasMediaDynamicPolicy()) {
mAudioHandler.removeMessages(MSG_BROADCAST_AUDIO_BECOMING_NOISY);
sendMsg(mAudioHandler,
MSG_BROADCAST_AUDIO_BECOMING_NOISY,
@@ -5709,6 +5712,24 @@
return delay;
}
+ /**
+ * @return true if there is currently a registered dynamic mixing policy that affects media
+ */
+ private boolean hasMediaDynamicPolicy() {
+ synchronized (mAudioPolicies) {
+ if (mAudioPolicies.isEmpty()) {
+ return false;
+ }
+ final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
+ for (AudioPolicyProxy app : appColl) {
+ if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
private void updateAudioRoutes(int device, int state)
{
int connType = 0;
@@ -7407,6 +7428,15 @@
Binder.restoreCallingIdentity(identity);
}
+ boolean hasMixAffectingUsage(int usage) {
+ for (AudioMix mix : mMixes) {
+ if (mix.isAffectingUsage(usage)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void addMixes(@NonNull ArrayList<AudioMix> mixes) {
// TODO optimize to not have to unregister the mixes already in place
synchronized (mMixes) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
index 5af19ec..6919282 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
@@ -23,6 +23,8 @@
import android.hardware.broadcastradio.V2_0.Announcement;
import android.hardware.broadcastradio.V2_0.DabTableEntry;
import android.hardware.broadcastradio.V2_0.IdentifierType;
+import android.hardware.broadcastradio.V2_0.Metadata;
+import android.hardware.broadcastradio.V2_0.MetadataKey;
import android.hardware.broadcastradio.V2_0.ProgramFilter;
import android.hardware.broadcastradio.V2_0.ProgramIdentifier;
import android.hardware.broadcastradio.V2_0.ProgramInfo;
@@ -34,6 +36,7 @@
import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
+import android.hardware.radio.RadioMetadata;
import android.os.ParcelableException;
import android.util.Slog;
@@ -283,6 +286,77 @@
secondaryIds, null);
}
+ private enum MetadataType {
+ INT, STRING
+ }
+
+ private static class MetadataDef {
+ private MetadataType type;
+ private String key;
+ private MetadataDef(MetadataType type, String key) {
+ this.type = type;
+ this.key = key;
+ }
+ }
+
+ private static final Map<Integer, MetadataDef> metadataKeys;
+ static {
+ metadataKeys = new HashMap<>();
+ metadataKeys.put(MetadataKey.RDS_PS, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_RDS_PS));
+ metadataKeys.put(MetadataKey.RDS_PTY, new MetadataDef(
+ MetadataType.INT, RadioMetadata.METADATA_KEY_RDS_PTY));
+ metadataKeys.put(MetadataKey.RBDS_PTY, new MetadataDef(
+ MetadataType.INT, RadioMetadata.METADATA_KEY_RBDS_PTY));
+ metadataKeys.put(MetadataKey.RDS_RT, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_RDS_RT));
+ metadataKeys.put(MetadataKey.SONG_TITLE, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_TITLE));
+ metadataKeys.put(MetadataKey.SONG_ARTIST, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_ARTIST));
+ metadataKeys.put(MetadataKey.SONG_ALBUM, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_ALBUM));
+ metadataKeys.put(MetadataKey.STATION_ICON, new MetadataDef(
+ MetadataType.INT, RadioMetadata.METADATA_KEY_ICON));
+ metadataKeys.put(MetadataKey.ALBUM_ART, new MetadataDef(
+ MetadataType.INT, RadioMetadata.METADATA_KEY_ART));
+ metadataKeys.put(MetadataKey.PROGRAM_NAME, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_PROGRAM_NAME));
+ metadataKeys.put(MetadataKey.DAB_ENSEMBLE_NAME, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_ENSEMBLE_NAME));
+ metadataKeys.put(MetadataKey.DAB_ENSEMBLE_NAME_SHORT, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT));
+ metadataKeys.put(MetadataKey.DAB_SERVICE_NAME, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_SERVICE_NAME));
+ metadataKeys.put(MetadataKey.DAB_SERVICE_NAME_SHORT, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_SERVICE_NAME_SHORT));
+ metadataKeys.put(MetadataKey.DAB_COMPONENT_NAME, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_COMPONENT_NAME));
+ metadataKeys.put(MetadataKey.DAB_COMPONENT_NAME_SHORT, new MetadataDef(
+ MetadataType.STRING, RadioMetadata.METADATA_KEY_DAB_COMPONENT_NAME_SHORT));
+ }
+
+ private static @NonNull RadioMetadata metadataFromHal(@NonNull ArrayList<Metadata> meta) {
+ RadioMetadata.Builder builder = new RadioMetadata.Builder();
+
+ for (Metadata entry : meta) {
+ MetadataDef keyDef = metadataKeys.get(entry.key);
+ if (keyDef == null) {
+ Slog.i(TAG, "Ignored unknown metadata entry: " + MetadataKey.toString(entry.key));
+ continue;
+ }
+ if (keyDef.type == MetadataType.STRING) {
+ builder.putString(keyDef.key, entry.stringValue);
+ } else { // MetadataType.INT
+ /* Current java API use 32-bit values for int metadata,
+ * but we might change it in the future */
+ builder.putInt(keyDef.key, (int)entry.intValue);
+ }
+ }
+
+ return builder.build();
+ }
+
static @NonNull RadioManager.ProgramInfo programInfoFromHal(@NonNull ProgramInfo info) {
Collection<ProgramSelector.Identifier> relatedContent = info.relatedContent.stream().
map(id -> Objects.requireNonNull(programIdentifierFromHal(id))).
@@ -295,7 +369,7 @@
relatedContent,
info.infoFlags,
info.signalQuality,
- null, // TODO(b/69860743): metadata
+ metadataFromHal(info.metadata),
vendorInfoFromHal(info.vendorInfo)
);
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index df60c66..cabccf3 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -333,8 +333,16 @@
try {
final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack();
- builder.setUserId(focusedStack.userId);
- builder.setPackageName(focusedStack.topActivity.getPackageName());
+ if (focusedStack != null && focusedStack.topActivity != null) {
+ builder.setUserId(focusedStack.userId);
+ builder.setPackageName(focusedStack.topActivity.getPackageName());
+ } else {
+ // Ignore the event because we can't determine user / package.
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring event due to null focusedStack.");
+ }
+ return;
+ }
} catch (RemoteException e) {
// Really shouldn't be possible.
return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a572cdf..468ec59 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2098,7 +2098,6 @@
private static final String[] VALID_SETTINGS = new String[] {
LockPatternUtils.LOCKOUT_PERMANENT_KEY,
- LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
LockPatternUtils.PASSWORD_TYPE_KEY,
LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f12795b..fdba99e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2980,6 +2980,9 @@
}
}
}
+ // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
+ // SELinux domain.
+ setting.fixSeInfoLocked();
}
// Now that we know all the packages we are keeping,
@@ -10376,20 +10379,24 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
- // SELinux sandboxes become more restrictive as targetSdkVersion increases.
- // To ensure that apps with sharedUserId are placed in the same selinux domain
- // without breaking any assumptions about access, put them into the least
- // restrictive targetSdkVersion=25 domain.
- // TODO(b/72290969): Base this on the actual targetSdkVersion(s) of the apps within the
- // sharedUserSetting, instead of defaulting to the least restrictive domain.
- final int targetSdk = (sharedUserSetting != null) ? 25
- : pkg.applicationInfo.targetSdkVersion;
+ // Apps which share a sharedUserId must be placed in the same selinux domain. If this
+ // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
+ // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
+ // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
+ // least restrictive selinux domain.
+ // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
+ // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
+ // ensures that all packages continue to run in the same selinux domain.
+ final int targetSdkVersion =
+ ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ?
+ sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion;
// TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
// They currently can be if the sharedUser apps are signed with the platform key.
final boolean isPrivileged = (sharedUserSetting != null) ?
sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
- SELinuxMMAC.assignSeInfoValue(pkg, isPrivileged, targetSdk);
+ pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+ pkg.applicationInfo.targetSandboxVersion, targetSdkVersion);
pkg.mExtras = pkgSetting;
pkg.applicationInfo.processName = fixProcessName(
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index a9f1528..b47d966 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -64,6 +64,8 @@
/** Required MAC permissions files */
private static List<File> sMacPermissions = new ArrayList<>();
+ private static final String DEFAULT_SEINFO = "default";
+
// Append privapp to existing seinfo label
private static final String PRIVILEGED_APP_STR = ":privapp";
@@ -307,45 +309,56 @@
}
/**
- * Applies a security label to a package based on an seinfo tag taken from a matched
- * policy. All signature based policy stanzas are consulted and, if no match is
- * found, the default seinfo label of 'default' (set in ApplicationInfo object) is
- * used. The security label is attached to the ApplicationInfo instance of the package
- * in the event that a matching policy was found.
+ * Selects a security label to a package based on input parameters and the seinfo tag taken
+ * from a matched policy. All signature based policy stanzas are consulted and, if no match
+ * is found, the default seinfo label of 'default' is used. The security label is attached to
+ * the ApplicationInfo instance of the package.
*
* @param pkg object representing the package to be labeled.
+ * @param isPrivileged boolean.
+ * @param targetSandboxVersion int.
+ * @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the
+ * greater of: lowest targetSdk for all pkgs in the sharedUser, or
+ * MINIMUM_TARGETSDKVERSION.
+ * @return String representing the resulting seinfo.
*/
- public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged,
- int targetSdkVersion) {
+ public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged,
+ int targetSandboxVersion, int targetSdkVersion) {
+ String seInfo = null;
synchronized (sPolicies) {
if (!sPolicyRead) {
if (DEBUG_POLICY) {
Slog.d(TAG, "Policy not read");
}
- return;
- }
- for (Policy policy : sPolicies) {
- String seInfo = policy.getMatchedSeInfo(pkg);
- if (seInfo != null) {
- pkg.applicationInfo.seInfo = seInfo;
- break;
+ } else {
+ for (Policy policy : sPolicies) {
+ seInfo = policy.getMatchedSeInfo(pkg);
+ if (seInfo != null) {
+ break;
+ }
}
}
}
- if (pkg.applicationInfo.targetSandboxVersion == 2)
- pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
-
- if (isPrivileged) {
- pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
+ if (seInfo == null) {
+ seInfo = DEFAULT_SEINFO;
}
- pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
+ if (targetSandboxVersion == 2) {
+ seInfo += SANDBOX_V2_STR;
+ }
+
+ if (isPrivileged) {
+ seInfo += PRIVILEGED_APP_STR;
+ }
+
+ seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
if (DEBUG_POLICY_INSTALL) {
Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
- "seinfo=" + pkg.applicationInfo.seInfo);
+ "seinfo=" + seInfo);
}
+ return seInfo;
}
}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index ed396c3..054f614 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -39,6 +39,10 @@
int uidFlags;
int uidPrivateFlags;
+ // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so
+ // that all apps within the sharedUser run in the same selinux context.
+ int seInfoTargetSdkVersion;
+
final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>();
final PackageSignatures signatures = new PackageSignatures();
@@ -84,6 +88,11 @@
}
void addPackage(PackageSetting packageSetting) {
+ // If this is the first package added to this shared user, temporarily (until next boot) use
+ // its targetSdkVersion when assigning seInfo for the shared user.
+ if ((packages.size() == 0) && (packageSetting.pkg != null)) {
+ seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion;
+ }
if (packages.add(packageSetting)) {
setFlags(this.pkgFlags | packageSetting.pkgFlags);
setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
@@ -107,4 +116,26 @@
public boolean isPrivileged() {
return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
}
+
+ /**
+ * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
+ * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
+ * targetSdkVersion of all apps within the shared user, which corresponds to the least
+ * restrictive selinux domain.
+ */
+ public void fixSeInfoLocked() {
+ final List<PackageParser.Package> pkgList = getPackages();
+
+ for (PackageParser.Package pkg : pkgList) {
+ if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) {
+ seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+ }
+ }
+ for (PackageParser.Package pkg : pkgList) {
+ final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
+ pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+ pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion);
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ab0779b..8bc9830 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4389,13 +4389,13 @@
@Override
// TODO: Should probably be moved into DisplayFrames.
- public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
- DisplayFrames displayFrames, Rect outContentInsets, Rect outStableInsets,
+ public boolean getLayoutHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
+ DisplayFrames displayFrames, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout) {
final int fl = PolicyControl.getWindowFlags(null, attrs);
final int pfl = attrs.privateFlags;
- final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
- final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
+ final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
+ final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
final int displayRotation = displayFrames.mRotation;
final int displayWidth = displayFrames.mDisplayWidth;
final int displayHeight = displayFrames.mDisplayHeight;
@@ -4416,21 +4416,20 @@
}
}
- final boolean layoutInScreenAndInsetDecor =
- (fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
- == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR);
+ final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
+ final boolean layoutInScreenAndInsetDecor = layoutInScreen &&
+ (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
if (layoutInScreenAndInsetDecor && !screenDecor) {
- Rect frame;
int availRight, availBottom;
if (canHideNavigationBar() &&
- (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
- frame = displayFrames.mUnrestricted;
+ (sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+ outFrame.set(displayFrames.mUnrestricted);
availRight = displayFrames.mUnrestricted.right;
availBottom = displayFrames.mUnrestricted.bottom;
} else {
- frame = displayFrames.mRestricted;
+ outFrame.set(displayFrames.mRestricted);
availRight = displayFrames.mRestricted.right;
availBottom = displayFrames.mRestricted.bottom;
}
@@ -4438,7 +4437,7 @@
availRight - displayFrames.mStable.right,
availBottom - displayFrames.mStable.bottom);
- if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
if ((fl & FLAG_FULLSCREEN) != 0) {
outContentInsets.set(displayFrames.mStableFullscreen.left,
displayFrames.mStableFullscreen.top,
@@ -4460,14 +4459,25 @@
displayWidth, displayHeight);
calculateRelevantTaskInsets(taskBounds, outStableInsets,
displayWidth, displayHeight);
+ outFrame.intersect(taskBounds);
}
- outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(frame));
+ outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame));
+ return mForceShowSystemBars;
+ } else {
+ if (layoutInScreen) {
+ outFrame.set(displayFrames.mUnrestricted);
+ } else {
+ outFrame.set(displayFrames.mStable);
+ }
+ if (taskBounds != null) {
+ outFrame.intersect(taskBounds);
+ }
+
+ outContentInsets.setEmpty();
+ outStableInsets.setEmpty();
+ outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
return mForceShowSystemBars;
}
- outContentInsets.setEmpty();
- outStableInsets.setEmpty();
- outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
- return mForceShowSystemBars;
}
/**
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index ab331a5..d5c12f7 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1145,13 +1145,14 @@
/**
- * Return the insets for the areas covered by system windows. These values are computed on the
+ * Return the layout hints for a newly added window. These values are computed on the
* most recent layout, so they are not guaranteed to be correct.
*
* @param attrs The LayoutParams of the window.
* @param taskBounds The bounds of the task this window is on or {@code null} if no task is
* associated with the window.
* @param displayFrames display frames.
+ * @param outFrame The frame of the window.
* @param outContentInsets The areas covered by system windows, expressed as positive insets.
* @param outStableInsets The areas covered by stable system windows irrespective of their
* current visibility. Expressed as positive insets.
@@ -1160,9 +1161,10 @@
* @return Whether to always consume the navigation bar.
* See {@link #isNavBarForcedShownLw(WindowState)}.
*/
- default boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
- DisplayFrames displayFrames, Rect outContentInsets, Rect outStableInsets,
- Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout) {
+ default boolean getLayoutHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
+ DisplayFrames displayFrames, Rect outFrame, Rect outContentInsets,
+ Rect outStableInsets, Rect outOutsets,
+ DisplayCutout.ParcelableWrapper outDisplayCutout) {
return false;
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 6e017cd..64a2570 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -61,12 +61,17 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.os.KernelCpuSpeedReader;
+import com.android.internal.os.KernelUidCpuTimeReader;
+import com.android.internal.os.KernelUidCpuClusterTimeReader;
+import com.android.internal.os.KernelUidCpuActiveTimeReader;
+import com.android.internal.os.KernelUidCpuFreqTimeReader;
import com.android.internal.os.KernelWakelockReader;
import com.android.internal.os.KernelWakelockStats;
import com.android.internal.os.PowerProfile;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -106,7 +111,6 @@
private final ShutdownEventReceiver mShutdownEventReceiver;
private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
- private final KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
private IWifiManager mWifiManager = null;
private TelephonyManager mTelephony = null;
private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
@@ -115,6 +119,15 @@
private final StatFs mStatFsTemp =
new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
+ private KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
+ private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
+ private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
+ new KernelUidCpuFreqTimeReader();
+ private KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
+ new KernelUidCpuActiveTimeReader();
+ private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
+ new KernelUidCpuClusterTimeReader();
+
public StatsCompanionService(Context context) {
super();
mContext = context;
@@ -159,6 +172,13 @@
numSpeedSteps);
firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
}
+ // use default throttling in
+ // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
+ mKernelUidCpuFreqTimeReader.setThrottleInterval(0);
+ long[] freqs = mKernelUidCpuFreqTimeReader.readFreqs(powerProfile);
+ mKernelUidCpuFreqTimeReader.setReadBinary(true);
+ mKernelUidCpuClusterTimeReader.setThrottleInterval(0);
+ mKernelUidCpuActiveTimeReader.setThrottleInterval(0);
}
@Override
@@ -676,6 +696,53 @@
}
}
+ private void pullKernelUidCpuTime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ mKernelUidCpuTimeReader.readAbsolute((uid, userTimeUs, systemTimeUs) -> {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
+ e.writeInt(uid);
+ e.writeLong(userTimeUs);
+ e.writeLong(systemTimeUs);
+ pulledData.add(e);
+ });
+ }
+
+ private void pullKernelUidCpuFreqTime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ mKernelUidCpuFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
+ for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
+ e.writeInt(uid);
+ e.writeInt(freqIndex);
+ e.writeLong(cpuFreqTimeMs[freqIndex]);
+ pulledData.add(e);
+ }
+ });
+ }
+
+ private void pullKernelUidCpuClusterTime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ mKernelUidCpuClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
+ for (int i = 0; i < cpuClusterTimesMs.length; i++) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
+ e.writeInt(uid);
+ e.writeInt(i);
+ e.writeLong(cpuClusterTimesMs[i]);
+ pulledData.add(e);
+ }
+ });
+ }
+
+ private void pullKernelUidCpuActiveTime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ mKernelUidCpuActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 2);
+ e.writeInt(uid);
+ e.writeLong((long)cpuActiveTimesMs);
+ pulledData.add(e);
+ });
+ }
+
private void pullWifiActivityEnergyInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
if (mWifiManager == null) {
@@ -828,6 +895,22 @@
pullCpuTimePerFreq(tagId, ret);
break;
}
+ case StatsLog.CPU_TIME_PER_UID: {
+ pullKernelUidCpuTime(tagId, ret);
+ break;
+ }
+ case StatsLog.CPU_TIME_PER_UID_FREQ: {
+ pullKernelUidCpuFreqTime(tagId, ret);
+ break;
+ }
+ case StatsLog.CPU_CLUSTER_TIME: {
+ pullKernelUidCpuClusterTime(tagId, ret);
+ break;
+ }
+ case StatsLog.CPU_ACTIVE_TIME: {
+ pullKernelUidCpuActiveTime(tagId, ret);
+ break;
+ }
case StatsLog.WIFI_ACTIVITY_ENERGY_INFO: {
pullWifiActivityEnergyInfo(tagId, ret);
break;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c04522e..2672337 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1728,6 +1728,8 @@
frame.set(win.mContainingFrame);
}
surfaceInsets = win.getAttrs().surfaceInsets;
+ // XXX(b/72757033): These are insets relative to the window frame, but we're really
+ // interested in the insets relative to the frame we chose in the if-blocks above.
insets.set(win.mContentInsets);
stableInsets.set(win.mStableInsets);
}
@@ -2120,4 +2122,12 @@
}
return stringName + ((mIsExiting) ? " mIsExiting=" : "");
}
+
+ Rect getLetterboxInsets() {
+ if (mLetterbox != null) {
+ return mLetterbox.getInsets();
+ } else {
+ return new Rect();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 8fa79ab..0f9735d 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -68,6 +68,17 @@
}
/**
+ * Gets the insets between the outer and inner rects.
+ */
+ public Rect getInsets() {
+ return new Rect(
+ mLeft.getWidth(),
+ mTop.getHeight(),
+ mRight.getWidth(),
+ mBottom.getHeight());
+ }
+
+ /**
* Hides the letterbox.
*
* @param t a transaction in which to hide the letterbox
@@ -141,5 +152,13 @@
mSurface = null;
}
}
+
+ public int getWidth() {
+ return Math.max(0, mLastRight - mLastLeft);
+ }
+
+ public int getHeight() {
+ return Math.max(0, mLastBottom - mLastTop);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 94b8518..662d51d 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -193,16 +193,16 @@
int viewVisibility, Rect outContentInsets, Rect outStableInsets,
InputChannel outInputChannel) {
return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
- outContentInsets, outStableInsets, null /* outOutsets */, null /* cutout */,
- outInputChannel);
+ new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
+ null /* cutout */, outInputChannel);
}
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
- Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout,
- InputChannel outInputChannel) {
- return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
+ int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
+ Rect outStableInsets, Rect outOutsets,
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+ return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
@@ -217,7 +217,8 @@
public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
- outContentInsets, outStableInsets, null /* outOutsets */, null /* cutout */, null);
+ new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
+ null /* cutout */, null /* outInputChannel */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 3d7b32c..a5a1ca5 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -281,17 +281,25 @@
}
private Rect getInsetsFromTaskBounds(WindowState state, Task task) {
- final Rect r = new Rect();
- r.set(state.getContentFrameLw());
- r.intersectUnchecked(state.getStableFrameLw());
+ // XXX(b/72757033): These are insets relative to the window frame, but we're really
+ // interested in the insets relative to the task bounds.
+ Rect insets = minRect(state.mContentInsets, state.mStableInsets);
+ insets = maxRect(insets, state.mAppToken.getLetterboxInsets());
+ return insets;
+ }
- final Rect taskBounds = task.getBounds();
+ private Rect minRect(Rect rect1, Rect rect2) {
+ return new Rect(Math.min(rect1.left, rect2.left),
+ Math.min(rect1.top, rect2.top),
+ Math.min(rect1.right, rect2.right),
+ Math.min(rect1.bottom, rect2.bottom));
+ }
- r.set(Math.max(0, r.left - taskBounds.left),
- Math.max(0, r.top - taskBounds.top),
- Math.max(0, taskBounds.right - r.right),
- Math.max(0, taskBounds.bottom - r.bottom));
- return r;
+ private Rect maxRect(Rect rect1, Rect rect2) {
+ return new Rect(Math.max(rect1.left, rect2.left),
+ Math.max(rect1.top, rect2.top),
+ Math.max(rect1.right, rect2.right),
+ Math.max(rect1.bottom, rect2.bottom));
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index e4db3b0..a9e53a1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -198,7 +198,7 @@
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
- View.GONE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
+ View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
tmpRect, tmpCutout, null);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bdd64d5..2041c6f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1104,7 +1104,7 @@
}
public int addWindow(Session session, IWindow client, int seq,
- LayoutParams attrs, int viewVisibility, int displayId,
+ LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
int[] appOp = new int[1];
@@ -1445,8 +1445,8 @@
} else {
taskBounds = null;
}
- if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayFrames, outContentInsets,
- outStableInsets, outOutsets, outDisplayCutout)) {
+ if (mPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, outFrame,
+ outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6259926..165aaac 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -261,6 +261,8 @@
private boolean mOnlyCore;
private boolean mFirstBoot;
private final boolean mRuntimeRestart;
+ private final long mRuntimeStartElapsedTime;
+ private final long mRuntimeStartUptime;
private static final String START_SENSOR_SERVICE = "StartSensorService";
private static final String START_HIDL_SERVICES = "StartHidlServices";
@@ -292,6 +294,9 @@
mFactoryTestMode = FactoryTest.getMode();
// Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
+
+ mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
+ mRuntimeStartUptime = SystemClock.uptimeMillis();
}
private void run() {
@@ -402,7 +407,8 @@
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
- mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
+ mSystemServiceManager.setStartInfo(mRuntimeRestart,
+ mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 32a29a2..d60623d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -486,4 +486,45 @@
verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
eq(r.appToken), any(DestroyActivityItem.class));
}
+
+ @Test
+ public void testFinishDisabledPackageActivities() throws Exception {
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
+
+ // Making the second activity a task overlay without an app means it will be removed from
+ // the task's activities as well once first activity is removed.
+ secondActivity.mTaskOverlay = true;
+ secondActivity.app = null;
+
+ assertEquals(mTask.mActivities.size(), 2);
+
+ mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName, null,
+ true /* doit */, true /* evenPersistent */, UserHandle.USER_ALL);
+
+ assertTrue(mTask.mActivities.isEmpty());
+ assertTrue(mStack.getAllTasks().isEmpty());
+ }
+
+ @Test
+ public void testHandleAppDied() throws Exception {
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
+
+ // Making the first activity a task overlay means it will be removed from the task's
+ // activities as well once second activity is removed as handleAppDied processes the
+ // activity list in reverse.
+ firstActivity.mTaskOverlay = true;
+ firstActivity.app = null;
+
+ // second activity will be immediately removed as it has no state.
+ secondActivity.haveState = false;
+
+ assertEquals(mTask.mActivities.size(), 2);
+
+ mStack.handleAppDiedLocked(secondActivity.app);
+
+ assertTrue(mTask.mActivities.isEmpty());
+ assertTrue(mStack.getAllTasks().isEmpty());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index b58c700..fdabfb4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -197,11 +197,6 @@
final ActivityInfo aInfo = containsConditions(preconditions, PRECONDITION_NO_ACTIVITY_INFO)
? null : new ActivityInfo();
- if (aInfo != null) {
- aInfo.applicationInfo = new ApplicationInfo();
- aInfo.applicationInfo.packageName = ActivityBuilder.DEFAULT_PACKAGE;
- }
-
IVoiceInteractionSession voiceSession =
containsConditions(preconditions, PRECONDITION_SOURCE_VOICE_SESSION)
? mock(IVoiceInteractionSession.class) : null;
@@ -210,6 +205,11 @@
final ActivityBuilder builder = new ActivityBuilder(service).setTask(
new TaskBuilder(service.mStackSupervisor).setVoiceSession(voiceSession).build());
+ if (aInfo != null) {
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = builder.getDefaultComponentPackageName();
+ }
+
// Offset uid by one from {@link ActivityInfo} to simulate different uids.
if (containsConditions(preconditions, PRECONDITION_DIFFERENT_UID)) {
builder.setUid(aInfo.applicationInfo.uid + 1);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index ff7b1d0..1195188 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -67,6 +67,12 @@
private final Context mContext = InstrumentationRegistry.getContext();
private HandlerThread mHandlerThread;
+ // Default package name
+ static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
+
+ // Default base activity name
+ private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity";
+
@Before
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
@@ -106,11 +112,7 @@
// An id appended to the end of the component name to make it unique
private static int sCurrentActivityId = 0;
- // Default package name
- static final String DEFAULT_PACKAGE = "com.foo";
- // Default base activity name
- private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
private final ActivityManagerService mService;
@@ -149,11 +151,15 @@
return this;
}
+ String getDefaultComponentPackageName() {
+ return DEFAULT_COMPONENT_PACKAGE_NAME;
+ }
+
ActivityRecord build() {
if (mComponent == null) {
final int id = sCurrentActivityId++;
- mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
- DEFAULT_BASE_ACTIVITY_NAME + id);
+ mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
+ DEFAULT_COMPONENT_CLASS_NAME + id);
}
if (mCreateTask) {
@@ -191,6 +197,9 @@
* Builder for creating new tasks.
*/
protected static class TaskBuilder {
+ // Default package name
+ static final String DEFAULT_PACKAGE = "com.bar";
+
private final ActivityStackSupervisor mSupervisor;
private ComponentName mComponent;
@@ -252,6 +261,11 @@
aInfo.applicationInfo.packageName = mPackage;
Intent intent = new Intent();
+ if (mComponent == null) {
+ mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
+ DEFAULT_COMPONENT_CLASS_NAME);
+ }
+
intent.setComponent(mComponent);
intent.setFlags(mFlags);
@@ -312,6 +326,8 @@
doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean());
// Do not schedule idle timeouts
doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
+ // unit test version does not handle launch wake lock
+ doNothing().when(supervisor).acquireLaunchWakelock();
supervisor.initialize();
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
index c6800be..b6be3a4 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
@@ -31,6 +31,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@@ -278,22 +279,70 @@
}
@Test
- public void insetHint_screenDecorWindow() {
+ public void layoutHint_screenDecorWindow() {
addDisplayCutout();
mAppWindow.attrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR;
mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ final Rect frame = new Rect();
final Rect content = new Rect();
final Rect stable = new Rect();
final Rect outsets = new Rect();
final DisplayCutout.ParcelableWrapper cutout = new DisplayCutout.ParcelableWrapper();
- mPolicy.getInsetHintLw(mAppWindow.attrs, null /* taskBounds */, mFrames, content,
+ mPolicy.getLayoutHintLw(mAppWindow.attrs, null /* taskBounds */, mFrames, frame, content,
stable, outsets, cutout);
+ assertThat(frame, equalTo(mFrames.mUnrestricted));
assertThat(content, equalTo(new Rect()));
assertThat(stable, equalTo(new Rect()));
assertThat(outsets, equalTo(new Rect()));
assertThat(cutout.get(), equalTo(DisplayCutout.NO_CUTOUT));
}
+
+ @Test
+ public void layoutHint_appWindow() {
+ // Initialize DisplayFrames
+ mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+
+ final Rect outFrame = new Rect();
+ final Rect outContentInsets = new Rect();
+ final Rect outStableInsets = new Rect();
+ final Rect outOutsets = new Rect();
+ final DisplayCutout.ParcelableWrapper outDisplayCutout =
+ new DisplayCutout.ParcelableWrapper();
+
+ mPolicy.getLayoutHintLw(mAppWindow.attrs, null, mFrames, outFrame, outContentInsets,
+ outStableInsets, outOutsets, outDisplayCutout);
+
+ assertThat(outFrame, is(mFrames.mUnrestricted));
+ assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT)));
+ assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT)));
+ assertThat(outOutsets, is(new Rect()));
+ assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+ }
+
+ @Test
+ public void layoutHint_appWindowInTask() {
+ // Initialize DisplayFrames
+ mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+
+ final Rect taskBounds = new Rect(100, 100, 200, 200);
+
+ final Rect outFrame = new Rect();
+ final Rect outContentInsets = new Rect();
+ final Rect outStableInsets = new Rect();
+ final Rect outOutsets = new Rect();
+ final DisplayCutout.ParcelableWrapper outDisplayCutout =
+ new DisplayCutout.ParcelableWrapper();
+
+ mPolicy.getLayoutHintLw(mAppWindow.attrs, taskBounds, mFrames, outFrame, outContentInsets,
+ outStableInsets, outOutsets, outDisplayCutout);
+
+ assertThat(outFrame, is(taskBounds));
+ assertThat(outContentInsets, is(new Rect()));
+ assertThat(outStableInsets, is(new Rect()));
+ assertThat(outOutsets, is(new Rect()));
+ assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+ }
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f0c120b..d43db32 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1856,6 +1856,33 @@
public static final String KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
= "carrier_network_service_wwan_package_override_string";
+ /**
+ * A list of 4 LTE RSCP thresholds above which a signal level is considered POOR,
+ * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+ *
+ * Note that the min and max thresholds are fixed at -120 and -24, as set in 3GPP TS 27.007
+ * section 8.69.
+ * <p>
+ * See SignalStrength#MAX_WCDMA_RSCP and SignalStrength#MIN_WDCMA_RSCP. Any signal level outside
+ * these boundaries is considered invalid.
+ * @hide
+ */
+ public static final String KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY =
+ "wcdma_rscp_thresholds_int_array";
+
+ /**
+ * The default measurement to use for signal strength reporting. If this is not specified, the
+ * RSSI is used.
+ * <p>
+ * e.g.) To use RSCP by default, set the value to "rscp". The signal strength level will
+ * then be determined by #KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY
+ * <p>
+ * Currently this only supports the value "rscp"
+ * @hide
+ */
+ public static final String KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING =
+ "wcdma_default_signal_strength_measurement_string";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2161,6 +2188,14 @@
-108, /* SIGNAL_STRENGTH_GOOD */
-98, /* SIGNAL_STRENGTH_GREAT */
});
+ sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -115, /* SIGNAL_STRENGTH_POOR */
+ -105, /* SIGNAL_STRENGTH_MODERATE */
+ -95, /* SIGNAL_STRENGTH_GOOD */
+ -85 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
}
/**
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 5ed5afe..ea2b0ae 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Objects;
/**
* Contains phone signal strength related information.
@@ -66,6 +67,13 @@
private static final int MAX_LTE_RSRP = -44;
private static final int MIN_LTE_RSRP = -140;
+ private static final int WCDMA_RSCP_THRESHOLDS_NUM = 4;
+ private static final int MAX_WCDMA_RSCP = -24;
+ private static final int MIN_WCDMA_RSCP = -120;
+
+ /* The type of signal measurement */
+ private static final String MEASUMENT_TYPE_RSCP = "rscp";
+
/** Parameters reported by the Radio */
private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
@@ -79,7 +87,10 @@
private int mLteRsrq;
private int mLteRssnr;
private int mLteCqi;
- private int mTdScdmaRscp;
+ private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
+ private int mWcdmaSignalStrength;
+ private int mWcdmaRscpAsu; // the WCDMA RSCP in ASU as reported from the HAL
+ private int mWcdmaRscp; // the WCDMA RSCP in dBm
/** Parameters from the framework */
private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
@@ -92,6 +103,13 @@
// min and max are fixed at MIN_LTE_RSRP (-140) and MAX_LTE_RSRP (-44).
private int mLteRsrpThresholds[] = new int[LTE_RSRP_THRESHOLDS_NUM];
+ // The type of default measurement for determining the display level of WCDMA signal bar.
+ private String mWcdmaDefaultSignalMeasurement;
+
+ // The threshold of WCDMA RSCP for determining the display level of WCDMA signal bar. Note that
+ // the min and max are fixed at MIN_WCDMA_RSCP (-120) and MAX_WCDMA_RSCP (-24).
+ private int mWcdmaRscpThresholds[] = new int[WCDMA_RSCP_THRESHOLDS_NUM];
+
/**
* Create a new SignalStrength from a intent notifier Bundle
*
@@ -141,10 +159,14 @@
mLteRssnr = INVALID;
mLteCqi = INVALID;
mTdScdmaRscp = INVALID;
+ mWcdmaSignalStrength = 99;
+ mWcdmaRscp = INVALID;
mLteRsrpBoost = 0;
mIsGsm = gsmFlag;
mUseOnlyRsrpForLteLevel = false;
+ mWcdmaDefaultSignalMeasurement = "";
setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+ setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
}
/**
@@ -157,9 +179,10 @@
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
- int tdScdmaRscp,
+ int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscpAsu,
// values Added by config
- int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp) {
+ int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp,
+ String wcdmaDefaultMeasurement) {
mGsmSignalStrength = gsmSignalStrength;
mGsmBitErrorRate = gsmBitErrorRate;
mCdmaDbm = cdmaDbm;
@@ -173,15 +196,20 @@
mLteRssnr = lteRssnr;
mLteCqi = lteCqi;
mTdScdmaRscp = INVALID;
+ mWcdmaSignalStrength = wcdmaSignalStrength;
+ mWcdmaRscpAsu = wcdmaRscpAsu;
+ mWcdmaRscp = wcdmaRscpAsu - 120;
mLteRsrpBoost = lteRsrpBoost;
mIsGsm = gsmFlag;
mUseOnlyRsrpForLteLevel = lteLevelBaseOnRsrp;
+ mWcdmaDefaultSignalMeasurement = wcdmaDefaultMeasurement;
setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+ setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
if (DBG) log("initialize: " + toString());
}
/**
- * Constructor for only values provided by Radio HAL
+ * Constructor for only values provided by Radio HAL V1.0
*
* @hide
*/
@@ -192,7 +220,23 @@
int tdScdmaRscp) {
this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
- lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 0, true, false);
+ lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 99, INVALID, 0, true, false, "");
+ }
+
+ /**
+ * Constructor for only values provided by Radio HAL V1.2
+ *
+ * @hide
+ */
+ public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+ int cdmaDbm, int cdmaEcio,
+ int evdoDbm, int evdoEcio, int evdoSnr,
+ int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+ int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscp) {
+ this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+ evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+ lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, wcdmaSignalStrength, wcdmaRscp, 0, true,
+ false, "");
}
/**
@@ -223,10 +267,15 @@
mLteRssnr = s.mLteRssnr;
mLteCqi = s.mLteCqi;
mTdScdmaRscp = s.mTdScdmaRscp;
+ mWcdmaSignalStrength = s.mWcdmaSignalStrength;
+ mWcdmaRscpAsu = s.mWcdmaRscpAsu;
+ mWcdmaRscp = s.mWcdmaRscp;
mLteRsrpBoost = s.mLteRsrpBoost;
mIsGsm = s.mIsGsm;
mUseOnlyRsrpForLteLevel = s.mUseOnlyRsrpForLteLevel;
+ mWcdmaDefaultSignalMeasurement = s.mWcdmaDefaultSignalMeasurement;
setLteRsrpThresholds(s.mLteRsrpThresholds);
+ setWcdmaRscpThresholds(s.mWcdmaRscpThresholds);
}
/**
@@ -250,10 +299,15 @@
mLteRssnr = in.readInt();
mLteCqi = in.readInt();
mTdScdmaRscp = in.readInt();
+ mWcdmaSignalStrength = in.readInt();
+ mWcdmaRscpAsu = in.readInt();
+ mWcdmaRscp = in.readInt();
mLteRsrpBoost = in.readInt();
mIsGsm = in.readBoolean();
mUseOnlyRsrpForLteLevel = in.readBoolean();
+ mWcdmaDefaultSignalMeasurement = in.readString();
in.readIntArray(mLteRsrpThresholds);
+ in.readIntArray(mWcdmaRscpThresholds);
}
/**
@@ -273,10 +327,15 @@
out.writeInt(mLteRssnr);
out.writeInt(mLteCqi);
out.writeInt(mTdScdmaRscp);
+ out.writeInt(mWcdmaSignalStrength);
+ out.writeInt(mWcdmaRscpAsu);
+ out.writeInt(mWcdmaRscp);
out.writeInt(mLteRsrpBoost);
out.writeBoolean(mIsGsm);
out.writeBoolean(mUseOnlyRsrpForLteLevel);
+ out.writeString(mWcdmaDefaultSignalMeasurement);
out.writeIntArray(mLteRsrpThresholds);
+ out.writeIntArray(mWcdmaRscpThresholds);
}
/**
@@ -316,8 +375,18 @@
if (DBG) log("Signal before validate=" + this);
// TS 27.007 8.5
mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
+ mWcdmaSignalStrength = (mWcdmaSignalStrength >= 0) ? mWcdmaSignalStrength : 99;
+ mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
// BER no change;
+ // WCDMA RSCP valid values are -120 through -24 as defined in TS 27.007 8.69
+ // but are reported in ASU which is 0 through 96, so we do the conversion here
+ mWcdmaRscpAsu =
+ ((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
+ ? mWcdmaRscpAsu : INVALID;
+ mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
+ ? mWcdmaRscp : INVALID;
+
mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
mCdmaEcio = (mCdmaEcio >= 0) ? -mCdmaEcio : -160;
@@ -326,15 +395,14 @@
mEvdoSnr = ((mEvdoSnr >= 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
// TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
- mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
mLteRsrp = ((-mLteRsrp >= MIN_LTE_RSRP) && (-mLteRsrp <= MAX_LTE_RSRP)) ? -mLteRsrp
: SignalStrength.INVALID;
mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
: SignalStrength.INVALID;
- mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120))
- ? -mTdScdmaRscp : SignalStrength.INVALID;
+ mTdScdmaRscp = ((mTdScdmaRscp >= 0) && (mTdScdmaRscp <= 96))
+ ? (mTdScdmaRscp - 120) : SignalStrength.INVALID;
// Cqi no change
if (DBG) log("Signal after validate=" + this);
}
@@ -372,6 +440,16 @@
}
/**
+ * @param defaultMeasurement sets the type of WCDMA default signal measurement
+ *
+ * Used by phone to determine default measurement type for calculation WCDMA signal level.
+ * @hide
+ */
+ public void setWcdmaDefaultSignalMeasurement(String defaultMeasurement) {
+ mWcdmaDefaultSignalMeasurement = defaultMeasurement;
+ }
+
+ /**
* @param lteRsrpBoost - signal strength offset
*
* Used by phone to set the lte signal strength offset which will be
@@ -415,6 +493,23 @@
}
/**
+ * Sets the threshold array for determining the display level of WCDMA signal bar.
+ *
+ * @param wcdmaRscpThresholds int array for determining the display level.
+ *
+ * @hide
+ */
+ public void setWcdmaRscpThresholds(int[] wcdmaRscpThresholds) {
+ if ((wcdmaRscpThresholds == null)
+ || (wcdmaRscpThresholds.length != WCDMA_RSCP_THRESHOLDS_NUM)) {
+ Log.wtf(LOG_TAG, "setWcdmaRscpThresholds - wcdmaRscpThresholds is invalid.");
+ return;
+ }
+ System.arraycopy(wcdmaRscpThresholds, 0, mWcdmaRscpThresholds, 0,
+ WCDMA_RSCP_THRESHOLDS_NUM);
+ }
+
+ /**
* Get the CDMA RSSI value in dBm
*/
public int getCdmaDbm() {
@@ -505,6 +600,8 @@
asuLevel = getLteAsuLevel();
} else if (mTdScdmaRscp != SignalStrength.INVALID) {
asuLevel = getTdScdmaAsuLevel();
+ } else if (mWcdmaRscp != SignalStrength.INVALID) {
+ asuLevel = getWcdmaAsuLevel();
} else {
asuLevel = getGsmAsuLevel();
}
@@ -538,7 +635,11 @@
dBm = getLteDbm();
if (dBm == INVALID) {
if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
- dBm = getGsmDbm();
+ if (getWcdmaDbm() == INVALID) {
+ dBm = getGsmDbm();
+ } else {
+ dBm = getWcdmaDbm();
+ }
} else {
dBm = getTdScdmaDbm();
}
@@ -810,17 +911,21 @@
if (rsrpIconLevel != -1) return rsrpIconLevel;
/* Valid values are (0-63, 99) as defined in TS 36.331 */
+ // TODO the range here is probably supposed to be (0..31, 99). It's unclear if anyone relies
+ // on the current incorrect range check, so this will be fixed in a future release with more
+ // soak time
if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
- if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+ if (DBG) log("getLteLevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+ rssiIconLevel);
return rssiIconLevel;
}
+
/**
* Get the LTE signal level as an asu value between 0..97, 99 is unknown
* Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
@@ -913,6 +1018,105 @@
return tdScdmaAsuLevel;
}
+ /**
+ * Gets WCDMA RSCP as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+ *
+ * @hide
+ */
+ public int getWcdmaRscp() {
+ return mWcdmaRscp;
+ }
+
+ /**
+ * Get the WCDMA signal level as an ASU value between 0-96, 255 is unknown
+ *
+ * @hide
+ */
+ public int getWcdmaAsuLevel() {
+ /*
+ * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+ * 0 -120 dBm or less
+ * 1 -119 dBm
+ * 2...95 -118... -25 dBm
+ * 96 -24 dBm or greater
+ * 255 not known or not detectable
+ */
+ final int wcdmaDbm = getWcdmaDbm();
+ int wcdmaAsuLevel = 255;
+ // validateInput will always give a valid range between -120 to -24 as per ril.h. so RSCP
+ // outside range is already set to INVALID
+ if (wcdmaDbm == SignalStrength.INVALID) wcdmaAsuLevel = 255;
+ else wcdmaAsuLevel = wcdmaDbm + 120;
+ if (DBG) log("Wcdma Asu level: " + wcdmaAsuLevel);
+ return wcdmaAsuLevel;
+ }
+
+ /**
+ * Gets WCDMA signal strength as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+ *
+ * @hide
+ */
+ public int getWcdmaDbm() {
+ return mWcdmaRscp;
+ }
+
+ /**
+ * Get WCDMA as level 0..4
+ *
+ * @hide
+ */
+ public int getWcdmaLevel() {
+ int level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+ if (mWcdmaDefaultSignalMeasurement == null) {
+ Log.wtf(LOG_TAG, "getWcdmaLevel - WCDMA default signal measurement is invalid.");
+ return level;
+ }
+
+ switch (mWcdmaDefaultSignalMeasurement) {
+ case MEASUMENT_TYPE_RSCP:
+ // RSCP valid values are (-120 through -24) as defined in TS 27.007 8.69
+ if (mWcdmaRscp < MIN_WCDMA_RSCP || mWcdmaRscp > MAX_WCDMA_RSCP) {
+ if (mWcdmaRscp != INVALID) {
+ Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSCP: mWcdmaRscp="
+ + mWcdmaRscp);
+ }
+ } else if (mWcdmaRscp >= mWcdmaRscpThresholds[3]) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (mWcdmaRscp >= mWcdmaRscpThresholds[2]) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (mWcdmaRscp >= mWcdmaRscpThresholds[1]) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else if (mWcdmaRscp >= mWcdmaRscpThresholds[0]) {
+ level = SIGNAL_STRENGTH_POOR;
+ }
+ if (DBG) log("getWcdmaLevel=" + level + " WcdmaRscp=" + mWcdmaRscp);
+ break;
+
+ default:
+ // RSSI valid values are (0..31) as defined in TS 27.007 8.5
+ if (mWcdmaSignalStrength < 0 || mWcdmaSignalStrength > 31) {
+ if (mWcdmaSignalStrength != 99) {
+ Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSSI: mWcdmaSignalStrength="
+ + mWcdmaSignalStrength);
+ }
+ } else if (mWcdmaSignalStrength >= 18) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (mWcdmaSignalStrength >= 13) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (mWcdmaSignalStrength >= 8) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else if (mWcdmaSignalStrength >= 3) {
+ level = SIGNAL_STRENGTH_POOR;
+ }
+ if (DBG) log("getWcdmaLevel=" + level + " WcdmaSignalStrength=" +
+ mWcdmaSignalStrength);
+ break;
+
+ }
+ return level;
+ }
+
/**
* @return hash code
*/
@@ -925,8 +1129,11 @@
+ (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
+ (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
+ (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
- + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (mIsGsm ? 1 : 0)
- + (mUseOnlyRsrpForLteLevel ? 1 : 0) + (Arrays.hashCode(mLteRsrpThresholds)));
+ + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum)
+ + (mWcdmaSignalStrength * primeNum) + (mWcdmaRscpAsu * primeNum)
+ + (mWcdmaRscp * primeNum) + (mIsGsm ? 1 : 0) + (mUseOnlyRsrpForLteLevel ? 1 : 0)
+ + (Objects.hashCode(mWcdmaDefaultSignalMeasurement))
+ + (Arrays.hashCode(mLteRsrpThresholds)) + (Arrays.hashCode(mWcdmaRscpThresholds)));
}
/**
@@ -960,9 +1167,14 @@
&& mLteCqi == s.mLteCqi
&& mLteRsrpBoost == s.mLteRsrpBoost
&& mTdScdmaRscp == s.mTdScdmaRscp
+ && mWcdmaSignalStrength == s.mWcdmaSignalStrength
+ && mWcdmaRscpAsu == s.mWcdmaRscpAsu
+ && mWcdmaRscp == s.mWcdmaRscp
&& mIsGsm == s.mIsGsm
&& mUseOnlyRsrpForLteLevel == s.mUseOnlyRsrpForLteLevel
- && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds));
+ && Objects.equals(mWcdmaDefaultSignalMeasurement, s.mWcdmaDefaultSignalMeasurement)
+ && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds)
+ && Arrays.equals(mWcdmaRscpThresholds, s.mWcdmaRscpThresholds));
}
/**
@@ -985,10 +1197,15 @@
+ " " + mLteCqi
+ " " + mLteRsrpBoost
+ " " + mTdScdmaRscp
+ + " " + mWcdmaSignalStrength
+ + " " + mWcdmaRscpAsu
+ + " " + mWcdmaRscp
+ " " + (mIsGsm ? "gsm|lte" : "cdma")
+ " " + (mUseOnlyRsrpForLteLevel ? "use_only_rsrp_for_lte_level" :
"use_rsrp_and_rssnr_for_lte_level")
- + " " + (Arrays.toString(mLteRsrpThresholds)));
+ + " " + mWcdmaDefaultSignalMeasurement
+ + " " + (Arrays.toString(mLteRsrpThresholds))
+ + " " + (Arrays.toString(mWcdmaRscpThresholds)));
}
/** Returns the signal strength related to GSM. */
@@ -997,7 +1214,10 @@
if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
level = getTdScdmaLevel();
if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
- level = getGsmLevel();
+ level = getWcdmaLevel();
+ if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+ level = getGsmLevel();
+ }
}
}
return level;
@@ -1042,12 +1262,20 @@
mLteCqi = m.getInt("LteCqi");
mLteRsrpBoost = m.getInt("LteRsrpBoost");
mTdScdmaRscp = m.getInt("TdScdma");
+ mWcdmaSignalStrength = m.getInt("WcdmaSignalStrength");
+ mWcdmaRscpAsu = m.getInt("WcdmaRscpAsu");
+ mWcdmaRscp = m.getInt("WcdmaRscp");
mIsGsm = m.getBoolean("IsGsm");
mUseOnlyRsrpForLteLevel = m.getBoolean("UseOnlyRsrpForLteLevel");
+ mWcdmaDefaultSignalMeasurement = m.getString("WcdmaDefaultSignalMeasurement");
ArrayList<Integer> lteRsrpThresholds = m.getIntegerArrayList("lteRsrpThresholds");
for (int i = 0; i < lteRsrpThresholds.size(); i++) {
mLteRsrpThresholds[i] = lteRsrpThresholds.get(i);
}
+ ArrayList<Integer> wcdmaRscpThresholds = m.getIntegerArrayList("wcdmaRscpThresholds");
+ for (int i = 0; i < wcdmaRscpThresholds.size(); i++) {
+ mWcdmaRscpThresholds[i] = wcdmaRscpThresholds.get(i);
+ }
}
/**
@@ -1071,13 +1299,22 @@
m.putInt("LteCqi", mLteCqi);
m.putInt("LteRsrpBoost", mLteRsrpBoost);
m.putInt("TdScdma", mTdScdmaRscp);
+ m.putInt("WcdmaSignalStrength", mWcdmaSignalStrength);
+ m.putInt("WcdmaRscpAsu", mWcdmaRscpAsu);
+ m.putInt("WcdmaRscp", mWcdmaRscp);
m.putBoolean("IsGsm", mIsGsm);
m.putBoolean("UseOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
+ m.putString("WcdmaDefaultSignalMeasurement", mWcdmaDefaultSignalMeasurement);
ArrayList<Integer> lteRsrpThresholds = new ArrayList<Integer>();
for (int value : mLteRsrpThresholds) {
lteRsrpThresholds.add(value);
}
m.putIntegerArrayList("lteRsrpThresholds", lteRsrpThresholds);
+ ArrayList<Integer> wcdmaRscpThresholds = new ArrayList<Integer>();
+ for (int value : mWcdmaRscpThresholds) {
+ wcdmaRscpThresholds.add(value);
+ }
+ m.putIntegerArrayList("wcdmaRscpThresholds", wcdmaRscpThresholds);
}
/**
@@ -1091,6 +1328,16 @@
}
/**
+ * Gets the default threshold array for determining the display level of WCDMA signal bar.
+ *
+ * @return int array for determining the display level.
+ */
+ private int[] getDefaultWcdmaRscpThresholds() {
+ return CarrierConfigManager.getDefaultConfig().getIntArray(
+ CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
+ }
+
+ /**
* log
*/
private static void log(String s) {
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index e396a63..8219150 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -427,6 +427,8 @@
printf(" new GZipSection(%d,", field->number());
splitAndPrint(s.args());
printf(" NULL),\n");
+ case SECTION_TOMBSTONE:
+ printf(" new TombstoneSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
break;
}
}